foldkit-agent-webmcp 0.7.1 → 0.8.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/README.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Agent } from "foldkit-agent";
|
|
2
2
|
import { Attribute, HtmlBuilder } from "foldkit/html";
|
|
3
|
-
//#region src/webmcp.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* The slice of Chrome's experimental WebMCP Imperative API this adapter uses.
|
|
6
5
|
*
|
|
@@ -48,8 +47,6 @@ interface ModelContext {
|
|
|
48
47
|
* a server, or in a browser with neither.
|
|
49
48
|
*/
|
|
50
49
|
declare const pageModelContext: () => ModelContext | undefined;
|
|
51
|
-
//#endregion
|
|
52
|
-
//#region src/forms.d.ts
|
|
53
50
|
/**
|
|
54
51
|
* One capability drawn as a WebMCP declarative tool: a form whose `toolname`
|
|
55
52
|
* and `tooldescription`, and whose fields' `name` and `toolparamdescription`,
|
|
@@ -79,8 +76,6 @@ declare const formTool: <ByName extends Record<string, unknown>, const Name exte
|
|
|
79
76
|
}) => FormTool<Name, ByName[Name]>;
|
|
80
77
|
/** Whether this browser draws forms as tools: its `SubmitEvent` says when an agent submitted. */
|
|
81
78
|
declare const declarativeTools: () => boolean;
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region src/register.d.ts
|
|
84
79
|
/** A live WebMCP registration. */
|
|
85
80
|
interface Registration {
|
|
86
81
|
/** Re-reads availability from the current Model and reconciles registrations. */
|
|
@@ -139,6 +134,5 @@ declare const register: <Model, Context_, Principal, ByName, ByTag>(options: Reg
|
|
|
139
134
|
declare namespace agentWebMcp_d_exports {
|
|
140
135
|
export { FormTool, RegisterOptions, Registration, declarativeTools, formTool, pageModelContext, register };
|
|
141
136
|
}
|
|
142
|
-
//#endregion
|
|
143
137
|
export { agentWebMcp_d_exports as AgentWebMcp, type ModelContext, type RegisterToolOptions, type ToolDescriptor, type ToolExecutionContext, type ToolResult };
|
|
144
138
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/webmcp.ts","../src/forms.ts","../src/register.ts","../src/agentWebMcp.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/webmcp.ts","../src/forms.ts","../src/register.ts","../src/agentWebMcp.ts"],"mappings":";;;;;;;;;;UASiB;;WAEN,SAAS;;;UAIH;WACN,SAAS;aAAyB;aAAuB;;WACzD;;;UAIM;WACN;WACA;WACA,aAAa;WACb,UAAU,YAAY,SAAS,yBAAyB,QAAQ;;;;;;;;UAS1D;WACN,SAAS;;;UAIH;WACN,eACP,MAAM,gBACN,UAAU,+BACA;;;;;;;;cASD,wBAAuB;;;;;;;UCzCnB,SAAS,8BAA8B;WAC7C,MAAM;;WAEN,OAAO,SAAS,GAAG,YAAY,aAAa,cAAc,UAAU;;;;;WAKpE,QAAQ,SACf,WAAW,gBACX,GAAG,YAAY,aACZ,cAAc,UAAU;;WAEpB,MAAM;;;;;;;;cAkBJ,WACX,eAAe,+BACT,mBAAmB,iBAAe,YAE5B,MAAM,0BAA0B,cAAY,MAClD,MAAI;WACU;MACnB,SAAS,MAAM,OAAO;;cA0CZ;;UCrFI;;WAEN,eAAe;;WAEf;;WAEA,kBAAkB;;UAGZ,gBAAgB,OAAO,UAAU,WAAW,QAAQ;;WAE1D,OAAO,MAAM,aAAa,OAAO,UAAU,WAAW,QAAQ;;WAE9D,eAAe;;WAEf,SAAS;;;;;;WAMT;;WAEA;;;;;WAKA,YAAY;;;;;;WAMZ,QAAQ,cAAc,eAAe;;;;;;;;;;;;;;;;;;;;cAqBnC,WAAY,OAAO,UAAU,WAAW,QAAQ,OAAK,SACvD,gBAAgB,OAAO,UAAU,WAAW,QAAQ,WAC5D"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D8jQpDG7.mjs";
|
|
2
2
|
import { Agent } from "foldkit-agent";
|
|
3
3
|
import { Effect, Option } from "effect";
|
|
4
|
-
|
|
4
|
+
// src/forms.ts
|
|
5
5
|
/** The description a property of the input's JSON Schema carries, if any. */
|
|
6
6
|
const describedBy = (property) => typeof property === "object" && property !== null && "description" in property && typeof property.description === "string" ? Option.some(property.description) : Option.none();
|
|
7
7
|
/**
|
|
@@ -88,8 +88,7 @@ const dispatchFor = (agent, invocationId) => async (name, input, signal) => {
|
|
|
88
88
|
return textResult(`Capability "${name}" failed unexpectedly`, true);
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
|
-
|
|
92
|
-
//#region src/webmcp.ts
|
|
91
|
+
// src/webmcp.ts
|
|
93
92
|
/**
|
|
94
93
|
* The page's model context, when it has one: `document.modelContext`, where
|
|
95
94
|
* the spec puts it, or else `navigator.modelContext`, the name Chromium used
|
|
@@ -102,8 +101,7 @@ const pageModelContext = () => {
|
|
|
102
101
|
if (current !== void 0) return current;
|
|
103
102
|
return typeof navigator === "undefined" ? void 0 : navigator.modelContext;
|
|
104
103
|
};
|
|
105
|
-
|
|
106
|
-
//#region src/register.ts
|
|
104
|
+
// src/register.ts
|
|
107
105
|
/**
|
|
108
106
|
* Projects an agent contract into `document.modelContext.registerTool(...)`.
|
|
109
107
|
*
|
|
@@ -213,15 +211,13 @@ const register = (options) => {
|
|
|
213
211
|
registered: () => [...controllers.keys()]
|
|
214
212
|
};
|
|
215
213
|
};
|
|
216
|
-
|
|
217
|
-
//#region src/agentWebMcp.ts
|
|
214
|
+
// src/agentWebMcp.ts
|
|
218
215
|
var agentWebMcp_exports = /* @__PURE__ */ __exportAll({
|
|
219
216
|
declarativeTools: () => declarativeTools,
|
|
220
217
|
formTool: () => formTool,
|
|
221
218
|
pageModelContext: () => pageModelContext,
|
|
222
219
|
register: () => register
|
|
223
220
|
});
|
|
224
|
-
//#endregion
|
|
225
221
|
export { agentWebMcp_exports as AgentWebMcp };
|
|
226
222
|
|
|
227
223
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/forms.ts","../src/webmcp.ts","../src/register.ts","../src/agentWebMcp.ts"],"sourcesContent":["import { Agent } from 'foldkit-agent'\nimport { Effect, Option } from 'effect'\nimport type { Attribute, HtmlBuilder } from 'foldkit/html'\nimport type { ToolResult } from './webmcp.js'\n\n/**\n * One capability drawn as a WebMCP declarative tool: a form whose `toolname`\n * and `tooldescription`, and whose fields' `name` and `toolparamdescription`,\n * come from the agent contract, so the form and the registered tool cannot\n * disagree. `register({ forms })` answers its agent submissions.\n */\nexport interface FormTool<Name extends string = string, Input = unknown> {\n readonly name: Name\n /** The form's attributes: `toolname`, `tooldescription`, and `toolautosubmit` when asked. */\n readonly form: <Message>(h: HtmlBuilder<Message>) => ReadonlyArray<Attribute<Message>>\n /**\n * A field's attributes: `name`, the input's key, and `toolparamdescription`\n * when the input's Schema describes it.\n */\n readonly field: <Message>(\n key: keyof Input & string,\n h: HtmlBuilder<Message>,\n ) => ReadonlyArray<Attribute<Message>>\n /** The input's keys, which an agent's submission is read from. */\n readonly keys: ReadonlyArray<string>\n}\n\n/** The description a property of the input's JSON Schema carries, if any. */\nconst describedBy = (property: unknown): Option.Option<string> =>\n typeof property === 'object' &&\n property !== null &&\n 'description' in property &&\n typeof property.description === 'string'\n ? Option.some(property.description)\n : Option.none()\n\n/**\n * Draws the capability `name` of an agent contract as a declarative tool: see\n * the README's \"Forms as declarative tools\". It throws for a name the contract\n * does not expose, or whose input is not an object of fields, which no form\n * could fill.\n */\nexport const formTool = <\n ByName extends Record<string, unknown>,\n const Name extends keyof ByName & string,\n>(\n definition: Agent.Definition<any, any, any, ByName, any>,\n name: Name,\n options: { readonly autosubmit?: boolean } = {},\n): FormTool<Name, ByName[Name]> => {\n const descriptor = Agent.messages(definition).find(each => each.name === name)\n if (descriptor === undefined)\n throw new Error(`AgentWebMcp.formTool: the contract exposes no capability \"${name}\"`)\n const properties = descriptor.inputSchema['properties']\n if (\n descriptor.inputSchema['type'] !== 'object' ||\n typeof properties !== 'object' ||\n properties === null\n )\n throw new Error(\n `AgentWebMcp.formTool: \"${name}\" takes no object of fields, which no form can fill`,\n )\n const fields = new Map(\n Object.entries(properties).map(([key, property]) => [key, describedBy(property)] as const),\n )\n return {\n name,\n keys: [...fields.keys()],\n form: h => [\n h.Attribute('toolname', name),\n h.Attribute('tooldescription', descriptor.description),\n ...(options.autosubmit === true ? [h.Attribute('toolautosubmit', '')] : []),\n ],\n field: (key, h) => {\n const described = fields.get(key)\n if (described === undefined)\n throw new Error(`AgentWebMcp.formTool: \"${name}\" has no field \"${key}\"`)\n return [\n // An attribute, not `h.Name`, which Foldkit sets only in the browser:\n // a server-rendered form names its fields too.\n h.Attribute('name', key),\n ...Option.match(described, {\n onNone: () => [],\n onSome: description => [h.Attribute('toolparamdescription', description)],\n }),\n ]\n },\n }\n}\n\n/** Whether this browser draws forms as tools: its `SubmitEvent` says when an agent submitted. */\nexport const declarativeTools = (): boolean =>\n typeof SubmitEvent !== 'undefined' && 'agentInvoked' in SubmitEvent.prototype\n\n/**\n * Answers an agent's submission of a form tool on `root`: in the capture phase,\n * before the application's own submit handler, the form's fields named by the\n * input are dispatched as the capability through `dispatch`, and the result\n * goes back through `respondWith`. A person's submission is left alone.\n */\nexport const answerForms = (\n root: Document,\n forms: ReadonlyArray<FormTool>,\n dispatch: (name: string, input: unknown) => Promise<ToolResult>,\n): (() => void) => {\n const byName = new Map(forms.map(form => [form.name, form]))\n const onSubmit = (event: Event) => {\n // `agentInvoked` and `respondWith` are what a declarative WebMCP browser adds to the event.\n const form = event.target\n if (!('agentInvoked' in event) || event.agentInvoked !== true) return\n if (!(form instanceof HTMLFormElement) || !('respondWith' in event)) return\n const { respondWith } = event\n if (typeof respondWith !== 'function') return\n const tool = byName.get(form.getAttribute('toolname') ?? '')\n if (tool === undefined) return\n event.preventDefault()\n event.stopImmediatePropagation()\n // Text, as a form submits it; a field the input does not name is not read.\n const data = new FormData(form)\n const input: Record<string, string> = Object.create(null)\n for (const key of tool.keys) {\n const value = data.get(key)\n if (typeof value === 'string') input[key] = value\n }\n respondWith.call(event, dispatch(tool.name, input))\n }\n root.addEventListener('submit', onSubmit, { capture: true })\n return () => root.removeEventListener('submit', onSubmit, { capture: true })\n}\n\n/** Text a tool returns, which an agent reads. */\nconst textResult = (text: string, isError = false): ToolResult => ({\n content: [{ type: 'text', text }],\n isError,\n})\n\n/** Dispatches a capability for an agent, with the result as a tool returns it; it never rejects. */\nexport const dispatchFor =\n (agent: Agent.AgentRuntime<any, any, any, any, any>, invocationId: () => string) =>\n async (name: string, input: unknown, signal?: AbortSignal): Promise<ToolResult> => {\n try {\n // WebMCP hands the page a promise-returning callback, so this is the\n // edge where Effect meets the browser, not a run inside a service.\n const result = await Effect.runPromise(\n Effect.result(\n // The tool name and payload both come off the wire.\n agent.messages.dispatchUnknown(name, input, {\n id: invocationId(),\n transport: 'webmcp',\n signal,\n }),\n ),\n )\n // Every agent failure carries a message written for this audience.\n if (result._tag === 'Failure') return textResult(result.failure.message, true)\n // A declared completion contract has already resolved by the time\n // dispatch returns, so a failed completion is a failed tool call.\n const summary = Agent.summarize(result.success)\n return textResult(summary.text, !summary.ok)\n } catch {\n // `Effect.result` captures expected failures but not defects, and a\n // rejected tool promise is not something a calling agent can act on.\n // Report it as a tool error without leaking the application's internals.\n return textResult(`Capability \"${name}\" failed unexpectedly`, true)\n }\n }\n","/**\n * The slice of Chrome's experimental WebMCP Imperative API this adapter uses.\n *\n * These types are declared locally rather than imported: the API is still\n * experimental, and Foldkit should not be coupled to a browser proposal that is\n * still changing.\n */\n\n/** Metadata passed to a tool's `execute` function. */\nexport interface ToolExecutionContext {\n /** Cancellation for this invocation: is this call still wanted? */\n readonly signal?: AbortSignal | undefined\n}\n\n/** The value a WebMCP tool returns. */\nexport interface ToolResult {\n readonly content: ReadonlyArray<{ readonly type: 'text'; readonly text: string }>\n readonly isError?: boolean\n}\n\n/** A tool registration as accepted by `document.modelContext.registerTool`. */\nexport interface ToolDescriptor {\n readonly name: string\n readonly description: string\n readonly inputSchema: Record<string, unknown>\n readonly execute: (input: any, context: ToolExecutionContext) => Promise<ToolResult>\n}\n\n/**\n * Options accepted alongside a tool registration.\n *\n * The registration signal belongs here, not on the descriptor: aborting it is\n * how the documented API unregisters a tool.\n */\nexport interface RegisterToolOptions {\n readonly signal?: AbortSignal | undefined\n}\n\n/** The producer surface exposed on `document.modelContext`. */\nexport interface ModelContext {\n readonly registerTool: (\n tool: ToolDescriptor,\n options?: RegisterToolOptions,\n ) => void | Promise<unknown>\n}\n\n/**\n * The page's model context, when it has one: `document.modelContext`, where\n * the spec puts it, or else `navigator.modelContext`, the name Chromium used\n * before 150 and agent extensions that provide WebMCP still use. Undefined on\n * a server, or in a browser with neither.\n */\nexport const pageModelContext = (): ModelContext | undefined => {\n if (typeof document === 'undefined') return undefined\n const current = (document as unknown as { modelContext?: ModelContext }).modelContext\n if (current !== undefined) return current\n return typeof navigator === 'undefined'\n ? undefined\n : (navigator as unknown as { modelContext?: ModelContext }).modelContext\n}\n","import { Agent } from 'foldkit-agent'\nimport { Effect } from 'effect'\nimport { answerForms, declarativeTools, dispatchFor, type FormTool } from './forms.js'\nimport { type ModelContext, type ToolDescriptor, pageModelContext } from './webmcp.js'\n\n/** A live WebMCP registration. */\nexport interface Registration {\n /** Re-reads availability from the current Model and reconciles registrations. */\n readonly refresh: () => Promise<void>\n /** Unregisters every tool and stops following the Model. */\n readonly unregister: () => void\n /** The capability names currently registered with WebMCP. */\n readonly registered: () => ReadonlyArray<string>\n}\n\nexport interface RegisterOptions<Model, Context_, Principal, ByName, ByTag> {\n /** The agent contract bound to a live Foldkit Runtime. */\n readonly agent: Agent.AgentRuntime<Model, Context_, Principal, ByName, ByTag>\n /** Defaults to `pageModelContext()`: `document.modelContext`, or the older `navigator.modelContext`. */\n readonly modelContext?: ModelContext | undefined\n /** Unregisters everything when aborted. */\n readonly signal?: AbortSignal | undefined\n /**\n * Follow the live Model and reconcile registrations as `available(model)`\n * changes. Defaults to `true`, and is inert unless the host supports\n * subscription.\n */\n readonly followModel?: boolean | undefined\n /** Supplies an invocation id. Defaults to `crypto.randomUUID()`. */\n readonly invocationId?: (() => string) | undefined\n /**\n * Reports a failure from a reconcile that no caller is awaiting -- the\n * initial registration, or one triggered by a Model change.\n */\n readonly onError?: ((error: unknown) => void) | undefined\n /**\n * Capabilities the page draws as forms (`formTool`). An agent's submission\n * of one is answered as its tool call would be. In a browser that draws\n * forms as tools these are not registered too, as the form is the tool.\n */\n readonly forms?: ReadonlyArray<FormTool<keyof ByName & string>> | undefined\n}\n\n/**\n * Projects an agent contract into `document.modelContext.registerTool(...)`.\n *\n * Each currently available capability becomes one tool: the capability name\n * becomes the tool name, the variant description becomes the description, the\n * derived JSON Schema becomes `inputSchema`, and `execute` validates its input\n * and dispatches into the same live Foldkit Runtime the human is using.\n *\n * Tool availability is itself a projection of Model state. When\n * `available(model)` changes, registrations are reconciled: capabilities that\n * are gone have their registration signal aborted, and capabilities that have\n * appeared are registered.\n *\n * @example\n * ```ts\n * const registration = AgentWebMcp.register({ agent: agentRuntime })\n * ```\n */\nexport const register = <Model, Context_, Principal, ByName, ByTag>(\n options: RegisterOptions<Model, Context_, Principal, ByName, ByTag>,\n): Registration => {\n const modelContext = options.modelContext ?? pageModelContext()\n if (modelContext === undefined) {\n throw new Error(\n 'WebMCP is unavailable: no document.modelContext or navigator.modelContext. Pass an explicit modelContext to register().',\n )\n }\n\n const { agent } = options\n const dispatch = dispatchFor(agent, options.invocationId ?? Agent.newInvocationId)\n const forms = options.forms ?? []\n // Drawn as forms where the browser makes them tools, so registered only elsewhere.\n const asForms = new Set<string>(declarativeTools() ? forms.map(form => form.name) : [])\n const stopAnswering =\n forms.length === 0 || typeof document === 'undefined'\n ? () => {}\n : answerForms(document, forms, dispatch)\n\n /** One AbortController per registered tool: aborting it unregisters that tool. */\n const controllers = new Map<string, AbortController>()\n let disposed = false\n\n const toolFor = (\n name: string,\n description: string,\n inputSchema: Record<string, unknown>,\n ): { readonly controller: AbortController; readonly tool: ToolDescriptor } => {\n const controller = new AbortController()\n const execute = (input: unknown, context: { readonly signal?: AbortSignal | undefined }) =>\n dispatch(name, input, context.signal)\n return { controller, tool: { name, description, inputSchema, execute } }\n }\n\n const runReconcile = async (): Promise<void> => {\n if (disposed) return\n\n const available = await Effect.runPromise(agent.messages.available)\n const wanted = new Map(\n available.flatMap(descriptor =>\n asForms.has(descriptor.name) ? [] : [[descriptor.name, descriptor] as const],\n ),\n )\n\n // Unregister capabilities the Model no longer offers.\n for (const [name, controller] of [...controllers]) {\n if (!wanted.has(name)) {\n controller.abort()\n controllers.delete(name)\n }\n }\n\n // Register capabilities that have appeared.\n let failure: unknown\n for (const [name, descriptor] of wanted) {\n // unregister() can land while an await above is pending. Nothing more is\n // registered after that.\n if (disposed) return\n if (controllers.has(name)) continue\n\n const { controller, tool } = toolFor(name, descriptor.description, descriptor.inputSchema)\n\n try {\n // The signal goes in the options bag: aborting it is what unregisters\n // the tool.\n await modelContext.registerTool(tool, { signal: controller.signal })\n } catch (error) {\n // Nothing was registered, so nothing is recorded and nothing to abort.\n failure ??= error\n continue\n }\n\n // Disposal can also land while this registration is in flight, in which\n // case the tool is already registered and has to be taken back.\n if (disposed) {\n controller.abort()\n return\n }\n\n // Recorded only once the browser has accepted it.\n controllers.set(name, controller)\n }\n\n if (failure !== undefined) throw failure\n }\n\n /**\n * Reconciles are serialized.\n *\n * A capability is recorded only once the browser has accepted it, so two\n * overlapping reconciles would both see it as missing and register it twice.\n */\n let queue: Promise<void> = Promise.resolve()\n\n const reconcile = (): Promise<void> => {\n const next = queue.then(runReconcile, runReconcile)\n queue = next.then(\n () => {},\n () => {},\n )\n return next\n }\n\n let unsubscribe: () => void = () => {}\n\n const unregister = (): void => {\n disposed = true\n for (const controller of controllers.values()) controller.abort()\n controllers.clear()\n unsubscribe()\n stopAnswering()\n }\n\n /**\n * Reconciles without a caller to await the result. A rejection here would\n * otherwise become an unhandled rejection, so it is reported through\n * `onError` and the registration is left as it was.\n */\n const reconcileInBackground = (): void => {\n reconcile().catch(error => {\n options.onError?.(error)\n })\n }\n\n reconcileInBackground()\n\n if (options.followModel !== false) {\n unsubscribe = agent.subscribe(reconcileInBackground)\n }\n\n if (options.signal?.aborted === true) {\n // An already-aborted signal never fires its listener.\n unregister()\n } else {\n options.signal?.addEventListener('abort', unregister, { once: true })\n }\n\n return {\n refresh: reconcile,\n unregister,\n registered: () => [...controllers.keys()],\n }\n}\n","export { register, type RegisterOptions, type Registration } from './register.js'\nexport { pageModelContext } from './webmcp.js'\nexport { declarativeTools, formTool, type FormTool } from './forms.js'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/forms.ts","../src/webmcp.ts","../src/register.ts","../src/agentWebMcp.ts"],"sourcesContent":["import { Agent } from 'foldkit-agent'\nimport { Effect, Option } from 'effect'\nimport type { Attribute, HtmlBuilder } from 'foldkit/html'\nimport type { ToolResult } from './webmcp.js'\n\n/**\n * One capability drawn as a WebMCP declarative tool: a form whose `toolname`\n * and `tooldescription`, and whose fields' `name` and `toolparamdescription`,\n * come from the agent contract, so the form and the registered tool cannot\n * disagree. `register({ forms })` answers its agent submissions.\n */\nexport interface FormTool<Name extends string = string, Input = unknown> {\n readonly name: Name\n /** The form's attributes: `toolname`, `tooldescription`, and `toolautosubmit` when asked. */\n readonly form: <Message>(h: HtmlBuilder<Message>) => ReadonlyArray<Attribute<Message>>\n /**\n * A field's attributes: `name`, the input's key, and `toolparamdescription`\n * when the input's Schema describes it.\n */\n readonly field: <Message>(\n key: keyof Input & string,\n h: HtmlBuilder<Message>,\n ) => ReadonlyArray<Attribute<Message>>\n /** The input's keys, which an agent's submission is read from. */\n readonly keys: ReadonlyArray<string>\n}\n\n/** The description a property of the input's JSON Schema carries, if any. */\nconst describedBy = (property: unknown): Option.Option<string> =>\n typeof property === 'object' &&\n property !== null &&\n 'description' in property &&\n typeof property.description === 'string'\n ? Option.some(property.description)\n : Option.none()\n\n/**\n * Draws the capability `name` of an agent contract as a declarative tool: see\n * the README's \"Forms as declarative tools\". It throws for a name the contract\n * does not expose, or whose input is not an object of fields, which no form\n * could fill.\n */\nexport const formTool = <\n ByName extends Record<string, unknown>,\n const Name extends keyof ByName & string,\n>(\n definition: Agent.Definition<any, any, any, ByName, any>,\n name: Name,\n options: { readonly autosubmit?: boolean } = {},\n): FormTool<Name, ByName[Name]> => {\n const descriptor = Agent.messages(definition).find(each => each.name === name)\n if (descriptor === undefined)\n throw new Error(`AgentWebMcp.formTool: the contract exposes no capability \"${name}\"`)\n const properties = descriptor.inputSchema['properties']\n if (\n descriptor.inputSchema['type'] !== 'object' ||\n typeof properties !== 'object' ||\n properties === null\n )\n throw new Error(\n `AgentWebMcp.formTool: \"${name}\" takes no object of fields, which no form can fill`,\n )\n const fields = new Map(\n Object.entries(properties).map(([key, property]) => [key, describedBy(property)] as const),\n )\n return {\n name,\n keys: [...fields.keys()],\n form: h => [\n h.Attribute('toolname', name),\n h.Attribute('tooldescription', descriptor.description),\n ...(options.autosubmit === true ? [h.Attribute('toolautosubmit', '')] : []),\n ],\n field: (key, h) => {\n const described = fields.get(key)\n if (described === undefined)\n throw new Error(`AgentWebMcp.formTool: \"${name}\" has no field \"${key}\"`)\n return [\n // An attribute, not `h.Name`, which Foldkit sets only in the browser:\n // a server-rendered form names its fields too.\n h.Attribute('name', key),\n ...Option.match(described, {\n onNone: () => [],\n onSome: description => [h.Attribute('toolparamdescription', description)],\n }),\n ]\n },\n }\n}\n\n/** Whether this browser draws forms as tools: its `SubmitEvent` says when an agent submitted. */\nexport const declarativeTools = (): boolean =>\n typeof SubmitEvent !== 'undefined' && 'agentInvoked' in SubmitEvent.prototype\n\n/**\n * Answers an agent's submission of a form tool on `root`: in the capture phase,\n * before the application's own submit handler, the form's fields named by the\n * input are dispatched as the capability through `dispatch`, and the result\n * goes back through `respondWith`. A person's submission is left alone.\n */\nexport const answerForms = (\n root: Document,\n forms: ReadonlyArray<FormTool>,\n dispatch: (name: string, input: unknown) => Promise<ToolResult>,\n): (() => void) => {\n const byName = new Map(forms.map(form => [form.name, form]))\n const onSubmit = (event: Event) => {\n // `agentInvoked` and `respondWith` are what a declarative WebMCP browser adds to the event.\n const form = event.target\n if (!('agentInvoked' in event) || event.agentInvoked !== true) return\n if (!(form instanceof HTMLFormElement) || !('respondWith' in event)) return\n const { respondWith } = event\n if (typeof respondWith !== 'function') return\n const tool = byName.get(form.getAttribute('toolname') ?? '')\n if (tool === undefined) return\n event.preventDefault()\n event.stopImmediatePropagation()\n // Text, as a form submits it; a field the input does not name is not read.\n const data = new FormData(form)\n const input: Record<string, string> = Object.create(null)\n for (const key of tool.keys) {\n const value = data.get(key)\n if (typeof value === 'string') input[key] = value\n }\n respondWith.call(event, dispatch(tool.name, input))\n }\n root.addEventListener('submit', onSubmit, { capture: true })\n return () => root.removeEventListener('submit', onSubmit, { capture: true })\n}\n\n/** Text a tool returns, which an agent reads. */\nconst textResult = (text: string, isError = false): ToolResult => ({\n content: [{ type: 'text', text }],\n isError,\n})\n\n/** Dispatches a capability for an agent, with the result as a tool returns it; it never rejects. */\nexport const dispatchFor =\n (agent: Agent.AgentRuntime<any, any, any, any, any>, invocationId: () => string) =>\n async (name: string, input: unknown, signal?: AbortSignal): Promise<ToolResult> => {\n try {\n // WebMCP hands the page a promise-returning callback, so this is the\n // edge where Effect meets the browser, not a run inside a service.\n const result = await Effect.runPromise(\n Effect.result(\n // The tool name and payload both come off the wire.\n agent.messages.dispatchUnknown(name, input, {\n id: invocationId(),\n transport: 'webmcp',\n signal,\n }),\n ),\n )\n // Every agent failure carries a message written for this audience.\n if (result._tag === 'Failure') return textResult(result.failure.message, true)\n // A declared completion contract has already resolved by the time\n // dispatch returns, so a failed completion is a failed tool call.\n const summary = Agent.summarize(result.success)\n return textResult(summary.text, !summary.ok)\n } catch {\n // `Effect.result` captures expected failures but not defects, and a\n // rejected tool promise is not something a calling agent can act on.\n // Report it as a tool error without leaking the application's internals.\n return textResult(`Capability \"${name}\" failed unexpectedly`, true)\n }\n }\n","/**\n * The slice of Chrome's experimental WebMCP Imperative API this adapter uses.\n *\n * These types are declared locally rather than imported: the API is still\n * experimental, and Foldkit should not be coupled to a browser proposal that is\n * still changing.\n */\n\n/** Metadata passed to a tool's `execute` function. */\nexport interface ToolExecutionContext {\n /** Cancellation for this invocation: is this call still wanted? */\n readonly signal?: AbortSignal | undefined\n}\n\n/** The value a WebMCP tool returns. */\nexport interface ToolResult {\n readonly content: ReadonlyArray<{ readonly type: 'text'; readonly text: string }>\n readonly isError?: boolean\n}\n\n/** A tool registration as accepted by `document.modelContext.registerTool`. */\nexport interface ToolDescriptor {\n readonly name: string\n readonly description: string\n readonly inputSchema: Record<string, unknown>\n readonly execute: (input: any, context: ToolExecutionContext) => Promise<ToolResult>\n}\n\n/**\n * Options accepted alongside a tool registration.\n *\n * The registration signal belongs here, not on the descriptor: aborting it is\n * how the documented API unregisters a tool.\n */\nexport interface RegisterToolOptions {\n readonly signal?: AbortSignal | undefined\n}\n\n/** The producer surface exposed on `document.modelContext`. */\nexport interface ModelContext {\n readonly registerTool: (\n tool: ToolDescriptor,\n options?: RegisterToolOptions,\n ) => void | Promise<unknown>\n}\n\n/**\n * The page's model context, when it has one: `document.modelContext`, where\n * the spec puts it, or else `navigator.modelContext`, the name Chromium used\n * before 150 and agent extensions that provide WebMCP still use. Undefined on\n * a server, or in a browser with neither.\n */\nexport const pageModelContext = (): ModelContext | undefined => {\n if (typeof document === 'undefined') return undefined\n const current = (document as unknown as { modelContext?: ModelContext }).modelContext\n if (current !== undefined) return current\n return typeof navigator === 'undefined'\n ? undefined\n : (navigator as unknown as { modelContext?: ModelContext }).modelContext\n}\n","import { Agent } from 'foldkit-agent'\nimport { Effect } from 'effect'\nimport { answerForms, declarativeTools, dispatchFor, type FormTool } from './forms.js'\nimport { type ModelContext, type ToolDescriptor, pageModelContext } from './webmcp.js'\n\n/** A live WebMCP registration. */\nexport interface Registration {\n /** Re-reads availability from the current Model and reconciles registrations. */\n readonly refresh: () => Promise<void>\n /** Unregisters every tool and stops following the Model. */\n readonly unregister: () => void\n /** The capability names currently registered with WebMCP. */\n readonly registered: () => ReadonlyArray<string>\n}\n\nexport interface RegisterOptions<Model, Context_, Principal, ByName, ByTag> {\n /** The agent contract bound to a live Foldkit Runtime. */\n readonly agent: Agent.AgentRuntime<Model, Context_, Principal, ByName, ByTag>\n /** Defaults to `pageModelContext()`: `document.modelContext`, or the older `navigator.modelContext`. */\n readonly modelContext?: ModelContext | undefined\n /** Unregisters everything when aborted. */\n readonly signal?: AbortSignal | undefined\n /**\n * Follow the live Model and reconcile registrations as `available(model)`\n * changes. Defaults to `true`, and is inert unless the host supports\n * subscription.\n */\n readonly followModel?: boolean | undefined\n /** Supplies an invocation id. Defaults to `crypto.randomUUID()`. */\n readonly invocationId?: (() => string) | undefined\n /**\n * Reports a failure from a reconcile that no caller is awaiting -- the\n * initial registration, or one triggered by a Model change.\n */\n readonly onError?: ((error: unknown) => void) | undefined\n /**\n * Capabilities the page draws as forms (`formTool`). An agent's submission\n * of one is answered as its tool call would be. In a browser that draws\n * forms as tools these are not registered too, as the form is the tool.\n */\n readonly forms?: ReadonlyArray<FormTool<keyof ByName & string>> | undefined\n}\n\n/**\n * Projects an agent contract into `document.modelContext.registerTool(...)`.\n *\n * Each currently available capability becomes one tool: the capability name\n * becomes the tool name, the variant description becomes the description, the\n * derived JSON Schema becomes `inputSchema`, and `execute` validates its input\n * and dispatches into the same live Foldkit Runtime the human is using.\n *\n * Tool availability is itself a projection of Model state. When\n * `available(model)` changes, registrations are reconciled: capabilities that\n * are gone have their registration signal aborted, and capabilities that have\n * appeared are registered.\n *\n * @example\n * ```ts\n * const registration = AgentWebMcp.register({ agent: agentRuntime })\n * ```\n */\nexport const register = <Model, Context_, Principal, ByName, ByTag>(\n options: RegisterOptions<Model, Context_, Principal, ByName, ByTag>,\n): Registration => {\n const modelContext = options.modelContext ?? pageModelContext()\n if (modelContext === undefined) {\n throw new Error(\n 'WebMCP is unavailable: no document.modelContext or navigator.modelContext. Pass an explicit modelContext to register().',\n )\n }\n\n const { agent } = options\n const dispatch = dispatchFor(agent, options.invocationId ?? Agent.newInvocationId)\n const forms = options.forms ?? []\n // Drawn as forms where the browser makes them tools, so registered only elsewhere.\n const asForms = new Set<string>(declarativeTools() ? forms.map(form => form.name) : [])\n const stopAnswering =\n forms.length === 0 || typeof document === 'undefined'\n ? () => {}\n : answerForms(document, forms, dispatch)\n\n /** One AbortController per registered tool: aborting it unregisters that tool. */\n const controllers = new Map<string, AbortController>()\n let disposed = false\n\n const toolFor = (\n name: string,\n description: string,\n inputSchema: Record<string, unknown>,\n ): { readonly controller: AbortController; readonly tool: ToolDescriptor } => {\n const controller = new AbortController()\n const execute = (input: unknown, context: { readonly signal?: AbortSignal | undefined }) =>\n dispatch(name, input, context.signal)\n return { controller, tool: { name, description, inputSchema, execute } }\n }\n\n const runReconcile = async (): Promise<void> => {\n if (disposed) return\n\n const available = await Effect.runPromise(agent.messages.available)\n const wanted = new Map(\n available.flatMap(descriptor =>\n asForms.has(descriptor.name) ? [] : [[descriptor.name, descriptor] as const],\n ),\n )\n\n // Unregister capabilities the Model no longer offers.\n for (const [name, controller] of [...controllers]) {\n if (!wanted.has(name)) {\n controller.abort()\n controllers.delete(name)\n }\n }\n\n // Register capabilities that have appeared.\n let failure: unknown\n for (const [name, descriptor] of wanted) {\n // unregister() can land while an await above is pending. Nothing more is\n // registered after that.\n if (disposed) return\n if (controllers.has(name)) continue\n\n const { controller, tool } = toolFor(name, descriptor.description, descriptor.inputSchema)\n\n try {\n // The signal goes in the options bag: aborting it is what unregisters\n // the tool.\n await modelContext.registerTool(tool, { signal: controller.signal })\n } catch (error) {\n // Nothing was registered, so nothing is recorded and nothing to abort.\n failure ??= error\n continue\n }\n\n // Disposal can also land while this registration is in flight, in which\n // case the tool is already registered and has to be taken back.\n if (disposed) {\n controller.abort()\n return\n }\n\n // Recorded only once the browser has accepted it.\n controllers.set(name, controller)\n }\n\n if (failure !== undefined) throw failure\n }\n\n /**\n * Reconciles are serialized.\n *\n * A capability is recorded only once the browser has accepted it, so two\n * overlapping reconciles would both see it as missing and register it twice.\n */\n let queue: Promise<void> = Promise.resolve()\n\n const reconcile = (): Promise<void> => {\n const next = queue.then(runReconcile, runReconcile)\n queue = next.then(\n () => {},\n () => {},\n )\n return next\n }\n\n let unsubscribe: () => void = () => {}\n\n const unregister = (): void => {\n disposed = true\n for (const controller of controllers.values()) controller.abort()\n controllers.clear()\n unsubscribe()\n stopAnswering()\n }\n\n /**\n * Reconciles without a caller to await the result. A rejection here would\n * otherwise become an unhandled rejection, so it is reported through\n * `onError` and the registration is left as it was.\n */\n const reconcileInBackground = (): void => {\n reconcile().catch(error => {\n options.onError?.(error)\n })\n }\n\n reconcileInBackground()\n\n if (options.followModel !== false) {\n unsubscribe = agent.subscribe(reconcileInBackground)\n }\n\n if (options.signal?.aborted === true) {\n // An already-aborted signal never fires its listener.\n unregister()\n } else {\n options.signal?.addEventListener('abort', unregister, { once: true })\n }\n\n return {\n refresh: reconcile,\n unregister,\n registered: () => [...controllers.keys()],\n }\n}\n","export { register, type RegisterOptions, type Registration } from './register.js'\nexport { pageModelContext } from './webmcp.js'\nexport { declarativeTools, formTool, type FormTool } from './forms.js'\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// \0rolldown/runtime.js
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __exportAll = (all, no_symbols) => {
|
|
4
4
|
let target = {};
|
|
@@ -9,5 +9,4 @@ var __exportAll = (all, no_symbols) => {
|
|
|
9
9
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
10
|
return target;
|
|
11
11
|
};
|
|
12
|
-
//#endregion
|
|
13
12
|
export { __exportAll as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "foldkit-agent-webmcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "WebMCP adapter for foldkit-agent. Projects exposed Foldkit Messages into document.modelContext tools.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"foldkit",
|
|
@@ -38,18 +38,18 @@
|
|
|
38
38
|
"LICENSE"
|
|
39
39
|
],
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"effect": "^4.
|
|
42
|
-
"foldkit": "^0.
|
|
43
|
-
"foldkit-agent": "^0.
|
|
41
|
+
"effect": "^4.1.0",
|
|
42
|
+
"foldkit": "^0.170.0",
|
|
43
|
+
"foldkit-agent": "^0.9.0"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@effect/platform-browser": "^4.0
|
|
48
|
-
"effect": "^4.0
|
|
49
|
-
"foldkit": "0.
|
|
47
|
+
"@effect/platform-browser": "^4.1.0",
|
|
48
|
+
"effect": "^4.1.0",
|
|
49
|
+
"foldkit": "0.170.0",
|
|
50
50
|
"tsdown": "^0.23.1",
|
|
51
51
|
"typescript": "7.0.2",
|
|
52
|
-
"foldkit-agent": "0.
|
|
52
|
+
"foldkit-agent": "0.9.0"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "tsdown",
|