From 91e97e19053e447fffec0c1fa19be9a60841ea42 Mon Sep 17 00:00:00 2001
From: "mark a. foltz" If |document| is |execution|'s [=pending tool
execution/target document=] and is not |execution|'s [=pending tool execution/caller
document=], then run |execution|'s [=pending tool execution/completion steps=] given null
- and false.
ModelContext=]'s [=ModelContext/internal context=]'s [=model context/tool map=].
-1. If |toolMap|[|toolName|] does not [=map/exist=], then run |completionSteps| given null and false,
- and abort these steps.
-
- Issue: Support the plumbing of more granular errors back to the invoker; this should result in a
- "{{NotFoundError}}" in the calling document.
+1. If |toolMap|[|toolName|] does not [=map/exist=], then run |completionSteps| given null and
+ "{{NotFoundError}}", and abort these steps.
This protects us against a race between tool unregistration and execution. While tool
@@ -476,14 +474,11 @@ internal value=] |uuid|, are as follows:
1. Let |inputObject| be the result of [=parse a JSON string to a JavaScript value=] given
|inputArguments| and |targetDocument|'s [=relevant realm=]. If exception was thrown, then run |completionSteps| given null and false, and abort
- these steps.
-
- Issue: Support more granular errors; here we should return something that prompts the caller to
- reject its {{Promise}} with a "{{DataError}}" {{DOMException}}.
+ thrown">exception was thrown, then run |completionSteps| given null and "{{DataError}}", and
+ abort these steps.
1. If |inputObject| [=Object type|is not an Object=], then run |completionSteps| given null
- and false, and abort these steps.
+ and "{{DataError}}", and abort these steps.
1. [=Fire an event=] named {{ModelContext/toolactivated}} at |targetDocument|'s [=Document/associated
ModelContext|associated ModelContext=], using {{ToolActivatedEvent}}, with its
@@ -526,9 +521,9 @@ internal value=] |uuid|, are as follows:
1. Let |serializedResult| be the result of [=serializing a JavaScript value to a JSON
string=] given |v|. If this throws an exception, run |completionSteps| given null and
- false, and abort these steps.
+ "{{OperationError}}", and abort these steps.
- 1. Run |completionSteps| given |serializedResult| and true.
+ 1. Run |completionSteps| given |serializedResult| and null.
- If |toolPromise| was rejected with reason |r|, then:
@@ -542,7 +537,7 @@ internal value=] |uuid|, are as follows:
1. [=map/Remove=] |localExecutions|[|uuid|].
- 1. Run |completionSteps| given null and false.
+ 1. Run |completionSteps| given null and "{{OperationError}}".
ModelContext=]'s [=ModelContext/internal context=]'s [=model context/tool map=].
@@ -1007,21 +998,23 @@ The executeTool(tool, inputObject
1. If |targetToolMap|[|toolName|] does not [=map/exist=], then [=queue a global task=] on the
[=webmcp task source=] given |callerDocument|'s [=relevant global object=] to [=reject=]
- |promise| with an "{{UnknownError}}" {{DOMException}}, and abort these steps.
-
- Issue: Support more granular errors than "{{UnknownError}}", based on each failure case.
+ |promise| with a "{{NotFoundError}}" {{DOMException}}, and abort these steps.
1. Let |tool definition| be |targetToolMap|[|toolName|].
1. If [=tool is exposed to an origin=] given |targetOrigin|, |tool definition|'s [=tool
definition/exposed origins=], and |callerOrigin| returns false, then [=queue a global task=]
on the [=webmcp task source=] given |callerDocument|'s [=relevant global object=] to
- [=reject=] |promise| with an "{{UnknownError}}" {{DOMException}}, and abort these steps.
+ [=reject=] |promise| with a "{{NotFoundError}}" {{DOMException}}, and abort these steps.
- Issue: Support more granular errors than "{{UnknownError}}", based on each failure case.
+ Note: Rejecting with "{{NotFoundError}}" across all three checks above—when |targetOrigin| does
+ not match |expectedTargetOrigin|, when |toolName| does not exist, and when |tool definition|
+ is not exposed to |callerOrigin|—prevents a cross-origin caller from using fabricated
+ {{RegisteredTool}} dictionaries to probe |targetDocument|'s current origin or enumerate
+ private tools not exposed to |callerOrigin|.
1. Let |completionSteps| be an algorithm that takes a [=string=]-or-null |result| and a
- [=boolean=] |success|, and runs the following steps [=in parallel=]:
+ [=string=]-or-null |errorName|, and runs the following steps [=in parallel=]:
1. If |targetDocument|'s [=node navigable=]'s [=navigable/traversable navigable=]'s
[=traversable navigable/pending tool executions map=][|uuid|] does not [=map/exist=],
@@ -1040,12 +1033,16 @@ The executeTool(tool, inputObject
1. [=map/Remove=] |targetDocument|'s [=node navigable=]'s [=navigable/traversable
navigable=]'s [=traversable navigable/pending tool executions map=][|uuid|].
- 1. If |success| is true, then [=queue a global task=] on the [=webmcp task source=] given
+ 1. If |errorName| is null, then [=queue a global task=] on the [=webmcp task source=] given
|callerDocument|'s [=relevant global object=] to [=resolve=] |promise| with |result|.
1. Otherwise, [=queue a global task=] on the [=webmcp task source=] given |callerDocument|'s
- [=relevant global object=] to [=reject=] |promise| with an "{{UnknownError}}"
- {{DOMException}}.
+ [=relevant global object=] to [=reject=] |promise| with a {{DOMException}} named
+ |errorName|.
+
+ Note: Passing only the platform exception name |errorName| (rather than any internal
+ JavaScript exception object or message thrown in |targetDocument|) prevents leaking
+ provider implementation details or stack traces across origins.
1. Let |execution| be a new [=pending tool execution=], with the following [=struct/items=]:
From d74249a7bc12eeeae5247d5b07878226df3296b9 Mon Sep 17 00:00:00 2001
From: Dominic Farolino | Value + | Description + | [=tool execution error/Corresponding exception name=] + |
|---|---|---|
| tool not found + | The tool being executed is not registered in the target {{Document}}. + | "{{NotFoundError}}" + |
| invalid input + | The input arguments could not be parsed into a JavaScript Object. + | "{{DataError}}" + |
| tool rejected + | The tool's {{ModelContextTool/execute}} callback returned a rejected {{Promise}}. + | "{{OperationError}}" + |
| unserializable result + | The tool's result could not be serialized to a JSON string. + | "{{OperationError}}" + |
| target document unloaded + | The target {{Document}} was unloaded before the execution completed. + | "{{AbortError}}" + |
[=Tool execution errors=] are not exposed to the web. They exist as a spec concept to give tool + execution algorithms a realm-agnostic set of failure reasons that correspond to {{DOMException}} + types that do get exposed to the caller; the caller only ever observes the [=tool + execution error/corresponding exception name=].
+ +Also note that this table only tracks the list of platform-defined failures. Tool + execution failures defined in userland by web developers that write tools can come in any + shape or format in the response JSON string.
+If |document| is |execution|'s [=pending tool execution/target document=] and is not |execution|'s [=pending tool execution/caller document=], then run |execution|'s [=pending tool execution/completion steps=] given null - and "{{AbortError}}".
+ and [=tool execution error/target document unloaded=]. Note: This removes |execution| from the [=traversable navigable/pending tool executions map=]. @@ -410,7 +454,7 @@ a [=list=] of [=origins=] |exposed origins|, and an [=origin=] |accessing origin The tool execute steps, given a [=string=] |toolName|, a {{Document}} |targetDocument|, a [=string=] |inputArguments|, an algorithm |completionSteps|, and a [=unique internal value=] |uuid|, are as follows. The |completionSteps| algorithm takes a [=string=]-or-null result -and a [=string=]-or-null errorName. +and a [=tool execution error=]-or-null error. 1. [=Assert=]: these steps are running on |targetDocument|'s [=relevant agent=]'s [=agent/event loop=]. @@ -419,7 +463,7 @@ and a [=string=]-or-null errorName.ModelContext=]'s [=ModelContext/internal context=]'s [=model context/tool map=].
1. If |toolMap|[|toolName|] does not [=map/exist=], then run |completionSteps| given null and
- "{{NotFoundError}}", and abort these steps.
+ [=tool execution error/tool not found=], and abort these steps.
This protects us against a race between tool unregistration and execution. While tool
@@ -474,11 +518,11 @@ internal value=] |uuid|, are as follows:
1. Let |inputObject| be the result of [=parse a JSON string to a JavaScript value=] given
|inputArguments| and |targetDocument|'s [=relevant realm=]. If exception was thrown, then run |completionSteps| given null and "{{DataError}}", and
- abort these steps.
+ thrown">exception was thrown, then run |completionSteps| given null and [=tool execution
+ error/invalid input=], and abort these steps.
1. If |inputObject| [=Object type|is not an Object=], then run |completionSteps| given null
- and "{{DataError}}", and abort these steps.
+ and [=tool execution error/invalid input=], and abort these steps.
1. [=Fire an event=] named {{ModelContext/toolactivated}} at |targetDocument|'s [=Document/associated
ModelContext|associated ModelContext=], using {{ToolActivatedEvent}}, with its
@@ -521,7 +565,7 @@ internal value=] |uuid|, are as follows:
1. Let |serializedResult| be the result of [=serializing a JavaScript value to a JSON
string=] given |v|. If this throws an exception, run |completionSteps| given null and
- "{{OperationError}}", and abort these steps.
+ [=tool execution error/unserializable result=], and abort these steps.
1. Run |completionSteps| given |serializedResult| and null.
@@ -537,7 +581,7 @@ internal value=] |uuid|, are as follows:
1. [=map/Remove=] |localExecutions|[|uuid|].
- 1. Run |completionSteps| given null and "{{OperationError}}".
+ 1. Run |completionSteps| given null and [=tool execution error/tool rejected=].
Also note that this table only tracks the list of platform-defined failures. Tool - execution failures defined in userland by web developers that write tools can come in any - shape or format in the response JSON string.
- +Also note that this table only tracks the list of platform-defined + failures. Tool execution failures defined by tool authors may also be reported + to the tool caller in the response JSON string.
+Also note that this table only tracks the list of platform-defined - failures. Tool execution failures defined by tool authors may also be reported + failures. Tool execution failures defined by tool authors can also be reported to the tool caller in the response JSON string.