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
145 changes: 145 additions & 0 deletions .github/workflows/feature-parity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: Feature Parity

on:
pull_request:
types:
- opened
- synchronize
- labeled
- unlabeled

jobs:
check-parity-label:
runs-on: ubuntu-latest
if: github.event.action == 'labeled' && github.event.label.name == 'parity'
permissions:
contents: read
pull-requests: write
issues: write
steps:
- name: Check out repository code
uses: actions/checkout@v4

- name: Check user permissions
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: context.actor
});

const hasWriteAccess = ['admin', 'write'].includes(permission.permission);

if (!hasWriteAccess) {
// Remove the parity label if user doesn't have write access
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
name: 'parity'
});

// Add a comment explaining why the label was removed
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `❌ **Parity Label Removed**\n\n@${context.actor}, you do not have sufficient permissions to add the 'parity' label. Only users with write access can trigger feature parity issues.\n\nIf you believe this feature should be implemented in the Python SDK, please ask a maintainer to add the label.`
});

throw new Error(`User ${context.actor} does not have write access to add parity label`);
}

console.log(`User ${context.actor} has ${permission.permission} access - proceeding with parity workflow`);

- name: Generate GitHub App token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.PARITY_APP_ID }}
private-key: ${{ secrets.PARITY_APP_PRIVATE_KEY }}
owner: browserbase
repositories: stagehand

- name: Create issue in Python SDK repository
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});

// Get PR comments for additional context
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

// Format comments for the issue description
let commentsSection = '';
if (comments.length > 0) {
commentsSection = '\n\n## Recent Comments\n\n';
comments.slice(-3).forEach(comment => {
commentsSection += `**@${comment.user.login}** commented:\n`;
commentsSection += `${comment.body.substring(0, 500)}${comment.body.length > 500 ? '...' : ''}\n\n`;
});
}

// Get list of changed files for context
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});

const changedFiles = files.map(file => `- \`${file.filename}\``).join('\n');

const issueTitle = `[Feature Parity] ${pullRequest.title}`;
const issueBody = `## Feature Parity Request

This issue was automatically created from a pull request in the TypeScript Stagehand repository that was labeled with 'parity'.

### Original PR Details
- **PR**: #${context.issue.number} - ${pullRequest.title}
- **Author**: @${pullRequest.user.login}
- **Link**: ${pullRequest.html_url}

### Description
${pullRequest.body || 'No description provided.'}

### Changed Files
${changedFiles}

${commentsSection}

### Action Required
Please review the changes in the original PR and implement equivalent functionality in the Python SDK if applicable.

---
*This issue was automatically generated by the Feature Parity workflow.*`;

// Create the issue in the Python repository
const { data: issue } = await github.rest.issues.create({
owner: 'browserbase',
repo: 'stagehand',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be stagehand-python ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will open an issue in the sibling repo

title: issueTitle,
body: issueBody,
labels: ['feature-parity']
});

console.log(`Created issue: ${issue.html_url}`);

// Add a comment to the original PR confirming the issue was created
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `🔄 **Feature Parity Issue Created**\n\nAn issue has been automatically created in the Python SDK repository to track parity implementation:\n${issue.html_url}`
});
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,26 @@
</a>
</p>

> Stagehand Python is now available! We're actively seeking feedback from the community and looking for contributors. Join our [Slack community](https://stagehand.dev/slack) to stay updated on the latest updates
<p align="center">
If you're looking for the TypeScript implementation, you can find it
<a href="https://github.com/browserbase/stagehand"> here</a>
</p>

<div align="center" style="display: flex; align-items: center; justify-content: center; gap: 4px; margin-bottom: 0;">
<b>Vibe code</b>
<span style="font-size: 1.05em;"> Stagehand with </span>
<a href="https://director.ai" style="display: flex; align-items: center;">
<span>Director</span>
</a>
<span> </span>
<picture>
<img alt="Director" src="media/director_icon.svg" width="25" />
</picture>
</div>


## Why Stagehand?

*Stagehand is the easiest way to build browser automations with AI-powered interactions.*

Most existing browser automation tools either require you to write low-level code in a framework like Selenium, Playwright, or Puppeteer, or use high-level agents that can be unpredictable in production. By letting developers choose what to write in code vs. natural language, Stagehand is the natural choice for browser automations in production.

1. **Choose when to write code vs. natural language**: use AI when you want to navigate unfamiliar pages, and use code ([Playwright](https://playwright.dev/)) when you know exactly what you want to do.
Expand Down
13 changes: 13 additions & 0 deletions media/director_icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.