Skip to content
Draft
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
79 changes: 79 additions & 0 deletions .agents/skills/aspire/references/agent-workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,85 @@ Inspect the live app before editing code:
4. `aspire otel traces <resource>` to follow cross-service activity.
5. `aspire export` when you need a zipped telemetry snapshot for deeper analysis or handoff.

## Scenario: I Need To Drive A Browser In An Aspire App

If the app exposes a Browser Automation resource, use it as the first-choice agent browser before reaching for Playwright. Browser Automation is optimized for frontend applications and keeps browser actions, console logs, network events, screenshots, cookies, storage, and session state tied to the Aspire resource.

If the AppHost does not expose browser automation for the frontend yet, add the frontend-focused browser integration before falling back to Playwright:

```bash
aspire add browsers
```

Attach browser automation to the frontend resource, not to backend services. For TypeScript AppHosts with a Vite frontend:

```typescript
const frontend = await builder
.addViteApp("frontend", "./frontend")
.withExternalHttpEndpoints()
.withBrowserAutomation();
```

For TypeScript AppHosts with a generic JavaScript frontend:

```typescript
const frontend = await builder
.addJavaScriptApp("frontend", "./frontend", { runScriptName: "dev" })
.withHttpEndpoint({ env: "PORT" })
.withExternalHttpEndpoints()
.withBrowserAutomation();
```

For C# AppHosts:

```csharp
builder.AddProject<Projects.Web>("web")
.WithExternalHttpEndpoints()
.WithBrowserAutomation();
```

For TypeScript AppHosts, run `aspire add browsers`, then inspect `.modules/aspire.ts` for the generated `withBrowserAutomation` API before editing `apphost.ts`.

Start the app and find the browser automation resource. The resource is currently named like `<frontend>-browser-automation`:

```bash
aspire start --isolated
aspire describe --format Json
aspire resource <browser-automation-resource> open-tracked-browser
aspire resource <browser-automation-resource> inspect-browser
```

Use refs and snapshots for the agent loop:

```bash
aspire resource <browser-automation-resource> click-browser e1 snapshotAfter=true
aspire resource <browser-automation-resource> type-browser-text e2 "hello" snapshotAfter=true
aspire resource <browser-automation-resource> wait selector='#results' timeoutMilliseconds=10000
aspire resource <browser-automation-resource> get text '#results'
```

Use state and session commands when tests need continuity or low-level browser control:

```bash
aspire resource <browser-automation-resource> state get
aspire resource <browser-automation-resource> state set '<state-json>' true
aspire resource <browser-automation-resource> cookies set session abc
aspire resource <browser-automation-resource> storage local set theme dark
aspire resource <browser-automation-resource> tabs list
aspire resource <browser-automation-resource> frames
aspire resource <browser-automation-resource> dialog accept
aspire resource <browser-automation-resource> downloads allow /tmp/downloads true
aspire resource <browser-automation-resource> upload '#file' '["/tmp/file.txt"]'
aspire resource <browser-automation-resource> cdp Runtime.evaluate '{"expression":"document.title","returnByValue":true}' page
```

Keep these points in mind:

- Re-run `inspect-browser` after navigation or major DOM changes because refs are snapshot-scoped.
- Prefer `snapshotAfter=true` on mutating commands when the next agent decision depends on the resulting DOM.
- Browser Automation cookie/state commands are page-origin scoped and cannot read or set HttpOnly cookies.
- Use Playwright only when you need independent contexts, browser matrix testing, tracing/video, or an existing Playwright test suite.

## Scenario: I Need To Add An Integration, Understand An API, Or Add A Custom Command Safely

Use the docs commands first for the workflow, then use the API reference commands if you need the concrete API entry:
Expand Down
58 changes: 58 additions & 0 deletions .agents/skills/aspire/references/playwright-handoff.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,59 @@

Use this when Playwright CLI is already configured and the next step is browser testing against a running Aspire app.

Before handing off to Playwright, check whether the AppHost has a Browser Automation resource for the frontend. Browser Automation is optimized for frontend applications, exposes an agent browser interface through `aspire resource <browser-automation-resource> <command> ...`, and keeps browser console/network telemetry attached to the Aspire resource.

If the AppHost does not have browser automation yet, run the frontend-focused browser integration alias and attach it to the frontend before falling back to Playwright:

```bash
aspire add browsers
```

TypeScript AppHost with Vite frontend:

```typescript
const frontend = await builder
.addViteApp("frontend", "./frontend")
.withExternalHttpEndpoints()
.withBrowserAutomation();
```

TypeScript AppHost with a generic JavaScript frontend:

```typescript
const frontend = await builder
.addJavaScriptApp("frontend", "./frontend", { runScriptName: "dev" })
.withHttpEndpoint({ env: "PORT" })
.withExternalHttpEndpoints()
.withBrowserAutomation();
```

C# AppHost:

```csharp
builder.AddProject<Projects.Web>("web")
.WithExternalHttpEndpoints()
.WithBrowserAutomation();
```

Prefer Browser Automation resource commands when the task can be handled by the tracked browser:

