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
5 changes: 4 additions & 1 deletion packages/core/src/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ export const COMMANDS: Record<string, CommandInfo> = {
'download-as': { desc: 'Set filename for next download', options: [],
usage: 'download-as <filename>',
examples: ['download-as bills/rogers-2026-03.pdf'] },
'wait-download': { desc: 'Wait for the next browser download to complete (returns full path)', options: [],
usage: 'wait-download',
examples: ['wait-download'] },
'start-recording': { desc: 'Start recording commands to .pw file', options: [],
usage: 'start-recording [filename]',
examples: ['start-recording', 'start-recording my-flow.pw'] },
Expand All @@ -197,7 +200,7 @@ export const CATEGORIES: Record<string, string[]> = {
'Video': ['video-start', 'video-stop', 'video-chapter'],
'Tracing': ['tracing-start', 'tracing-stop'],
'Recording': ['start-recording', 'stop-recording', 'pause-recording', 'discard-recording'],
'Other': ['dialog-accept', 'dialog-dismiss', 'route', 'route-list', 'unroute', 'resize', 'pdf', 'upload', 'download-as', 'config-print'],
'Other': ['dialog-accept', 'dialog-dismiss', 'route', 'route-list', 'unroute', 'resize', 'pdf', 'upload', 'download-as', 'wait-download', 'config-print'],
};

/** Commands that mutate the page — snapshot should be attached when includeSnapshot is on. */
Expand Down
38 changes: 38 additions & 0 deletions packages/extension/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,9 @@ async function executeSingleCommand(command: string): Promise<{ text: string; is

type BridgeResult = { text: string; isError: boolean; image?: string; blobUrl?: string; duration?: number; size?: number };

// Pending resolver for wait-download command
let pendingDownloadResolve: ((result: BridgeResult) => void) | null = null;

function executeCommandPayload(msg: {
command: string;
scriptType?: 'command' | 'script';
Expand Down Expand Up @@ -716,6 +719,26 @@ async function handleBridgeCommand(msg: {
return { text: `Next download will save as: ${path}`, isError: false };
}

// ── Wait download ───────────────────────────────────────────────────────────
// Waits for the next browser download to complete and returns its full path.
if (cmd === 'wait-download') {
return new Promise<BridgeResult>((resolve) => {
if (pendingDownloadResolve) {
resolve({ text: 'A wait-download is already pending', isError: true });
return;
}
const timer = setTimeout(() => {
pendingDownloadResolve = null;
resolve({ text: 'wait-download timed out after 30s', isError: true });
}, 30_000);
pendingDownloadResolve = (result) => {
clearTimeout(timer);
pendingDownloadResolve = null;
resolve(result);
};
});
}

// Validate existing page connection is still alive (#849)
if (currentPage) {
try {
Expand Down Expand Up @@ -994,6 +1017,21 @@ chrome.downloads.onDeterminingFilename.addListener((_item, suggest) => {
}
});

// ─── Download completion tracking ───────────────────────────────────────────
// Resolves pending wait-download promises when a download completes or fails.
chrome.downloads.onChanged.addListener((delta) => {
if (!pendingDownloadResolve) return;
if (delta.state?.current === 'complete') {
chrome.downloads.search({ id: delta.id }, (items) => {
if (items[0] && pendingDownloadResolve) {
pendingDownloadResolve({ text: items[0].filename, isError: false });
}
});
} else if (delta.state?.current === 'interrupted') {
pendingDownloadResolve({ text: `Download interrupted: ${delta.error?.current ?? 'unknown'}`, isError: true });
}
});

// Expose stable globals for swDebugEval — functions that never change go here, not inside attachToTab
globalThis.downloadAs = (filename: string) => { globalThis.__downloadFilename = filename; };
globalThis.attachToTab = attachToTab;
1 change: 1 addition & 0 deletions packages/stagecraft/AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ Run `help` via MCP to get the full list. Key commands for recording flows:
| `select <text\|ref> <value>` | Select dropdown option |
| `verify-text <text>` | Assert text is present |
| `download-as <filename>` | Set filename for next browser download |
| `wait-download` | Wait for download to complete; returns full saved path |
| `start-recording [file]` | Begin recording to .pw file |
| `stop-recording` | Save recording |
| `pause-recording` | Pause/resume |
Expand Down
15 changes: 7 additions & 8 deletions packages/stagecraft/skills/rogers/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@ description: Navigate to MyRogers and download bill PDFs
category: tax/bills/telecom
preconditions: Must be logged into rogers.com (use bridge mode)
parameters:
- billing_periods: list of dates to check (e.g. "January 24, 2026", "February 24, 2026")
output: PDF files downloaded to browser's default download folder
- billing_period: billing period label to download (e.g. "January 24, 2026")
- filename: output filename for the download (e.g. "rogers-2026-01.pdf")
output: Full path to the downloaded PDF file (printed by wait-download)
---

# Download Rogers Bill

Navigates to MyRogers self-serve billing page, opens the Save PDF modal,
selects the requested billing periods, and triggers the download.
checks the requested billing period, downloads the PDF, and returns the saved path.

The agent should:
1. Run the .pw script to navigate to the billing page
2. Read the snapshot to see available billing periods
3. Check the requested periods
4. Click "Download bills"
Use the `.pw` skill for simple single-period downloads. Use the `.js` skill for
multi-period downloads or when you need `download.saveAs(path)` to save outside
the default Downloads folder.

Note: The latest billing period is pre-checked by default.
5 changes: 4 additions & 1 deletion packages/stagecraft/skills/rogers/download-bill.pw
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
# Requires: logged into rogers.com (bridge mode)
#
# Usage:
# replay skills/rogers/download-bill.pw --variable billing_period="January 24, 2026"
# replay skills/rogers/download-bill.pw --variable billing_period="January 24, 2026" --variable filename="rogers-2026-01.pdf"

# Ensure wide viewport — Rogers shows "Save PDF" at desktop width, different text at narrow width
resize 1280 800
goto https://www.rogers.com/consumer/self-serve/overview
click "View your bill" --exact
click "Save PDF"
check "{{billing_period}}"
download-as {{filename}}
click "Download bills"
wait-download
Loading