Repository navigation
Signal tool stability with waitForToolsUntil() for user agent observations - #373
khushalsagar wants to merge 4 commits into
Conversation
|
A tangential thing worth taking up in a separate PR: the toolChange notification from register/unregister isn't coalesced well right now. It's triggered for every register/unregister call. Seems like it would be better to do it in a separate task (or microtask?) since in a task the state will be updated by multiple calls and we should dispatch a single event for all those mutations. |
94b382b to
9f62142
Compare
9f62142 to
59af1ff
Compare
markafoltz
left a comment
There was a problem hiding this comment.
Overall structure looks good, it this PR has several features (toolchange event, modelContext.toolsReady, blocking getTools()) not yet landed; are you thinking of adjusting this once the implementations land?
| 1. [=set/Append=] |promise| to |context|'s [=model context/pending tool readiness promises=]. | ||
|
|
||
| 1. [=Update the tools-ready state=] given |document|. |
There was a problem hiding this comment.
Web IDL wraps every Promise<any> argument in a new promise, so even waitForToolsUntil(Promise.resolve()) or waitForToolsUntil(42) synchronously sets tools-ready to false and fires toolchange{ready:false} at every document. A microtask later it fires toolchange{ready:true}.
Chromium returns early when the promise has already settled, so it fires nothing. The waitForToolsUntil(42) case in the WPT would behave differently from the spec once ToolChangeEvent ships.
Suggest coalescing: have update the tools-ready state queue a task that compares the current state with the last state we notified about, and notify only when they differ. This fits with your PR comment about coalescing the register/unregister notifications.
There was a problem hiding this comment.
Updated the spec to match the WPTs and ignore already settled promises, nice catch!
Deferred the ToolChangeEvent dispatch changes to a follow-up PR, will take care of toolchange event batching there. Also, my comment was about an existing issue with no batching for toolchange in the register/unregister case tracked in #374.
There was a problem hiding this comment.
Can you add an Issue(374) note in the spec about the toolchange coalescing (if there isn't one already)?
…omments - Defer ToolChangeEvent/toolchange readiness dispatch and the getTools() wait to a follow-up PR. - wait for tools to be ready: capture the top-level active document up front, drop the null check, and return "ready" or "navigated". - perform an observation: return early on "navigated". - waitForToolsUntil(): ignore already-settled promises, split React into fulfilled/rejected branches, and always update tools-ready on settle. - Move tools-ready below the ModelContext creation paragraph, rename the example variable, and fix in-parallel indentation in registerTool().
The navigable can also be destroyed while waiting, so "navigated" was too narrow. Update the note in perform an observation to cover both cases.
* WebPlatform: implement WebMCP (document.modelContext) - document.modelContext and the ModelContext interface of the WebMCP specification: registerTool() (name/description validation, schema serialization, exposedTo, signal), getTools() (frame tree, same-origin and fromOrigins/exposedTo filtering, sorted by name), executeTool() (pending executions per traversable, cancellation, toolcancel and toolactivated events, unloading document cleanup steps), toolchange - the Tool interface of webmachinelearning/webmcp#348 (what Chromium and the WPT implement) instead of the RegisteredTool dictionary, and the outputSchema member - waitForToolsUntil() and toolsReady of webmachinelearning/webmcp#373, marked [Experimental("WEBPLATEXP0018")] - the "tools" permissions policy feature and WebPlatformFeatures.WebMcpEnabled - a host API for the application, as the browser agent: BrowsingContext.GetModelContextTools(), ExecuteModelContextToolAsync() and ModelContextToolsReady - ScriptEngine JSON hooks (JSON.stringify/JSON.parse of the realm) - WPT: run webmcp; the declarative API (explainer only) is skipped, and the subtests that expect unquoted string results are TEST BUGs (webmachinelearning/webmcp#361) * WebPlatform: address the review of WebMCP - the settlement of a tool and of a waitForToolsUntil() promise is handled by a task of the event loop (a task of the application can complete on another thread) - the realms capture JSON.parse() and JSON.stringify() when they are created, before the page can replace them - executeTool() checks the caller again after serializing the arguments (toJSON() can detach it) - Tool.Document is the document that registered the tool
markafoltz
left a comment
There was a problem hiding this comment.
LGTM % adding Issues for things to follow up on.
| disconnected and is no longer [=Document/fully active=]. Returning true here immediately | ||
| unblocks the wait so the caller can check [=Document/fully active=] and abort. | ||
|
|
||
| 1. [=list/For each=] [=navigable=] |navigable| of |activeDocument|'s [=Document/inclusive |
There was a problem hiding this comment.
I didn't see a note about permissions policy near the tools-ready definition, where I expected to find it.
| 1. [=set/Append=] |promise| to |context|'s [=model context/pending tool readiness promises=]. | ||
|
|
||
| 1. [=Update the tools-ready state=] given |document|. |
There was a problem hiding this comment.
Can you add an Issue(374) note in the spec about the toolchange coalescing (if there isn't one already)?
|
|
||
| 1. Let |activeDocument| be |traversable|'s [=navigable/active document=]. | ||
|
|
||
| 1. [=Assert=]: |activeDocument| is [=Document/fully active=]. |
There was a problem hiding this comment.
This is checked before these steps are run, but can this be asserted if this is running in parallel, or do we need to abort if it's no longer the case?
|
|
||
| <dl class="domintro" dfn-type=attribute dfn-for=ToolChangeEvent> | ||
| : <dfn>ready</dfn> | ||
| :: Returns true if the tools are ready to be read, or false if tool updates are in progress. |
There was a problem hiding this comment.
Add a Issue(236) note here to update it later?
|
|
||
| 1. Run the following steps [=in parallel=]: | ||
|
|
||
| 1. [=Wait for tools to be ready=] given |toolRequestor|'s [=node navigable=]'s |
There was a problem hiding this comment.
Add Issue(328) here noting the deadlock issue?
| 1. If |toolsReady| is false, then return. | ||
|
|
||
| 1. [=In parallel=], [=notify documents of a tool change=] given |targetDocument|, |exposed | ||
| origins|, and |toolsReady|. |
There was a problem hiding this comment.
I don't feel strongly, it just looks a little odd. It should be a minor change on this PR?
|
|
||
| 1. [=Notify documents of a tool change=] given |tool owner| and |exposed origins|. | ||
| 1. If |toolsReady| is true, then [=notify documents of a tool change=] given |tool owner|, | ||
| |exposed origins|, and |toolsReady|. |
Implement the resolution from #328 (minutes) and #328 (comment):
waitForToolsUntilandtoolsReady, and state tracking for thetools-readystate based on pending promises.tools-ready(up to an implementation-defined timeout) inperform an observation.toolchangeevent (ToolChangeEventwithready) when tools become not ready and suppress dispatch of this event until tools become ready again.Wiring the wait for
tools-readytogetTools()and changing dispatch oftoolchangeevents is deferred for a follow up PR.Note: There's still an open question for the
Documentlifecycle until which tools are presumed to be not ready.Part of #328.
Preview | Diff