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
6 changes: 3 additions & 3 deletions .agents/skills/verify-astro-devtools/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ the `Route type filter` group and the `Filter routes` search box (Routes),
```sh
drive.ts http /api/hello # status, content-type, location, body
drive.ts mcp tools # tools/list through the real Streamable HTTP handshake
drive.ts mcp call astro-devtools_routes_info --save routes-mcp
drive.ts mcp call astro-devtools_routes_list --save routes-mcp
drive.ts log --grep '_actions' # the dev server's own output, ANSI stripped
drive.ts url # the base URL, for curl
```
Expand Down Expand Up @@ -160,8 +160,8 @@ Standards for a proof:
suite stubs the host); recognise it and clear it, don't count it against
the integration.
- The MCP surface and the panels share one handler per query, so parity
is a legitimate proof: `browser rpc astro-devtools:overview:info` and
`mcp call astro-devtools_overview_info` must return the same data.
is a legitimate proof: `browser rpc astro-devtools:overview:get` and
`mcp call astro-devtools_overview_get` must return the same data.

## Cleanup

Expand Down
4 changes: 2 additions & 2 deletions .agents/skills/verify-astro-devtools/features/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Preconditions:
- **Open it.** Run `drive.ts browser goto /`, `drive.ts browser dock Config` and `drive.ts browser wait --testid config-row`.
- **File card.** Run `drive.ts browser aria config --selector devframes-dock-embedded`. It shows `heading "Config file"`, `button "astro.config.mjs"` and `heading "Astro config"`.
- **Rows.** Run `drive.ts browser count --testid config-row` (`17`) and `drive.ts browser text --testid config-row --save config-rows`. The rows read key then value, e.g. `outputstatic`, `adapter@astrojs/node`, `base/`, `trailingSlashignore`, `build.formatdirectory`, `i18n.localesen, ja`, `i18n.fallbackja → en (redirect)`, `site(not set)`, and `integrations` including `astro-devtools@<version>` and `playground-extension`. The integrations row lists the adapter first (`@astrojs/node@<version>`), then the renderer integrations (`@astrojs/preact`, `@astrojs/react`, `@astrojs/solid-js`, `@astrojs/svelte`, `@astrojs/vue` and `@astrojs/alpinejs`, each with its version), `playground-extension`, `astro-devtools@<version>` and `astro:actions`, the entry Astro adds because the project has an actions file.
- **Data behind it.** Run `drive.ts browser rpc astro-devtools:config:info --save config-rpc`. `configFile` is `astro.config.mjs`, `root` is the playground's absolute path with a trailing slash, and `entries` holds the same key/value pairs as the rows.
- **Data behind it.** Run `drive.ts browser rpc astro-devtools:config:get --save config-rpc`. `configFile` is `astro.config.mjs`, `root` is the playground's absolute path with a trailing slash, and `entries` holds the same key/value pairs as the rows.
- **Embedded proof.** Run `drive.ts browser screenshot config` before navigating away from the page.
- **Standalone.** Run `drive.ts browser goto /__devtools/`, `drive.ts browser panel config` and `drive.ts browser count --testid config-row`. It is the same `17`: nothing in this panel is page-scoped.
- **Standalone proof.** Run `drive.ts browser screenshot config-standalone`.
Expand All @@ -31,4 +31,4 @@ Preconditions:
- Row text is key immediately followed by value; match on both parts (`outputstatic`).
- The `astro.config.mjs` button opens the developer's editor; prove its label, never click.
- The integrations row resolves each integration's version by looking its package up from the project root (falling back to the integration's own install), so a dependency bump changes it; the row count stays `17` because the conditional rows `image.domains`, `image.remotePatterns`, `env (keys only)` and `experimental (enabled)` are all at their defaults in the playground and are omitted, while the four `i18n.*` rows appear only because the playground configures i18n.
- This panel is not on the MCP surface (`astro-devtools:config:info` carries no agent metadata); prove it through the page or `browser rpc`, not `mcp call`.
- This panel is not on the MCP surface (`astro-devtools:config:get` carries no agent metadata); prove it through the page or `browser rpc`, not `mcp call`.
8 changes: 4 additions & 4 deletions .agents/skills/verify-astro-devtools/features/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ While `astro dev` runs on a loopback host, the dev server exposes an unauthentic
## Sub-features

