From 0f38335bd9aa08c06a8ed2a5f2151d1d03b60cb8 Mon Sep 17 00:00:00 2001 From: rcholic Date: Sun, 21 Dec 2025 15:16:17 -0800 Subject: [PATCH] sync extensions --- .github/workflows/sync-extension.yml | 123 +++++++++++++++++++++++++++ src/browser.ts | 48 ++++++++--- 2 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/sync-extension.yml diff --git a/.github/workflows/sync-extension.yml b/.github/workflows/sync-extension.yml new file mode 100644 index 00000000..7fa2ff87 --- /dev/null +++ b/.github/workflows/sync-extension.yml @@ -0,0 +1,123 @@ +name: Sync Extension from sentience-chrome + +on: + repository_dispatch: + types: [extension-updated] + workflow_dispatch: + inputs: + release_tag: + description: 'Release tag from sentience-chrome (e.g., v1.0.0)' + required: true + type: string + schedule: + # Check for new releases daily at 2 AM UTC + - cron: '0 2 * * *' + +jobs: + sync-extension: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout sdk-ts + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Determine release tag + id: release + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + TAG="${{ github.event.inputs.release_tag }}" + elif [ "${{ github.event_name }}" == "repository_dispatch" ]; then + TAG="${{ github.event.client_payload.release_tag }}" + else + # Scheduled check - get latest release + TAG=$(curl -s https://api.github.com/repos/${{ secrets.SENTIENCE_CHROME_REPO }}/releases/latest | jq -r '.tag_name // empty') + fi + + if [ -z "$TAG" ] || [ "$TAG" == "null" ]; then + echo "No release found, skipping" + echo "skip=true" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "tag=$TAG" >> $GITHUB_OUTPUT + echo "Release tag: $TAG" + + - name: Download extension files + if: steps.release.outputs.skip != 'true' + run: | + TAG="${{ steps.release.outputs.tag }}" + REPO="${{ secrets.SENTIENCE_CHROME_REPO }}" + + # Download release assets + mkdir -p extension-temp + cd extension-temp + + # Download each file from release + curl -L -H "Authorization: token ${{ secrets.SENTIENCE_CHROME_TOKEN }}" \ + "https://api.github.com/repos/$REPO/releases/tags/$TAG" | \ + jq -r '.assets[] | select(.name | endswith(".js") or endswith(".wasm") or endswith(".json") or endswith(".d.ts")) | .browser_download_url' | \ + while read url; do + filename=$(basename "$url") + curl -L -H "Authorization: token ${{ secrets.SENTIENCE_CHROME_TOKEN }}" "$url" -o "$filename" + done + + - name: Copy extension files + if: steps.release.outputs.skip != 'true' + run: | + # Create extension directory structure + mkdir -p src/extension/pkg + + # Copy extension files + cp extension-temp/manifest.json src/extension/ 2>/dev/null || echo "manifest.json not found in release" + cp extension-temp/content.js src/extension/ 2>/dev/null || echo "content.js not found in release" + cp extension-temp/background.js src/extension/ 2>/dev/null || echo "background.js not found in release" + cp extension-temp/injected_api.js src/extension/ 2>/dev/null || echo "injected_api.js not found in release" + + # Copy WASM files + cp extension-temp/pkg/sentience_core.js src/extension/pkg/ 2>/dev/null || echo "sentience_core.js not found" + cp extension-temp/pkg/sentience_core_bg.wasm src/extension/pkg/ 2>/dev/null || echo "sentience_core_bg.wasm not found" + cp extension-temp/pkg/*.d.ts src/extension/pkg/ 2>/dev/null || echo "Type definitions not found" + + - name: Check for changes + if: steps.release.outputs.skip != 'true' + id: changes + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add src/extension/ || true + if git diff --staged --quiet; then + echo "changed=false" >> $GITHUB_OUTPUT + echo "No changes detected" + else + echo "changed=true" >> $GITHUB_OUTPUT + echo "Changes detected" + fi + + - name: Create Pull Request + if: steps.release.outputs.skip != 'true' && steps.changes.outputs.changed == 'true' + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "chore: sync extension files from sentience-chrome ${{ steps.release.outputs.tag }}" + title: "Sync Extension: ${{ steps.release.outputs.tag }}" + body: | + This PR syncs extension files from sentience-chrome release ${{ steps.release.outputs.tag }}. + + **Files updated:** + - Extension manifest and scripts + - WASM binary and bindings + + **Source:** [sentience-chrome release ${{ steps.release.outputs.tag }}](${{ secrets.SENTIENCE_CHROME_REPO }}/releases/tag/${{ steps.release.outputs.tag }}) + branch: sync-extension-${{ steps.release.outputs.tag }} + delete-branch: true + diff --git a/src/browser.ts b/src/browser.ts index 091f1e90..8c9be5f1 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -34,22 +34,44 @@ export class SentienceBrowser { } async start(): Promise { - // Get extension source path (relative to project root) + // Try to find extension in multiple locations: + // 1. Embedded extension (src/extension/) - for production/CI + // 2. Development mode (../sentience-chrome/) - for local development + // Handle both ts-node (src/) and compiled (dist/src/) cases + let sdkRoot: string; let repoRoot: string; if (__dirname.includes('dist')) { - // Compiled: dist/src/ -> go up 3 levels to project root (Sentience/) - repoRoot = path.resolve(__dirname, '../../..'); + // Compiled: dist/src/ -> go up 2 levels to sdk-ts/ + sdkRoot = path.resolve(__dirname, '../..'); + // Go up 1 more level to project root (Sentience/) + repoRoot = path.resolve(sdkRoot, '..'); } else { - // ts-node: src/ -> go up 2 levels to project root (Sentience/) - repoRoot = path.resolve(__dirname, '../..'); + // ts-node: src/ -> go up 1 level to sdk-ts/ + sdkRoot = path.resolve(__dirname, '..'); + // Go up 1 more level to project root (Sentience/) + repoRoot = path.resolve(sdkRoot, '..'); } - const extensionSource = path.join(repoRoot, 'sentience-chrome'); - - if (!fs.existsSync(extensionSource)) { + + // Check for embedded extension first (production/CI) + const embeddedExtension = path.join(sdkRoot, 'src', 'extension'); + + // Check for development extension (local development) + const devExtension = path.join(repoRoot, 'sentience-chrome'); + + // Prefer embedded extension, fall back to dev extension + let extensionSource: string; + if (fs.existsSync(embeddedExtension) && fs.existsSync(path.join(embeddedExtension, 'manifest.json'))) { + extensionSource = embeddedExtension; + } else if (fs.existsSync(devExtension) && fs.existsSync(path.join(devExtension, 'manifest.json'))) { + extensionSource = devExtension; + } else { throw new Error( - `Extension not found at ${extensionSource}. ` + - 'Make sure sentience-chrome directory exists.' + `Extension not found. Checked:\n` + + ` 1. ${embeddedExtension}\n` + + ` 2. ${devExtension}\n` + + 'Make sure extension files are available. ' + + 'For development: cd ../sentience-chrome && ./build.sh' ); } @@ -87,7 +109,8 @@ export class SentienceBrowser { if (!fs.existsSync(pkgSource)) { throw new Error( `WASM package directory not found at ${pkgSource}\n` + - 'Make sure to build the extension: cd sentience-chrome && ./build.sh' + 'Make sure extension files are available. ' + + 'For development: cd ../sentience-chrome && ./build.sh' ); } @@ -99,7 +122,8 @@ export class SentienceBrowser { `WASM files not found. Expected:\n` + ` - ${wasmJs}\n` + ` - ${wasmBinary}\n` + - 'Make sure to build the extension: cd sentience-chrome && ./build.sh' + 'Make sure extension files are available. ' + + 'For development: cd ../sentience-chrome && ./build.sh' ); }