- Run comparison benchmark in an isolated git worktree to prevent workspace pollution and local branch conflicts.
- Harden security by passing benchmark target and SHA as environment variables to prevent shell injection, and adding '--' to bazel query and git rev-parse.
- Optimize workflow by removing pnpm caching to mitigate cache poisoning risks.
- Improve robustness of benchmark log parsing, supporting both ZIP outputs and raw directories, and safely checking for JSON reports.
- Centralize git command execution on the dev-infra GitClient for consistency.
- Add tslib to benchpress dependencies to prevent module resolution failures.
(cherry picked from commit 547d85addf)
This enables the use of the `experimentalWebMcpTool` option on signal forms and implicitly declares a WebMCP tool based on the form data model. This is an experiment inspirted by the WebMCP declarative forms API to see if Angular's framework-level knowledge of the form's declarative data model can produce higher quality WebMCP tools than the web standard can on its own with less effort from the developer.
Example:
```typescript
// main.ts
import {bootstrapApplication} from '@angular/platform-browser';
import {provideExperimentalWebMcpForms} from '@angular/forms';
import {MyComp} from './form';
bootstrapApplication(MyComp, {
providers: [
// Activate the feature.
provideExperimentalWebMcpForms(),
],
});
```
```typescript
// form.ts
import {Component, signal} from '@angular/core';
import {form} from '@angular/forms';
@Component({ /* ... */ })
export class MyComp {
private readonly f = form(signal({
firstName: '',
lastName: '',
}), {
// Implicitly creates a WebMCP tool named `createUser` which accepts a `firstName` and `lastName` as parameters.
experimentalWebMcpTool: {
name: 'createUser',
description: 'Creates a user with the given name.',
},
// Invokes the submit action when the agent calls the WebMCP tool.
submission: {
action: () => {
console.log('User clicked submit, or agent called the tool!');
},
},
});
// ...
}
```
This is a relatively light wrapper around `navigator.modelContext.registerTool` which ties tool registration to the lifecycle of an `Injector`. When the `Injector` is destroyed, the tool is automatically unregistered. This makes it easier to create WebMCP tools without having to worry about managing unregistration.
I went a little off-spec by providing the `AbortSignal` to the `execute` function. I suspect something like this will be added eventually and there are some early discussions of that, but AFAICT, this behavior is not defined yet so I'm making something up instead so the `execute` function can observe a cancellation based on the `Injector` being destroyed.
This uses `@mcp-b/webmcp-polyfill` for testing, as it provides a small `modelContextTesting` utility for listing and invoking WebMCP tools. Unfortunately it is slightly out of date of the current Chrome spec (it requires `modelContext.unregisterTool` to be called, whereas the spec recently removed this option and expects you to provide an `AbortSignal` to `registerTool`). My slightly hacky solution for the moment is to both trigger the `AbortSignal` and also call `unregisterTool` safely. In production, only the `AbortSignal` happens, but in testing the `unregisterTool` code path is used. Hopefully this will get smoothed out as the spec matures and `@mcp-b/webmcp-polyfill` updates over time.
This copies WebMCP types into `@angular/core` and redistributes them. Ideally this would just be a regular dependency, but we need to do this vendoring for API extractor to properly process the types, since they will inform `@angular/core` public API.
One downside of this approach is that the dependency is not visible in Intellisense, breaking type inference.
Updates the supported Node.js engine versions to include Node.js 26.
This allows running the CLI on Node.js 26.0.0 and above while continuing to support active LTS versions.