- `mcp-discovery` publishes `/__astro-devtools/__connection.json` naming the MCP path (`__mcp`, relative, same origin, no separate port).
- `mcp-tools` lists `astro-devtools_overview_info`, `astro-devtools_routes_info` and `astro-devtools_actions_info`, each marked read-only, and none of the panel-only queries (plus upstream's own read-only `devframe_state_read`).
- `mcp-tools` lists `astro-devtools_overview_get`, `astro-devtools_routes_list` and `astro-devtools_actions_list`, each marked read-only, and none of the panel-only queries (plus upstream's own read-only `devframe_state_read`).
- `mcp-call` answers a tool call with the running server's data.
- `mcp-parity` returns exactly what the corresponding panel RPC returns, since both share one handler.
- `mcp-gate` stays off on non-loopback hosts unless the integration's own `mcp: true` (`astroDevtools({ mcp: true })`, unrelated to `vite.devtools.mcp`), and off everywhere with `mcp: false`; the decision reads the resolved bind address once the dev server has settled it.
Expand All @@ -24,9 +24,9 @@ Preconditions:
- Baseline (`drive.ts doctor` includes the `server.mcp` check).

- **Discovery.** Run `drive.ts http /__astro-devtools/__connection.json --save mcp-connection`. Status `200`; the body has `mcp.path` equal to `__mcp` and no `mcp.port`. Run `drive.ts http /__astro-devtools/__mcp --save mcp-get`: a plain GET answers `405` with the JSON-RPC error `Method not allowed.`, which proves the route is mounted and not origin-gated (a `403` would mean the gate rejected the harness).
- **Tool list.** Run `drive.ts mcp tools --save mcp-tools`. The list contains `astro-devtools_overview_info`, `astro-devtools_routes_info` and `astro-devtools_actions_info`, each with `readOnlyHint: true` and a description ending in `This query is read-only.`; it does not contain `astro-devtools_project_context` or `astro-devtools_config_info` (upstream adds its own `devframe_state_read`, also `readOnlyHint: true`).
- **Call.** Run `drive.ts mcp call astro-devtools_overview_info --save mcp-overview`. `isError` is `false` and `data.astroVersion` is a semver; `drive.ts mcp call astro-devtools_actions_info` lists the five playground actions with `actionsFile: "src/actions/index.ts"`; `drive.ts mcp call astro-devtools_routes_info` has a `context` with `adapterName` and `output` and a non-empty `routes` array.
- **Parity.** Run `drive.ts browser rpc astro-devtools:overview:info --save parity-rpc` and compare with `mcp-overview.json`: the RPC result and the tool's `data` are identical JSON.
- **Tool list.** Run `drive.ts mcp tools --save mcp-tools`. The list contains `astro-devtools_overview_get`, `astro-devtools_routes_list` and `astro-devtools_actions_list`, each with `readOnlyHint: true` and a description ending in `This query is read-only.`; it does not contain `astro-devtools_project_context` or `astro-devtools_config_get` (upstream adds its own `devframe_state_read`, also `readOnlyHint: true`).
- **Call.** Run `drive.ts mcp call astro-devtools_overview_get --save mcp-overview`. `isError` is `false` and `data.astroVersion` is a semver; `drive.ts mcp call astro-devtools_actions_list` lists the five playground actions with `actionsFile: "src/actions/index.ts"`; `drive.ts mcp call astro-devtools_routes_list` has a `context` with `adapterName` and `output` and a non-empty `routes` array.
- **Parity.** Run `drive.ts browser rpc astro-devtools:overview:get --save parity-rpc` and compare with `mcp-overview.json`: the RPC result and the tool's `data` are identical JSON.
- **Hub route off.** Run `drive.ts http /__devtools/__connection.json --save hub-connection`: `200` JSON with `backend`, `websocket`, `sse` and `configs` but no `mcp` key. Run `drive.ts http /__devtools/__mcp --save hub-mcp-get`: `200` with `text/html` (the hub's own page, `<title>Devframes</title>`), not an MCP answer. Run `drive.ts http /__devtools/__mcp --method POST --body '{}' --save hub-mcp-post`: `405` with an empty body.
- **Proof.** The saved JSON files above are the evidence; add `drive.ts log --grep '__astro-devtools'` if the server logged the requests.

Expand Down
4 changes: 2 additions & 2 deletions .agents/skills/verify-astro-devtools/features/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Overview is the Astro group's landing panel: it shows the integration's version,
- Click `Astro` in the dock: the group opens on Overview.
- Click `Overview` in the group's sidebar from any other Astro panel.
- Open `/__devtools/`, then the Astro group.
- Agents read the same data through the `astro-devtools_overview_info` MCP tool; [mcp.md](./mcp.md) drives it and its parity with this panel.
- Agents read the same data through the `astro-devtools_overview_get` MCP tool; [mcp.md](./mcp.md) drives it and its parity with this panel.

## Driving it with drive.ts

Expand All @@ -25,7 +25,7 @@ Preconditions:
- **Open it.** Run `drive.ts browser dock Overview` and `drive.ts browser wait --selector '#astro-version'`. The Astro version stat is visible.
- **Versions.** Run `drive.ts browser text --selector '#astro-version'` and `drive.ts browser aria overview --selector devframes-dock-embedded`. The stat reads the installed Astro version as a semver (`v7.3.2` at the time of writing); the snapshot lists `heading "Astro DevTools" [level=1]`, `paragraph: astro-devtools v0.0.1` (the package version), `link "Astro v<version>"` to `https://astro.build` and `link "Vite v<version>"` to `https://vite.dev`.
- **Counts.** In the same snapshot, `button "9 pages"` and `button "5 actions"` match the playground's nine pages (`/`, `/ja`, `/blog/[slug]`, `/client-directives`, `/client-islands-failed`, `/dashboard`, `/frameworks`, `/server-islands`, `/server-islands-failed`) and five actions (`greet`, `feedback.submit`, `survey`, `upload`, `likes.add`).
- **Data behind it.** Run `drive.ts browser rpc astro-devtools:overview:info --save overview-rpc`. The JSON has `astroVersion`, `viteVersion`, `astroDevtoolsVersion`, `nodeVersion`, `output: "static"`, `adapterName: "@astrojs/node"`, `actionsFile: "src/actions/index.ts"`, `middlewareFile: "src/middleware.ts"`, `configFile: "astro.config.mjs"`, `root`, `base`, `trailingSlash`, `buildFormat`, an `i18n` block with locales `en`, `ja`, and `counts: { pages: 9, endpoints: 1, redirects: 1, actions: 5 }`.
- **Data behind it.** Run `drive.ts browser rpc astro-devtools:overview:get --save overview-rpc`. The JSON has `astroVersion`, `viteVersion`, `astroDevtoolsVersion`, `nodeVersion`, `output: "static"`, `adapterName: "@astrojs/node"`, `actionsFile: "src/actions/index.ts"`, `middlewareFile: "src/middleware.ts"`, `configFile: "astro.config.mjs"`, `root`, `base`, `trailingSlash`, `buildFormat`, an `i18n` block with locales `en`, `ja`, and `counts: { pages: 9, endpoints: 1, redirects: 1, actions: 5 }`.
- **Jump to Routes.** Run `drive.ts browser click --role button --name "9 pages" --exact` and `drive.ts browser wait --role group --name "Route type filter"`. The Routes panel is open.
- **Jump to Actions.** Run `drive.ts browser dock Overview`, then `drive.ts browser click --role button --name "5 actions" --exact` and `drive.ts browser wait --role button --name greet --exact`. The Actions panel is open. This is the Actions panel's second entry point; `features/actions.md` drives the panel itself.
- **Footer links.** In the `overview` snapshot, `contentinfo` holds `link "Star on GitHub"` to `https://github.com/morinokami/astro-devtools` and `link "Report a Bug"` to its `/issues` page.
Expand Down
4 changes: 2 additions & 2 deletions packages/astro-devtools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ origin — `http://localhost:4321/__astro-devtools/__mcp` on Astro's default
port (Streamable HTTP; discoverable via
`/__astro-devtools/__connection.json`). It gets three read-only tools
answering with data only the running dev server has:
`astro-devtools_overview_info`, `astro-devtools_routes_info`, and
`astro-devtools_actions_info`.
`astro-devtools_overview_get`, `astro-devtools_routes_list`, and
`astro-devtools_actions_list`.

When developing this repository, start the playground dev server, then run
`vp run inspect` in another terminal to open the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { actionId, useActionCallState } from "./use-action-call-state.ts";
const ACTIONS_DOCS_URL = "https://docs.astro.build/en/guides/actions/";

export function ActionsPanel({ context, refreshKey }: PanelProps) {
const actionsState = useRpcData(context, refreshKey, "astro-devtools:actions:info");
const actionsState = useRpcData(context, refreshKey, "astro-devtools:actions:list");
const actionsInfo = actionsState.data;
const state = useActionCallState(actionsInfo);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { parse as devalueParse } from "devalue";

/** Call real Astro Action endpoints and decode their responses. */

/** URL options for the `/_actions/` endpoint from the actions-info RPC. */
/** URL options for the `/_actions/` endpoint from the `astro-devtools:actions:list` RPC. */
interface ActionEndpointOptions {
/** Resolved `base` of the site; `/` when unset. */
base?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useRpcData } from "../../platform/hooks.ts";

/** Show the resolved Astro config and a link to its source file. */
export function ConfigPanel({ context, refreshKey }: PanelProps) {
const configState = useRpcData(context, refreshKey, "astro-devtools:config:info");
const configState = useRpcData(context, refreshKey, "astro-devtools:config:get");
const configInfo = configState.data;
const configFile = configInfo?.configFile;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const EXTERNAL_LINKS: {

/** Show project versions and statistics, with links to the other panels. */
export function OverviewPanel({ context, refreshKey }: PanelProps) {
const overviewState = useRpcData(context, refreshKey, "astro-devtools:overview:info");
const overviewState = useRpcData(context, refreshKey, "astro-devtools:overview:get");
const overviewInfo = overviewState.data;
const astroDevtoolsVersion = formatVersion(overviewInfo?.astroDevtoolsVersion);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { RouteSectionCard } from "./RouteSectionCard.tsx";

export function RoutesPanel({ context, refreshKey, active }: PanelProps) {
const pageScoped = isPageScoped(context);
const routesState = useRpcData(context, refreshKey, "astro-devtools:routes:info");
const routesState = useRpcData(context, refreshKey, "astro-devtools:routes:list");
const routesInfo = routesState.data;
// Re-render after Astro client navigation so the current-page row moves
// with the page.
Expand Down
8 changes: 4 additions & 4 deletions packages/astro-devtools/src/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ interface AstroDevtoolsRpcDefinition<
export function createRpcDefinitions(store: AstroDevtoolsStore): AstroDevtoolsRpcDefinition[] {
return [
defineQuery(
"astro-devtools:overview:info",
"astro-devtools:overview:get",
async () => ({
...store.project,
counts: {
Expand All @@ -47,14 +47,14 @@ export function createRpcDefinitions(store: AstroDevtoolsStore): AstroDevtoolsRp
),
// Used by the Islands panel for project-relative editor links.
defineQuery("astro-devtools:project:context", async () => ({ root: store.project.root })),
defineQuery("astro-devtools:routes:info", async () => buildRoutesInfo(store), {
defineQuery("astro-devtools:routes:list", async () => buildRoutesInfo(store), {
description:
"List project, integration-injected, and Astro internal routes with URL patterns, " +
"source files, i18n variants, production delivery modes, output settings, adapter, " +
"and middleware. This query is read-only.",
}),
defineQuery(
"astro-devtools:actions:info",
"astro-devtools:actions:list",
async () => ({
actionsFile: store.project.actionsFile,
root: store.project.root,
Expand All @@ -73,7 +73,7 @@ export function createRpcDefinitions(store: AstroDevtoolsStore): AstroDevtoolsRp
},
),
// Display-ready values used only by the Config panel.
defineQuery("astro-devtools:config:info", async () => ({
defineQuery("astro-devtools:config:get", async () => ({
configFile: store.project.configFile,
root: store.project.root,
entries: store.configSummary,
Expand Down
18 changes: 9 additions & 9 deletions packages/astro-devtools/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export interface RoutesContext {
i18n?: I18nInfo;
}

/** Response from the `astro-devtools:routes:info` RPC. */
/** Response from the `astro-devtools:routes:list` RPC. */
export interface RoutesInfo {
context: RoutesContext;
routes: RouteDisplay[];
Expand All @@ -117,7 +117,7 @@ export interface ProjectContext {
root?: string;
}

/** One exported action, as the `astro-devtools:actions:info` RPC describes it. */
/** One exported action, as the `astro-devtools:actions:list` RPC describes it. */
export interface ActionDescriptor {
/** The property names leading from the root `server` object to this action. */
segments: string[];
Expand All @@ -137,7 +137,7 @@ export interface ActionDescriptor {
input?: unknown;
}

/** Response from the `astro-devtools:actions:info` RPC. */
/** Response from the `astro-devtools:actions:list` RPC. */
export interface ActionsInfo {
/** Root-relative path of the actions file; unset when the project has none. */
actionsFile?: string;
Expand Down Expand Up @@ -167,7 +167,7 @@ export interface ConfigEntry {
value: string;
}

/** Response from the `astro-devtools:config:info` RPC. */
/** Response from the `astro-devtools:config:get` RPC. */
export interface ConfigInfo {
/**
* Root-relative path of the project's astro.config file. Unset when no
Expand Down Expand Up @@ -243,18 +243,18 @@ export interface OverviewCounts {
actions?: number;
}

/** Response from the `astro-devtools:overview:info` RPC. */
/** Response from the `astro-devtools:overview:get` RPC. */
export interface OverviewInfo extends ProjectInfo {
counts: OverviewCounts;
}

/** Response type for every RPC function registered by this integration. */
export interface AstroDevtoolsRpcFunctions {
"astro-devtools:overview:info": OverviewInfo;
"astro-devtools:overview:get": OverviewInfo;
"astro-devtools:project:context": ProjectContext;
"astro-devtools:routes:info": RoutesInfo;
"astro-devtools:actions:info": ActionsInfo;
"astro-devtools:config:info": ConfigInfo;
"astro-devtools:routes:list": RoutesInfo;
"astro-devtools:actions:list": ActionsInfo;
"astro-devtools:config:get": ConfigInfo;
}

export interface AstroDevtoolsOptions {
Expand Down
4 changes: 2 additions & 2 deletions packages/astro-devtools/test/actions-metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ describe("actionsMetadataPlugin on a dev server", () => {
store.setViteServer(viteServer);
store.setActionsModulePath(join(root, "src/actions/index.ts"));
const definition = createRpcDefinitions(store).find(
({ name }) => name === "astro-devtools:actions:info",
({ name }) => name === "astro-devtools:actions:list",
);
if (!definition) throw new Error("actions:info RPC definition not found");
if (!definition) throw new Error("actions:list RPC definition not found");
return (await definition.setup().handler()) as ActionsInfo;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/astro-devtools/test/client/platform/hooks.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function HookView({
context: DockClientScriptContext;
refreshKey: number;
}) {
const result = useRpcData(context, refreshKey, "astro-devtools:config:info");
const result = useRpcData(context, refreshKey, "astro-devtools:config:get");
return (
<div data-status={result.status} data-file={result.data?.configFile ?? ""}>
<span>{result.error?.message}</span>
Expand Down Expand Up @@ -78,7 +78,7 @@ describe("useRpcData", () => {

await act(() => render(<HookView context={dock.context} refreshKey={1} />, container));
expect(status(container)).toBe("loading");
expect(call).toHaveBeenCalledWith("astro-devtools:config:info");
expect(call).toHaveBeenCalledWith("astro-devtools:config:get");

await act(async () => request.resolve(configInfo("astro.config.mjs")));
expect(status(container)).toBe("ready");
Expand Down
Loading
Loading