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
85 changes: 85 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Release to PyPI

on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 0.1.0)'
required: true
type: string

jobs:
build-and-publish:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine

- name: Extract version from tag or input
id: version
run: |
if [ "${{ github.event_name }}" == "release" ]; then
VERSION=${GITHUB_REF#refs/tags/v}
VERSION=${VERSION#refs/tags/}
else
VERSION="${{ github.event.inputs.version }}"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version: $VERSION"

- name: Update version in pyproject.toml
run: |
VERSION="${{ steps.version.outputs.version }}"
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml

- name: Update version in __init__.py
run: |
VERSION="${{ steps.version.outputs.version }}"
sed -i "s/^__version__ = \".*\"/__version__ = \"$VERSION\"/" sentience/__init__.py

- name: Build package
run: |
python -m build

- name: Check package
run: |
twine check dist/*

- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
twine upload dist/*

- name: Create GitHub Release
if: github.event_name == 'workflow_dispatch'
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.version.outputs.version }}
name: Release v${{ steps.version.outputs.version }}
body: |
Release v${{ steps.version.outputs.version }} of sentience-python

## Installation
```bash
pip install sentience-python==${{ steps.version.outputs.version }}
```
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

49 changes: 49 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Test

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.11']

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Playwright browsers
run: |
python -m pip install --upgrade pip
pip install playwright
playwright install chromium

- name: Install dependencies
run: |
pip install -e ".[dev]"

- name: Build extension (if needed)
run: |
if [ -d "../sentience-chrome" ]; then
cd ../sentience-chrome && ./build.sh || echo "Extension build skipped (may not be available in CI)"
else
echo "Extension directory not found, skipping build"
fi

- name: Run tests
run: |
pytest tests/ -v
env:
CI: true

56 changes: 18 additions & 38 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
# Python
# Ignore __pycache__ directories at any level
__pycache__/
**/__pycache__/
# Ignore Python cache files
*.py[cod]
*.pyc
*.pyo
*.pyd
*$py.class
*.so
.Python

# Distribution / packaging
build/
develop-eggs/
dist/
Expand All @@ -24,51 +16,39 @@ parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
*.manifest
*.spec

# Unit test / coverage reports
.pytest_cache/
.coverage
.coverage.*
.cache
htmlcov/
.tox/
.nox/
coverage/
*.cover
*.py,cover
.hypothesis/

# Virtual environments
.env
.venv
env/
venv/
env/
ENV/
env.bak/
venv.bak/
.venv

# IDEs
# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/

# Jupyter
.ipynb_checkpoints

# Environment
.env
.env.local

# OS
.DS_Store
Thumbs.db

# Project specific
snapshot_*.json
*.log

# Playwright
.playwright/
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include README.md
include LICENSE
recursive-include spec *
recursive-include sentience *.py

20 changes: 18 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,19 @@ name = "sentience-python"
version = "0.1.0"
description = "Python SDK for Sentience AI Agent Browser Automation"
readme = "README.md"
requires-python = ">=3.8"
requires-python = ">=3.11"
license = {text = "MIT"}
authors = [
{name = "Sentience Team"}
]
keywords = ["browser-automation", "playwright", "ai-agent", "web-automation", "sentience"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
]
dependencies = [
"playwright>=1.40.0",
"pydantic>=2.0.0",
Expand All @@ -16,6 +28,11 @@ dependencies = [
"playwright-stealth>=1.0.6", # Bot evasion and stealth mode
]

[project.urls]
Homepage = "https://github.com/SentienceAPI/sentience-python"
Repository = "https://github.com/SentienceAPI/sentience-python"
Issues = "https://github.com/SentienceAPI/sentience-python/issues"

[project.scripts]
sentience = "sentience.cli:main"

Expand All @@ -28,4 +45,3 @@ dev = [
[tool.setuptools.packages.find]
where = ["."]
include = ["sentience*"]

72 changes: 72 additions & 0 deletions spec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Sentience API Specification

This directory contains the **single source of truth** for the API contract between the Chrome extension and SDKs.

## Files

- **`snapshot.schema.json`** - JSON Schema for snapshot response validation
- **`SNAPSHOT_V1.md`** - Human-readable snapshot API contract
- **`sdk-types.md`** - SDK-level type definitions (ActionResult, WaitResult, TraceStep)

## Purpose

These specifications ensure:
1. **Consistency**: Both Python and TypeScript SDKs implement the same contract
2. **Validation**: SDKs can validate extension responses
3. **Type Safety**: Strong typing in both languages
4. **Documentation**: Clear reference for developers

## Usage

### For SDK Developers

1. **Read** `SNAPSHOT_V1.md` for human-readable contract
2. **Use** `snapshot.schema.json` for JSON Schema validation
3. **Reference** `sdk-types.md` for SDK-level types

### For Extension Developers

1. **Ensure** extension output matches `snapshot.schema.json`
2. **Update** schema when adding new fields
3. **Version** schema for breaking changes

## Versioning

- **v1.0.0**: Initial stable version (Day 1)
- Future versions: Increment major version for breaking changes
- SDKs should validate version and handle compatibility

## Validation

Both SDKs should validate extension responses:

**Python**:
```python
import jsonschema
from spec.snapshot.schema import load_schema

schema = load_schema()
jsonschema.validate(snapshot_data, schema)
```

**TypeScript**:
```typescript
import Ajv from 'ajv';
import schema from './spec/snapshot.schema.json';

const ajv = new Ajv();
const validate = ajv.compile(schema);
validate(snapshot_data);
```

## Testing

- Validate against real extension output
- Test with edge cases (empty pages, many elements, errors)
- Verify type coercion and defaults

---

**Last Updated**: Day 1 Implementation
**Status**: ✅ Stable

Loading
Loading