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
8 changes: 4 additions & 4 deletions .github/workflows/action-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
push:
branches: [main]
paths:
- 'github-action/**'
- 'action.yml'
- '.github/workflows/action-test.yml'
- 'flows/**'
workflow_dispatch:
Expand Down Expand Up @@ -39,7 +39,7 @@ jobs:
- uses: actions/checkout@v4

# Use the local action definition (same repo, same commit)
- uses: ./github-action
- uses: ./
id: run
with:
flow: ${{ github.event.inputs.flow || 'flows/youtube.yaml' }}
Expand All @@ -61,7 +61,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: ./github-action
- uses: ./
id: run
with:
goal: 'Open YouTube app and verify the home feed is visible'
Expand All @@ -84,7 +84,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: ./github-action
- uses: ./
id: run
with:
flow: ${{ github.event.inputs.flow || 'flows/youtube.yaml' }}
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/layer3-branch-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: ./github-action
- uses: ./
id: run
with:
use-local-build: 'true'
Expand All @@ -55,7 +55,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: ./github-action
- uses: ./
id: run
with:
use-local-build: 'true'
Expand All @@ -75,17 +75,19 @@ jobs:
ios-flow:
name: iOS — YAML flow
runs-on: macos-14
if: github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && inputs.platform == 'ios')
if: false

steps:
- uses: actions/checkout@v4

- uses: ./github-action
- uses: ./
id: run
with:
use-local-build: 'true'
flow: ${{ inputs.flow || 'flows/wdio.yaml' }}
platform: ios
ios-device-type: simulator
mcp-debug: 'true'
provider: gemini
agent-mode: vision
api-key: ${{ secrets.LLM_API_KEY }}
Expand Down
26 changes: 13 additions & 13 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@

### Features

