Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/docs/src/content/agents/mcp-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ Your client can ask you before it runs them. To drop them from the server, set `

### Pages and tabs

Each browser tab reports on its own and gets a page id, and so does an [Angular Native](../getting-started/angular-native.md) or [NativeScript](../getting-started/nativescript.md) app. `list-pages` lists them with their platform. Tools that read live data use the most recent page by default. Pass `page` to pick another tab (`inspect-providers`, `highlight`, `inspect-component` and `defer-blocks` also accept `pageId`). An id that no tab reports gets an answer that lists the tabs that do, instead of data from another tab. The server drops pages that stop reporting after a short time.
Each browser tab reports on its own and gets a page id, and so does an [Angular Native](../getting-started/angular-native.md) or [NativeScript](../getting-started/nativescript.md) app. `list-pages` lists them with their platform. Most tools that read live data use the most recent page by default, and [Agent tools](./tools.md) names the ones that don't. Pass `page` to pick another tab (`inspect-providers`, `highlight`, `inspect-component` and `defer-blocks` also accept `pageId`). An id that no tab reports gets an answer that lists the tabs that do, instead of data from another tab. The server drops pages that stop reporting after a short time.

## Where to next

Expand Down
10 changes: 5 additions & 5 deletions apps/docs/src/content/agents/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,11 @@ While on, the overlay wraps `Observable.prototype.subscribe` and records which c

An image of one component's host element as the page renders it now. The answer is an MCP image content block (PNG, or JPEG when the PNG is large) with a short note: the size in CSS pixels, what was masked and what could not be drawn. Reads: page.

| Argument | Required | Value |
| ---------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `selector` | yes | An instance id from the `component-tree` resource (like `c12`), a class name, a host tag or any CSS selector. |
| `page` | no | The page id, from `list-pages`. Defaults to the most recent page. |
| `pageId` | no | Same as `page`. |
| Argument | Required | Value |
| ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `selector` | yes | An instance id from the `component-tree` resource (like `c12`), a class name, a host tag or any CSS selector. |
| `page` | no | The page id, from `list-pages`. Without it, ids, class names and tags are searched on every page, newest first, and a CSS selector uses the most recent page. |
| `pageId` | no | Same as `page`. |

The page draws a copy of the element, not the screen: it copies the element's DOM with every computed style written inline into an SVG, and draws that on a canvas that is never added to the page. Nothing in the app changes, no app code runs, and a component scrolled out of view or behind a dialog is drawn all the same. A class name or tag that matches several instances captures the first and lists the ids of all of them. A CSS selector captures the first element it matches on the most recent page, or on `page`.

Expand Down
47 changes: 47 additions & 0 deletions packages/devtools/src/__tests__/tool-descriptions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { createHostContext } from 'devframe/node';
import { expect, it } from 'vitest';
import pangular from '../devframe.ts';

it('keeps all agent tool and resource descriptions under 600 characters', async () => {
const host = {
mountStatic: () => {},
resolveOrigin: () => 'http://localhost',
getStorageDir: () => '',
};
const ctx = await createHostContext({ cwd: process.cwd(), mode: 'dev', host: host as never });
await pangular.setup(ctx as never);
const { tools, resources } = ctx.agent.list();

const oversizedTools: { id: string; len: number }[] = [];
for (const tool of tools) {
if (tool.description.length > 600) {
oversizedTools.push({ id: tool.id, len: tool.description.length });
}
expect(
tool.description.length,
`Tool "${tool.id}" description is too short (${tool.description.length} chars)`,
).toBeGreaterThanOrEqual(40);
}

const oversizedResources: { id: string; len: number }[] = [];
for (const resource of resources) {
const desc = resource.description ?? '';
if (desc.length > 600) {
oversizedResources.push({ id: resource.id, len: desc.length });
}
expect(
desc.length,
`Resource "${resource.id}" description is too short (${desc.length} chars)`,
).toBeGreaterThanOrEqual(40);
}

expect(
oversizedTools,
`Found tools with description > 600 chars: ${JSON.stringify(oversizedTools)}`,
).toEqual([]);

expect(
oversizedResources,
`Found resources with description > 600 chars: ${JSON.stringify(oversizedResources)}`,
).toEqual([]);
});
Loading
Loading