```bash
aspire resource <browser-automation-resource> open-tracked-browser
aspire resource <browser-automation-resource> inspect-browser
aspire resource <browser-automation-resource> click-browser e1 snapshotAfter=true
aspire resource <browser-automation-resource> fill-browser '#email' 'user@example.com' snapshotAfter=true
aspire resource <browser-automation-resource> wait selector='#results' timeoutMilliseconds=10000
aspire resource <browser-automation-resource> get text '#results'
aspire resource <browser-automation-resource> state get
aspire resource <browser-automation-resource> storage local set theme dark
aspire resource <browser-automation-resource> cookies get
aspire resource <browser-automation-resource> tabs list
aspire resource <browser-automation-resource> cdp Target.getTargets '{}' browser
```

Use Playwright when the task needs capabilities outside the tracked browser resource, such as independent browser contexts, cross-browser matrix testing, tracing/video, or a test suite already written in Playwright.

## Scenario: I Need The Right Frontend URL Before Browser Testing

Use these commands when the task is to discover the live frontend endpoint from Aspire state and then hand that URL to Playwright.
Expand All @@ -15,6 +68,11 @@ playwright-cli --help
Keep these points in mind:

- Aspire discovers the endpoint first; Playwright uses the discovered endpoint after the handoff.
- If a Browser Automation resource exists, try its resource commands first so logs, network events, screenshots, and state changes stay correlated with Aspire telemetry.
- `inspect-browser` returns element refs such as `e1`; use refs quickly and re-run `inspect-browser` after navigation or major DOM changes.
- Mutating commands commonly support `snapshotAfter=true` to return a fresh page snapshot for agent verification.
- Browser Automation `state`, `cookies`, and `storage` operate in the active page origin and only expose page-visible cookies; use Playwright browser contexts when HttpOnly cookies or multi-origin storage state are required.
- Use the raw `cdp` command as the escape hatch for low-level browser protocol operations before leaving Aspire.
- Prefer `aspire describe --format Json` when the URL needs to be consumed by a script or passed to another tool.
- Use `--apphost <path>` when multiple AppHosts exist and the user is asking about one specific app.
- Do not guess frontend endpoints without first consulting Aspire state.
Expand Down
35 changes: 35 additions & 0 deletions .agents/skills/aspire/references/typescript-apphosts.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,41 @@ Keep these points in mind:
- Inspect `.modules/aspire.ts` after `aspire add` to see the refreshed API surface available to `apphost.ts`.
- The local `tsconfig.json` often includes `.modules/**/*.ts` in its compilation scope.

## Scenario: I Need Browser Automation For A JavaScript Frontend

Use this when the AppHost is `apphost.ts` and the frontend is a Vite app or another JavaScript app. Browser Automation is optimized for frontend applications, so attach it to the browser-served frontend resource rather than backend services.

```bash
aspire add browsers
```

For Vite frontends, attach browser automation to the Vite resource:

```typescript
const frontend = await builder
.addViteApp("frontend", "./frontend")
.withExternalHttpEndpoints()
.withBrowserAutomation();
```

For generic JavaScript frontends that run from a package.json script, attach browser automation to the JavaScript app resource:

```typescript
const frontend = await builder
.addJavaScriptApp("frontend", "./frontend", { runScriptName: "dev" })
.withHttpEndpoint({ env: "PORT" })
.withExternalHttpEndpoints()
.withBrowserAutomation();
```

Keep these points in mind:

- Run `aspire add browsers` first so `.modules/aspire.ts` includes `withBrowserAutomation`.
- Use `addViteApp` for Vite projects and `addJavaScriptApp` for package.json-script frontends such as Next.js, CRA, or custom dev servers.
- Add an HTTP endpoint before `withBrowserAutomation`; for generic JavaScript apps, prefer `.withHttpEndpoint({ env: "PORT" })` when the dev server can read `PORT`.
- Use `.withExternalHttpEndpoints()` when the user or an agent needs to open the frontend directly in a browser.
- After editing, restart with `aspire start --isolated` and use `aspire describe --format Json` to find the generated `<frontend>-browser-automation` resource.

## Scenario: `.modules/` Disappeared After A Pull, Clean, Or Branch Switch

Use this when generated support files are missing or stale and the TypeScript AppHost needs to be restored.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#pragma warning disable ASPIREBROWSERLOGS001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning disable ASPIREBROWSERAUTOMATION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

var builder = DistributedApplication.CreateBuilder(args);

builder.AddProject<Projects.BrowserTelemetry_Web>("web")
.WithExternalHttpEndpoints()
.WithBrowserLogs();
.WithBrowserAutomation();

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
Expand All @@ -21,4 +21,4 @@

builder.Build().Run();

#pragma warning restore ASPIREBROWSERLOGS001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning restore ASPIREBROWSERAUTOMATION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<div class="container">
<div class="row g-4">
<div class="col-lg-8">
<h1 class="display-6">Browser logs demo</h1>
<h1 class="display-6">Browser automation demo</h1>
<p class="lead">
Use the <strong>web-browser-logs</strong> resource in the dashboard to open a tracked browser session, then
Use the <strong>web-browser-automation</strong> resource in the dashboard to open a tracked browser session, then
use the buttons below to emit browser-side console logs, network requests, and unhandled failures.
</p>
</div>
<div class="col-lg-4">
<div class="alert alert-secondary mb-0" id="browser-log-status">
<div class="alert alert-secondary mb-0" id="browser-automation-status">
Waiting for browser interaction.
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ function wireButton(id, callback) {
}

function setStatus(message) {
const status = document.getElementById('browser-log-status');
const status = document.getElementById('browser-automation-status');
if (!status) {
return;
}
Expand Down
Loading