* add action.yml at repo root for GitHub Marketplace publishing ([#20](https://github.com/AppiumTestDistribution/AppClaw/issues/20)) ([c007399](https://github.com/AppiumTestDistribution/AppClaw/commit/c007399fa670273058cd51e65f0fd68323ccb3be))
- add action.yml at repo root for GitHub Marketplace publishing ([#20](https://github.com/AppiumTestDistribution/AppClaw/issues/20)) ([c007399](https://github.com/AppiumTestDistribution/AppClaw/commit/c007399fa670273058cd51e65f0fd68323ccb3be))

## 1.0.0 (2026-04-16)

### Features

* integrate ai-sdk-ollama for LLM support and update configuration ([#9](https://github.com/AppiumTestDistribution/AppClaw/issues/9)) ([c6794d7](https://github.com/AppiumTestDistribution/AppClaw/commit/c6794d718a37ef690c09f5fb006c8994c78e361b))
* parallel testing support and screen recording for SDK ([#16](https://github.com/AppiumTestDistribution/AppClaw/issues/16)) ([7d14e7b](https://github.com/AppiumTestDistribution/AppClaw/commit/7d14e7b760c41783c61f1227c037e1b28d184a5c))
* strict playground tap matching, waitUntil pre-check, faster vision assert ([59b8c29](https://github.com/AppiumTestDistribution/AppClaw/commit/59b8c299bf20c9232d89bbbb4d93a9ef600cca2b))
* vision improvements — drag support, screenshot optimization, an… ([#7](https://github.com/AppiumTestDistribution/AppClaw/issues/7)) ([8cfbcb4](https://github.com/AppiumTestDistribution/AppClaw/commit/8cfbcb483fce0dec531ad8c21c8cd93d5743d62f))
- integrate ai-sdk-ollama for LLM support and update configuration ([#9](https://github.com/AppiumTestDistribution/AppClaw/issues/9)) ([c6794d7](https://github.com/AppiumTestDistribution/AppClaw/commit/c6794d718a37ef690c09f5fb006c8994c78e361b))
- parallel testing support and screen recording for SDK ([#16](https://github.com/AppiumTestDistribution/AppClaw/issues/16)) ([7d14e7b](https://github.com/AppiumTestDistribution/AppClaw/commit/7d14e7b760c41783c61f1227c037e1b28d184a5c))
- strict playground tap matching, waitUntil pre-check, faster vision assert ([59b8c29](https://github.com/AppiumTestDistribution/AppClaw/commit/59b8c299bf20c9232d89bbbb4d93a9ef600cca2b))
- vision improvements — drag support, screenshot optimization, an… ([#7](https://github.com/AppiumTestDistribution/AppClaw/issues/7)) ([8cfbcb4](https://github.com/AppiumTestDistribution/AppClaw/commit/8cfbcb483fce0dec531ad8c21c8cd93d5743d62f))

### Bug Fixes

* add semantic-release for automated versioning and npm publishing ([#19](https://github.com/AppiumTestDistribution/AppClaw/issues/19)) ([66c73a6](https://github.com/AppiumTestDistribution/AppClaw/commit/66c73a677e763112c4fab80dd29301f3d2071532))
* ci ([#10](https://github.com/AppiumTestDistribution/AppClaw/issues/10)) ([dfcd62f](https://github.com/AppiumTestDistribution/AppClaw/commit/dfcd62fa083d673c98fc0c381820c7dd58d36818))
* DOM locator resolution, vision assert parsing, and appium-mcp coordinate scaling ([9272c36](https://github.com/AppiumTestDistribution/AppClaw/commit/9272c36b65e7bd996b730bb6d67d0fa6fee9518a))
* read CLI version from package.json instead of hardcoded string ([#14](https://github.com/AppiumTestDistribution/AppClaw/issues/14)) ([fcb3a64](https://github.com/AppiumTestDistribution/AppClaw/commit/fcb3a6417ddc48d72d246bc9fd5dd1438020635d))
* screenshot parsing ([e449a23](https://github.com/AppiumTestDistribution/AppClaw/commit/e449a2341fc67e193f1519bae16d4cace878bcfc))
* scroll-aware stuck detection, press_enter tool, and post-done verification ([c03bbe4](https://github.com/AppiumTestDistribution/AppClaw/commit/c03bbe4222ce7fd7bba6867f7d1e59ac5ef3c8ee))
* terminal UI ([294a780](https://github.com/AppiumTestDistribution/AppClaw/commit/294a780113d8afdb99b80cf57b47db5b3fe12dc2))
* terminal view ([42c0e75](https://github.com/AppiumTestDistribution/AppClaw/commit/42c0e75e2d8a28c569b6511891628c1b98380cc3))
- add semantic-release for automated versioning and npm publishing ([#19](https://github.com/AppiumTestDistribution/AppClaw/issues/19)) ([66c73a6](https://github.com/AppiumTestDistribution/AppClaw/commit/66c73a677e763112c4fab80dd29301f3d2071532))
- ci ([#10](https://github.com/AppiumTestDistribution/AppClaw/issues/10)) ([dfcd62f](https://github.com/AppiumTestDistribution/AppClaw/commit/dfcd62fa083d673c98fc0c381820c7dd58d36818))
- DOM locator resolution, vision assert parsing, and appium-mcp coordinate scaling ([9272c36](https://github.com/AppiumTestDistribution/AppClaw/commit/9272c36b65e7bd996b730bb6d67d0fa6fee9518a))
- read CLI version from package.json instead of hardcoded string ([#14](https://github.com/AppiumTestDistribution/AppClaw/issues/14)) ([fcb3a64](https://github.com/AppiumTestDistribution/AppClaw/commit/fcb3a6417ddc48d72d246bc9fd5dd1438020635d))
- screenshot parsing ([e449a23](https://github.com/AppiumTestDistribution/AppClaw/commit/e449a2341fc67e193f1519bae16d4cace878bcfc))
- scroll-aware stuck detection, press_enter tool, and post-done verification ([c03bbe4](https://github.com/AppiumTestDistribution/AppClaw/commit/c03bbe4222ce7fd7bba6867f7d1e59ac5ef3c8ee))
- terminal UI ([294a780](https://github.com/AppiumTestDistribution/AppClaw/commit/294a780113d8afdb99b80cf57b47db5b3fe12dc2))
- terminal view ([42c0e75](https://github.com/AppiumTestDistribution/AppClaw/commit/42c0e75e2d8a28c569b6511891628c1b98380cc3))
138 changes: 130 additions & 8 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,40 @@ inputs:
required: false
default: '500'

# ── Debug ────────────────────────────────────────────────────────────────────
mcp-debug:
description: 'Enable MCP debug logging (MCP_DEBUG=1). Default: false'
required: false
default: 'false'
mcp-timeout-ms:
description: 'MCP request timeout in milliseconds. Default: 300000'
required: false
default: '300000'
llm-thinking:
description: 'Enable LLM extended thinking: on or off. Default: off'
required: false
default: 'off'

# ── iOS device ───────────────────────────────────────────────────────────────
ios-device-type:
description: 'iOS device type: simulator or real. Default: simulator'
required: false
default: 'simulator'

# ── iOS simulator ────────────────────────────────────────────────────────────
device-udid:
description: 'Explicit device/simulator UDID to target. Leave empty to let AppClaw auto-detect.'
required: false
default: ''
ios-simulator-name:
description: 'iOS simulator device model to boot (e.g. "iPhone 16", "iPhone 15 Pro"). Default: iPhone 16'
required: false
default: 'iPhone 16'
ios-simulator-os:
description: 'iOS version to use when multiple runtimes are available (e.g. "18.4", "17.5"). Default: latest available'
required: false
default: ''

# ── Android emulator ─────────────────────────────────────────────────────────
android-api-level:
description: 'Android emulator API level. Default: 33 (Android 13)'
Expand Down Expand Up @@ -191,7 +225,7 @@ runs:
LLM_PROVIDER: ${{ inputs.provider }}
LLM_API_KEY: ${{ inputs.api-key }}
LLM_MODEL: ${{ inputs.model }}
LLM_THINKING: 'off'
LLM_THINKING: ${{ inputs.llm-thinking }}
AGENT_MODE: ${{ inputs.agent-mode }}
MAX_STEPS: ${{ inputs.max-steps }}
STEP_DELAY: ${{ inputs.step-delay }}
Expand All @@ -212,7 +246,7 @@ runs:
LLM_PROVIDER: ${{ inputs.provider }}
LLM_API_KEY: ${{ inputs.api-key }}
LLM_MODEL: ${{ inputs.model }}
LLM_THINKING: 'off'
LLM_THINKING: ${{ inputs.llm-thinking }}
AGENT_MODE: ${{ inputs.agent-mode }}
MAX_STEPS: ${{ inputs.max-steps }}
STEP_DELAY: ${{ inputs.step-delay }}
Expand Down Expand Up @@ -243,7 +277,7 @@ runs:
LLM_PROVIDER: ${{ inputs.provider }}
LLM_API_KEY: ${{ inputs.api-key }}
LLM_MODEL: ${{ inputs.model }}
LLM_THINKING: 'off'
LLM_THINKING: ${{ inputs.llm-thinking }}
AGENT_MODE: ${{ inputs.agent-mode }}
MAX_STEPS: ${{ inputs.max-steps }}
STEP_DELAY: ${{ inputs.step-delay }}
Expand All @@ -265,7 +299,7 @@ runs:
LLM_PROVIDER: ${{ inputs.provider }}
LLM_API_KEY: ${{ inputs.api-key }}
LLM_MODEL: ${{ inputs.model }}
LLM_THINKING: 'off'
LLM_THINKING: ${{ inputs.llm-thinking }}
AGENT_MODE: ${{ inputs.agent-mode }}
MAX_STEPS: ${{ inputs.max-steps }}
STEP_DELAY: ${{ inputs.step-delay }}
Expand All @@ -279,6 +313,88 @@ runs:
disable-animations: true
script: appclaw "${{ inputs.goal }}" --platform android

# ── iOS — pre-download WebDriverAgent ────────────────────────────────────
- name: Download prebuilt WebDriverAgent for iOS simulator
if: inputs.platform == 'ios' && inputs.cloud-provider == ''
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
# Resolve latest WDA version via GitHub API (authenticated = 5000/hr, no rate-limit risk)
WDA_VERSION=$(curl -fsSL \
-H "Authorization: Bearer ${GH_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/appium/WebDriverAgent/releases/latest" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['tag_name'].lstrip('v'))")

if [ -z "$WDA_VERSION" ]; then
echo "::error::Could not resolve latest WDA version from GitHub"
exit 1
fi

ARCH=$(uname -m) # arm64 on macos-14 (Apple Silicon), x86_64 otherwise
URL="https://github.com/appium/WebDriverAgent/releases/download/v${WDA_VERSION}/WebDriverAgentRunner-Build-Sim-${ARCH}.zip"

echo "Downloading prebuilt WDA v${WDA_VERSION} for ${ARCH}..."
curl -fsSL "${URL}" -o /tmp/wda.zip
unzip -q /tmp/wda.zip -d /tmp/wda

WDA_APP="/tmp/wda/WebDriverAgentRunner-Runner.app"
if [ ! -d "$WDA_APP" ]; then
echo "::error::WebDriverAgentRunner-Runner.app not found after extraction"
ls -la /tmp/wda/
exit 1
fi

echo "APPIUM_MCP_WDA_APP_PATH=${WDA_APP}" >> $GITHUB_ENV
echo "WDA pre-downloaded: ${WDA_APP}"

# ── iOS — boot simulator ─────────────────────────────────────────────────
- name: Boot iOS simulator
if: inputs.platform == 'ios' && inputs.cloud-provider == '' && inputs.ios-device-type == 'simulator'
shell: bash
env:
SIM_NAME: ${{ inputs.ios-simulator-name }}
SIM_OS: ${{ inputs.ios-simulator-os }}
run: |
xcrun simctl list devices available -j > /tmp/simctl_devices.json

UDID=$(python3 <<'EOF'
import json, os, re, sys
sim_name = os.environ.get('SIM_NAME', 'iPhone 16').lower()
sim_os = os.environ.get('SIM_OS', '').strip()
data = json.load(open('/tmp/simctl_devices.json'))
candidates = []
for runtime, devs in data['devices'].items():
if 'iOS' not in runtime:
continue
# Extract version from runtime key, e.g. "com.apple.CoreSimulator.SimRuntime.iOS-18-4" → "18.4"
m = re.search(r'iOS[- ]([\d][\d.-]+)', runtime, re.IGNORECASE)
ver = m.group(1).replace('-', '.') if m else ''
if sim_os and not ver.startswith(sim_os):
continue
for d in devs:
if d.get('isAvailable') and sim_name in d.get('name', '').lower():
candidates.append((ver, d['udid']))
if not candidates:
sys.exit(1)
# Pick highest iOS version
candidates.sort(key=lambda x: [int(p) for p in x[0].split('.') if p.isdigit()], reverse=True)
print(candidates[0][1])
EOF
)

if [ -z "$UDID" ]; then
echo "::error::No available iOS simulator matching name='${SIM_NAME}' os='${SIM_OS}'"
xcrun simctl list devices available
exit 1
fi

echo "Booting simulator $UDID (${SIM_NAME})"
xcrun simctl boot "$UDID" 2>/dev/null || true # already Booted is OK
xcrun simctl bootstatus "$UDID" -b # block until fully booted
echo "IOS_SIMULATOR_UDID=$UDID" >> "$GITHUB_ENV"

# ── iOS — YAML flow ───────────────────────────────────────────────────────
- name: Run YAML flow on iOS simulator
if: inputs.platform == 'ios' && inputs.cloud-provider == '' && inputs.flow != ''
Expand All @@ -287,12 +403,15 @@ runs:
LLM_PROVIDER: ${{ inputs.provider }}
LLM_API_KEY: ${{ inputs.api-key }}
LLM_MODEL: ${{ inputs.model }}
LLM_THINKING: 'off'
LLM_THINKING: ${{ inputs.llm-thinking }}
AGENT_MODE: ${{ inputs.agent-mode }}
MAX_STEPS: ${{ inputs.max-steps }}
STEP_DELAY: ${{ inputs.step-delay }}
PLATFORM: ios
DEVICE_TYPE: simulator
DEVICE_TYPE: ${{ inputs.ios-device-type }}
DEVICE_UDID: ${{ inputs.device-udid || env.IOS_SIMULATOR_UDID }}
MCP_DEBUG: ${{ inputs.mcp-debug == 'true' && '1' || '0' }}
MCP_TIMEOUT_MS: ${{ inputs.mcp-timeout-ms }}
run: appclaw --flow "${{ inputs.flow }}" --platform ios

# ── iOS — natural language goal ───────────────────────────────────────────
Expand All @@ -303,12 +422,15 @@ runs:
LLM_PROVIDER: ${{ inputs.provider }}
LLM_API_KEY: ${{ inputs.api-key }}
LLM_MODEL: ${{ inputs.model }}
LLM_THINKING: 'off'
LLM_THINKING: ${{ inputs.llm-thinking }}
AGENT_MODE: ${{ inputs.agent-mode }}
MAX_STEPS: ${{ inputs.max-steps }}
STEP_DELAY: ${{ inputs.step-delay }}
PLATFORM: ios
DEVICE_TYPE: simulator
DEVICE_TYPE: ${{ inputs.ios-device-type }}
DEVICE_UDID: ${{ inputs.device-udid || env.IOS_SIMULATOR_UDID }}
MCP_DEBUG: ${{ inputs.mcp-debug == 'true' && '1' || '0' }}
MCP_TIMEOUT_MS: ${{ inputs.mcp-timeout-ms }}
run: appclaw "${{ inputs.goal }}" --platform ios

# ── Report ────────────────────────────────────────────────────────────────
Expand Down
Loading
Loading