From 7564bd975976f81433d357e858e94d29cb4d6057 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Jun 2026 23:33:17 +0000 Subject: [PATCH 1/8] feat: add supertonic TTS shared workflow and daily-news voice summary Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/daily-news.lock.yml | 40 +++-- .github/workflows/daily-news.md | 55 ++++++- .github/workflows/shared/supertonic.md | 203 +++++++++++++++++++++++++ 3 files changed, 285 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/shared/supertonic.md diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index 766142b0d0e..7e40fe24ecf 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"8d41a250f29248203bc447b1d39fe538173aa7b849fdbc6d8c2dadeb04b5d229","body_hash":"5843ee6b9c68bfefd446e6e2e850fe1786319fcad93fded7bf831fea4e9fcf44","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"},"agent_image_runner":"aw-gpu-runner-T4"} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"914690f8952561c05e7e74d81d1500c9fb716283e2e2543feb949bb68c39020d","body_hash":"7451be458e89d34bcecde90ff4a55369b6615a4cf94fb3abed6fb7e714360320","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"},"agent_image_runner":"aw-gpu-runner-T4"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN","TAVILY_API_KEY"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -35,6 +35,7 @@ # - shared/repo-memory-standard.md # - shared/reporting.md # - shared/daily-audit-base.md +# - shared/supertonic.md # - shared/trends.md # # Secrets used: @@ -281,24 +282,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_821dea60e51933e9_EOF' + cat << 'GH_AW_PROMPT_cd53ff158bb0d1a6_EOF' - GH_AW_PROMPT_821dea60e51933e9_EOF + GH_AW_PROMPT_cd53ff158bb0d1a6_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_821dea60e51933e9_EOF' + cat << 'GH_AW_PROMPT_cd53ff158bb0d1a6_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_821dea60e51933e9_EOF + GH_AW_PROMPT_cd53ff158bb0d1a6_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_821dea60e51933e9_EOF' + cat << 'GH_AW_PROMPT_cd53ff158bb0d1a6_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -327,20 +328,21 @@ jobs: {{/if}} - GH_AW_PROMPT_821dea60e51933e9_EOF + GH_AW_PROMPT_cd53ff158bb0d1a6_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_821dea60e51933e9_EOF' + cat << 'GH_AW_PROMPT_cd53ff158bb0d1a6_EOF' {{#runtime-import .github/workflows/shared/mcp/tavily.md}} {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/trends.md}} + {{#runtime-import .github/workflows/shared/supertonic.md}} {{#runtime-import .github/workflows/shared/otlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/python-dataviz.md}} {{#runtime-import .github/shared/editorial.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/daily-news.md}} - GH_AW_PROMPT_821dea60e51933e9_EOF + GH_AW_PROMPT_cd53ff158bb0d1a6_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -529,6 +531,20 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" env: GH_TOKEN: ${{ github.token }} + - name: Install Supertonic with server support + run: | + set -e + mkdir -p /tmp/gh-aw/agent + if [ ! -d /tmp/gh-aw/agent/venv ]; then + python3 -m venv /tmp/gh-aw/agent/venv + fi + echo "/tmp/gh-aw/agent/venv/bin" >> "$GITHUB_PATH" + /tmp/gh-aw/agent/venv/bin/pip install --quiet 'supertonic[serve]' + /tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(f'Supertonic {supertonic.__version__} installed with server support')" + - name: Start Supertonic HTTP server + run: "set -e\n# Start server in background; first run downloads the model (~400MB) from HuggingFace\nnohup /tmp/gh-aw/agent/venv/bin/supertonic serve \\\n --host 127.0.0.1 --port 7788 \\\n > /tmp/gh-aw/agent/supertonic.log 2>&1 &\nSTTC_PID=$!\necho $STTC_PID > /tmp/gh-aw/agent/supertonic.pid\necho \"Supertonic server PID: $STTC_PID β€” logs at /tmp/gh-aw/agent/supertonic.log\"\n" + - name: Wait for Supertonic server readiness + run: "# Allow up to 3 minutes (60 Γ— 3s) to accommodate model download on first run\nURL=\"http://127.0.0.1:7788/docs\"\nSTATUS=\"\"\nfor i in $(seq 1 60); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" \\\n --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Supertonic server ready at http://127.0.0.1:7788\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for Supertonic... ($i/60) (status: $STATUS)\" && sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Supertonic server failed to start after 3 minutes (final status: $STATUS)\"\n cat /tmp/gh-aw/agent/supertonic.log || true\n exit 1\nfi\n" - name: Setup Python environment run: "# Create working directory for Python scripts\nmkdir -p /tmp/gh-aw/python\nmkdir -p /tmp/gh-aw/python/data\nmkdir -p /tmp/gh-aw/python/charts\nmkdir -p /tmp/gh-aw/python/artifacts\n\necho \"Python environment setup complete\"\necho \"Working directory: /tmp/gh-aw/python\"\necho \"Data directory: /tmp/gh-aw/python/data\"\necho \"Charts directory: /tmp/gh-aw/python/charts\"\necho \"Artifacts directory: /tmp/gh-aw/python/artifacts\"\n" - name: Install Python scientific libraries @@ -1020,7 +1036,7 @@ jobs: - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): - timeout-minutes: 30 + timeout-minutes: 50 run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt @@ -1072,7 +1088,7 @@ jobs: GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_TIMEOUT_MINUTES: 30 + GH_AW_TIMEOUT_MINUTES: 50 GH_AW_VERSION: dev GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true @@ -1552,7 +1568,7 @@ jobs: GH_AW_FAILURE_REPORT_AS_ISSUE: "true" GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" - GH_AW_TIMEOUT_MINUTES: "30" + GH_AW_TIMEOUT_MINUTES: "50" GH_AW_CACHE_MEMORY_ENABLED: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/daily-news.md b/.github/workflows/daily-news.md index 328c238b82f..cad95929fa2 100644 --- a/.github/workflows/daily-news.md +++ b/.github/workflows/daily-news.md @@ -20,7 +20,7 @@ engine: id: copilot bare: true -timeout-minutes: 30 # Reduced from 45 since pre-fetching data is faster +timeout-minutes: 50 # Increased from 30 to accommodate Supertonic model download (~400MB) and TTS synthesis experiments: prompt_style: variants: [detailed, concise] @@ -319,6 +319,7 @@ imports: title-prefix: "[daily-news] " expires: 3d - shared/trends.md + - shared/supertonic.md - shared/otlp.md --- @@ -551,4 +552,56 @@ Create a new GitHub discussion with a title containing today's date (e.g., "Dail Only a new discussion should be created, do not close or update any existing discussions. {{/if}} +## πŸ”Š Voice Summary + +After creating the discussion, generate a short spoken summary of the day's news using the Supertonic TTS server (already running at `http://127.0.0.1:7788`). + +### Step 1 β€” Write the summary script + +Compose a concise spoken summary (2–4 sentences) covering the headline metrics and most notable event of the day. Keep it natural and conversational β€” this is text-to-speech, not markdown. + +Example: +> "Good morning! Today in the gh-aw repository, 12 pull requests were merged and 8 new issues were opened. The highlight was the release of version 0.47.0, which ships improved MCP Gateway support. Have a productive day!" + +### Step 2 β€” Synthesize the audio + +```bash +mkdir -p /tmp/gh-aw/agent +curl -sS -X POST http://127.0.0.1:7788/v1/tts \ + -H 'content-type: application/json' \ + -d "{\"text\": \"\", \"voice\": \"F1\", \"lang\": \"en\", \"steps\": 8}" \ + -o /tmp/gh-aw/agent/daily-voice-summary.wav +echo "Voice summary generated: $(ls -lh /tmp/gh-aw/agent/daily-voice-summary.wav)" +``` + +Replace `` with the summary you composed in Step 1. + +### Step 3 β€” Upload as a run artifact + +Stage the file and call the `upload_artifact` safe-output tool: + +```bash +mkdir -p "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts" +cp /tmp/gh-aw/agent/daily-voice-summary.wav \ + "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/daily-voice-summary.wav" +``` + +Call the safe-output tool: +```json +{ "type": "upload_artifact", "path": "daily-voice-summary.wav" } +``` + +### Step 4 β€” Add the artifact link to the discussion + +Update the discussion you created with a final section: + +```markdown +### πŸ”Š Voice Summary + +A spoken version of today's digest is available as a run artifact: +[🎧 Download daily-voice-summary.wav]() +``` + +Replace `` with the `slot_N_artifact_url` returned by the `upload_artifact` tool. + {{#runtime-import shared/noop-reminder.md}} \ No newline at end of file diff --git a/.github/workflows/shared/supertonic.md b/.github/workflows/shared/supertonic.md new file mode 100644 index 00000000000..3759da15978 --- /dev/null +++ b/.github/workflows/shared/supertonic.md @@ -0,0 +1,203 @@ +--- +# Supertonic TTS HTTP Server +# +# Shared workflow that installs the Supertonic Python SDK, downloads the model, +# starts the HTTP server on port 7788, and provides curl instructions. +# +# Usage: +# imports: +# - shared/supertonic.md +# +# This import provides: +# - Supertonic TTS HTTP server on http://127.0.0.1:7788 +# - /v1/tts endpoint (native Supertonic API) +# - /v1/audio/speech endpoint (OpenAI-compatible) +# - 10 built-in voices (M1–M5, F1–F5), 31 languages +# - WAV, FLAC, and OGG output formats +# +# Prerequisites: +# - Python 3.8+ available on runner +# - Network access to pypi.org (python ecosystem) +# - Sufficient disk space (~400MB for model download on first run) +# - Recommended timeout-minutes: β‰₯ 20 to allow model download and server startup +# +# Note: The Supertonic model (~400MB) is downloaded from Hugging Face on the first +# run and cached in ~/.cache/supertonic3/. Subsequent runs are significantly faster. + +tools: + bash: + - "curl *" + - "cat *" + - "echo *" + - "kill *" + - "cp *" + - "mkdir *" + - "ls *" + - "python3 *" + - "python *" + +network: + allowed: + - python + +steps: + - name: Install Supertonic with server support + run: | + set -e + mkdir -p /tmp/gh-aw/agent + if [ ! -d /tmp/gh-aw/agent/venv ]; then + python3 -m venv /tmp/gh-aw/agent/venv + fi + echo "/tmp/gh-aw/agent/venv/bin" >> "$GITHUB_PATH" + /tmp/gh-aw/agent/venv/bin/pip install --quiet 'supertonic[serve]' + /tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(f'Supertonic {supertonic.__version__} installed with server support')" + + - name: Start Supertonic HTTP server + run: | + set -e + # Start server in background; first run downloads the model (~400MB) from HuggingFace + nohup /tmp/gh-aw/agent/venv/bin/supertonic serve \ + --host 127.0.0.1 --port 7788 \ + > /tmp/gh-aw/agent/supertonic.log 2>&1 & + STTC_PID=$! + echo $STTC_PID > /tmp/gh-aw/agent/supertonic.pid + echo "Supertonic server PID: $STTC_PID β€” logs at /tmp/gh-aw/agent/supertonic.log" + + - name: Wait for Supertonic server readiness + run: | + # Allow up to 3 minutes (60 Γ— 3s) to accommodate model download on first run + URL="http://127.0.0.1:7788/docs" + STATUS="" + for i in $(seq 1 60); do + STATUS=$(curl -sS -o /dev/null -w "%{http_code}" \ + --connect-timeout 5 --max-time 5 "$URL" || true) + [ "$STATUS" = "200" ] && echo "Supertonic server ready at http://127.0.0.1:7788" && break + if [ -z "$STATUS" ]; then STATUS="curl_error"; fi + echo "Waiting for Supertonic... ($i/60) (status: $STATUS)" && sleep 3 + done + if [ "$STATUS" != "200" ]; then + echo "Supertonic server failed to start after 3 minutes (final status: $STATUS)" + cat /tmp/gh-aw/agent/supertonic.log || true + exit 1 + fi +--- + +## Supertonic TTS HTTP Server Ready + +The Supertonic text-to-speech HTTP server is running at `http://127.0.0.1:7788`. + +### Generate Audio with curl + +#### Native `/v1/tts` endpoint β€” full Supertonic parameter set + +```bash +curl -X POST http://127.0.0.1:7788/v1/tts \ + -H 'content-type: application/json' \ + -d '{ + "text": "Hello, this is a test of the Supertonic TTS system.", + "voice": "M1", + "lang": "en", + "steps": 8, + "speed": 1.05, + "response_format": "wav" + }' \ + -o /tmp/gh-aw/agent/output.wav +echo "Audio saved to /tmp/gh-aw/agent/output.wav" +``` + +Response headers include: +- `X-Audio-Duration` β€” duration of the generated audio in seconds +- `X-Sample-Rate` β€” sample rate (44100 Hz) +- `X-Supertonic-Version` β€” model version + +#### OpenAI-compatible `/v1/audio/speech` endpoint + +```bash +curl -X POST http://127.0.0.1:7788/v1/audio/speech \ + -H 'content-type: application/json' \ + -d '{ + "model": "supertonic-3", + "input": "Hello, this is a test of the Supertonic TTS system.", + "voice": "M1", + "response_format": "wav" + }' \ + -o /tmp/gh-aw/agent/output.wav +``` + +### Available Endpoints + +| Endpoint | Method | Description | +|---|---|---| +| `/v1/tts` | POST | Native synthesis β€” full Supertonic parameter set | +| `/v1/audio/speech` | POST | OpenAI-compatible speech endpoint | +| `/v1/styles` | GET | List all available voice styles | +| `/v1/styles/import` | POST | Upload a custom voice-style JSON (`multipart/form-data`) | +| `/docs` | GET | Interactive OpenAPI documentation | + +### Built-in Voices (10) + +| Category | Voices | +|---|---| +| **Male** | M1, M2, M3, M4, M5 | +| **Female** | F1, F2, F3, F4, F5 | + +### Supported Languages (31) + +`ar`, `bg`, `hr`, `cs`, `da`, `nl`, `en`, `et`, `fi`, `fr`, `de`, `el`, `hi`, `hu`, `id`, `it`, `ja`, `ko`, `lv`, `lt`, `pl`, `pt`, `ro`, `ru`, `sk`, `sl`, `es`, `sv`, `tr`, `uk`, `vi` + +Pass `"lang": "na"` for automatic language detection. + +### Quality and Speed Controls + +| Parameter | Range | Default | Notes | +|---|---|---|---| +| `steps` | 5–12 | 8 | Higher = better quality, slower synthesis | +| `speed` | 0.7–2.0 | 1.05 | Higher = faster speech | + +### Multilingual Example + +```bash +# English +curl -X POST http://127.0.0.1:7788/v1/tts \ + -H 'content-type: application/json' \ + -d '{"text":"Hello from the Supertonic TTS system!","voice":"F1","lang":"en"}' \ + -o /tmp/gh-aw/agent/english.wav + +# Spanish +curl -X POST http://127.0.0.1:7788/v1/tts \ + -H 'content-type: application/json' \ + -d '{"text":"Β‘Hola desde el sistema Supertonic!","voice":"F1","lang":"es"}' \ + -o /tmp/gh-aw/agent/spanish.wav + +# Auto-detect language +curl -X POST http://127.0.0.1:7788/v1/tts \ + -H 'content-type: application/json' \ + -d '{"text":"γ“γ‚“γ«γ‘γ―γ€γ‚ΉγƒΌγƒ‘γƒΌγƒˆγƒ‹γƒƒγ‚―γ§γ™γ€‚","voice":"M2","lang":"na"}' \ + -o /tmp/gh-aw/agent/japanese.wav +``` + +### Upload Generated Audio as a Run Artifact + +Stage the WAV file and call the `upload_artifact` safe-output tool: + +```bash +# Stage the file for upload +mkdir -p "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts" +cp /tmp/gh-aw/agent/output.wav \ + "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/voice-summary.wav" +``` + +Then call the safe-output tool with: +```json +{ "type": "upload_artifact", "path": "voice-summary.wav" } +``` + +The tool returns `slot_N_artifact_url` β€” a direct download link to the uploaded artifact. +Include this URL in any report or discussion to give readers access to the audio file. + +### Stop the Server (Optional Cleanup) + +```bash +kill $(cat /tmp/gh-aw/agent/supertonic.pid) 2>/dev/null || true +rm -f /tmp/gh-aw/agent/supertonic.pid /tmp/gh-aw/agent/supertonic.log +``` From e962c544ec5fef44f86406cc2576b344cb0c713c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Jun 2026 23:34:54 +0000 Subject: [PATCH 2/8] fix: address review feedback on supertonic workflow and daily-news curl escaping Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/daily-news.lock.yml | 4 ++-- .github/workflows/daily-news.md | 16 +++++++++++++--- .github/workflows/shared/supertonic.md | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index 7e40fe24ecf..f978b789108 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"914690f8952561c05e7e74d81d1500c9fb716283e2e2543feb949bb68c39020d","body_hash":"7451be458e89d34bcecde90ff4a55369b6615a4cf94fb3abed6fb7e714360320","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"},"agent_image_runner":"aw-gpu-runner-T4"} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"3d64dc35e4ebd3efaef53e388b1785f59b1e8c88f6139d3faddc8031d2cf3e2c","body_hash":"442d55be3544bee33ab60a8ca6b00b1a4ddd2be509e466db167953acb8d281d3","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"},"agent_image_runner":"aw-gpu-runner-T4"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN","TAVILY_API_KEY"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -544,7 +544,7 @@ jobs: - name: Start Supertonic HTTP server run: "set -e\n# Start server in background; first run downloads the model (~400MB) from HuggingFace\nnohup /tmp/gh-aw/agent/venv/bin/supertonic serve \\\n --host 127.0.0.1 --port 7788 \\\n > /tmp/gh-aw/agent/supertonic.log 2>&1 &\nSTTC_PID=$!\necho $STTC_PID > /tmp/gh-aw/agent/supertonic.pid\necho \"Supertonic server PID: $STTC_PID β€” logs at /tmp/gh-aw/agent/supertonic.log\"\n" - name: Wait for Supertonic server readiness - run: "# Allow up to 3 minutes (60 Γ— 3s) to accommodate model download on first run\nURL=\"http://127.0.0.1:7788/docs\"\nSTATUS=\"\"\nfor i in $(seq 1 60); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" \\\n --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Supertonic server ready at http://127.0.0.1:7788\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for Supertonic... ($i/60) (status: $STATUS)\" && sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Supertonic server failed to start after 3 minutes (final status: $STATUS)\"\n cat /tmp/gh-aw/agent/supertonic.log || true\n exit 1\nfi\n" + run: "# Allow up to 3 minutes (60 iterations Γ— 3s each) to accommodate model download on first run\nURL=\"http://127.0.0.1:7788/docs\"\nSTATUS=\"\"\nfor i in $(seq 1 60); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" \\\n --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Supertonic server ready at http://127.0.0.1:7788\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for Supertonic... ($i/60) (status: $STATUS)\" && sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Supertonic server failed to start after 3 minutes (final status: $STATUS)\"\n cat /tmp/gh-aw/agent/supertonic.log || true\n exit 1\nfi\n" - name: Setup Python environment run: "# Create working directory for Python scripts\nmkdir -p /tmp/gh-aw/python\nmkdir -p /tmp/gh-aw/python/data\nmkdir -p /tmp/gh-aw/python/charts\nmkdir -p /tmp/gh-aw/python/artifacts\n\necho \"Python environment setup complete\"\necho \"Working directory: /tmp/gh-aw/python\"\necho \"Data directory: /tmp/gh-aw/python/data\"\necho \"Charts directory: /tmp/gh-aw/python/charts\"\necho \"Artifacts directory: /tmp/gh-aw/python/artifacts\"\n" - name: Install Python scientific libraries diff --git a/.github/workflows/daily-news.md b/.github/workflows/daily-news.md index cad95929fa2..54cdaa761c6 100644 --- a/.github/workflows/daily-news.md +++ b/.github/workflows/daily-news.md @@ -20,7 +20,7 @@ engine: id: copilot bare: true -timeout-minutes: 50 # Increased from 30 to accommodate Supertonic model download (~400MB) and TTS synthesis +timeout-minutes: 50 # Increased from 30 to accommodate Supertonic model download (~400MB) and TTS synthesis; original value was 45 experiments: prompt_style: variants: [detailed, concise] @@ -565,16 +565,26 @@ Example: ### Step 2 β€” Synthesize the audio +Write the summary text to a file first, then pass it to the API to avoid shell quoting issues: + ```bash mkdir -p /tmp/gh-aw/agent + +# Write the summary text to a file (avoids shell quoting complexity) +cat > /tmp/gh-aw/agent/summary.txt << 'SUMMARY' + +SUMMARY + +# Synthesize to WAV via the Supertonic TTS server +SUMMARY_TEXT=$(cat /tmp/gh-aw/agent/summary.txt) curl -sS -X POST http://127.0.0.1:7788/v1/tts \ -H 'content-type: application/json' \ - -d "{\"text\": \"\", \"voice\": \"F1\", \"lang\": \"en\", \"steps\": 8}" \ + --data-binary "{\"text\": $(jq -n --arg t "$SUMMARY_TEXT" '$t'), \"voice\": \"F1\", \"lang\": \"en\", \"steps\": 8}" \ -o /tmp/gh-aw/agent/daily-voice-summary.wav echo "Voice summary generated: $(ls -lh /tmp/gh-aw/agent/daily-voice-summary.wav)" ``` -Replace `` with the summary you composed in Step 1. +Replace the `` placeholder with the summary composed in Step 1. ### Step 3 β€” Upload as a run artifact diff --git a/.github/workflows/shared/supertonic.md b/.github/workflows/shared/supertonic.md index 3759da15978..90cb43c0fbb 100644 --- a/.github/workflows/shared/supertonic.md +++ b/.github/workflows/shared/supertonic.md @@ -65,7 +65,7 @@ steps: - name: Wait for Supertonic server readiness run: | - # Allow up to 3 minutes (60 Γ— 3s) to accommodate model download on first run + # Allow up to 3 minutes (60 iterations Γ— 3s each) to accommodate model download on first run URL="http://127.0.0.1:7788/docs" STATUS="" for i in $(seq 1 60); do From e80ab7182330a1bddcc13bc9971e59711ac91396 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Jun 2026 15:24:43 +0000 Subject: [PATCH 3/8] =?UTF-8?q?chore:=20plan=20=E2=80=94=20cache=20superto?= =?UTF-8?q?nic=20model=20in=20actions/cache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/schemas/github-workflow.json | 294 ++++++++++++++++++---- 1 file changed, 245 insertions(+), 49 deletions(-) diff --git a/pkg/workflow/schemas/github-workflow.json b/pkg/workflow/schemas/github-workflow.json index ca272f38383..f670ca49089 100644 --- a/pkg/workflow/schemas/github-workflow.json +++ b/pkg/workflow/schemas/github-workflow.json @@ -1095,11 +1095,19 @@ "properties": { "branch_protection_rule": { "$comment": "https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#branch_protection_rule", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the branch_protection_rule event occurs. More than one activity type triggers this event.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "edited", "deleted"] @@ -1110,11 +1118,19 @@ }, "check_run": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#check-run-event-check_run", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the check_run event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/checks/runs.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "rerequested", "completed", "requested_action"] @@ -1125,11 +1141,19 @@ }, "check_suite": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#check-suite-event-check_suite", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the check_suite event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/checks/suites/.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["completed", "requested", "rerequested"] @@ -1140,31 +1164,55 @@ }, "create": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#create-event-create", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime someone creates a branch or tag, which triggers the create event. For information about the REST API, see https://developer.github.com/v3/git/refs/#create-a-reference." }, "delete": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#delete-event-delete", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime someone deletes a branch or tag, which triggers the delete event. For information about the REST API, see https://developer.github.com/v3/git/refs/#delete-a-reference." }, "deployment": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#deployment-event-deployment", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime someone creates a deployment, which triggers the deployment event. Deployments created with a commit SHA may not have a Git ref. For information about the REST API, see https://developer.github.com/v3/repos/deployments/." }, "deployment_status": { "$comment": "https://docs.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime a third party provides a deployment status, which triggers the deployment_status event. Deployments created with a commit SHA may not have a Git ref. For information about the REST API, see https://developer.github.com/v3/repos/deployments/#create-a-deployment-status." }, "discussion": { "$comment": "https://docs.github.com/en/actions/reference/events-that-trigger-workflows#discussion", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the discussion event occurs. More than one activity type triggers this event. For information about the GraphQL API, see https://docs.github.com/en/graphql/guides/using-the-graphql-api-for-discussions", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "edited", "deleted", "transferred", "pinned", "unpinned", "labeled", "unlabeled", "locked", "unlocked", "category_changed", "answered", "unanswered"] @@ -1175,11 +1223,19 @@ }, "discussion_comment": { "$comment": "https://docs.github.com/en/actions/reference/events-that-trigger-workflows#discussion_comment", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the discussion_comment event occurs. More than one activity type triggers this event. For information about the GraphQL API, see https://docs.github.com/en/graphql/guides/using-the-graphql-api-for-discussions", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "edited", "deleted"] @@ -1190,21 +1246,37 @@ }, "fork": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#fork-event-fork", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime when someone forks a repository, which triggers the fork event. For information about the REST API, see https://developer.github.com/v3/repos/forks/#create-a-fork." }, "gollum": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#gollum-event-gollum", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow when someone creates or updates a Wiki page, which triggers the gollum event." }, "issue_comment": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#issue-comment-event-issue_comment", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the issue_comment event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/issues/comments/.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "edited", "deleted"] @@ -1215,11 +1287,19 @@ }, "issues": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#issues-event-issues", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the issues event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/issues.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["opened", "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened", "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked", "milestoned", "demilestoned"] @@ -1230,11 +1310,19 @@ }, "label": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#label-event-label", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the label event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/issues/labels/.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "edited", "deleted"] @@ -1245,11 +1333,19 @@ }, "merge_group": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#merge_group", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow when a pull request is added to a merge queue, which adds the pull request to a merge group. For information about the merge queue, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request-with-a-merge-queue .", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["checks_requested"] @@ -1260,11 +1356,19 @@ }, "milestone": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#milestone-event-milestone", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the milestone event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/issues/milestones/.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "closed", "opened", "edited", "deleted"] @@ -1275,16 +1379,28 @@ }, "page_build": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#page-build-event-page_build", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime someone pushes to a GitHub Pages-enabled branch, which triggers the page_build event. For information about the REST API, see https://developer.github.com/v3/repos/pages/." }, "project": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#project-event-project", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the project event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/projects/.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "updated", "closed", "reopened", "edited", "deleted"] @@ -1295,11 +1411,19 @@ }, "project_card": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#project-card-event-project_card", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the project_card event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/projects/cards.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "moved", "converted", "edited", "deleted"] @@ -1310,11 +1434,19 @@ }, "project_column": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#project-column-event-project_column", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the project_column event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/projects/columns.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "updated", "moved", "deleted"] @@ -1325,7 +1457,11 @@ }, "public": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#public-event-public", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime someone makes a private repository public, which triggers the public event. For information about the REST API, see https://developer.github.com/v3/repos/#edit." }, "pull_request": { @@ -1341,7 +1477,11 @@ "type": "object", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": [ @@ -1412,11 +1552,19 @@ }, "pull_request_review": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#pull-request-review-event-pull_request_review", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the pull_request_review event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/pulls/reviews.\nNote: Workflows do not run on private base repositories when you open a pull request from a forked repository.\nWhen you create a pull request from a forked repository to the base repository, GitHub sends the pull_request event to the base repository and no pull request events occur on the forked repository.\nWorkflows don't run on forked repositories by default. You must enable GitHub Actions in the Actions tab of the forked repository.\nThe permissions for the GITHUB_TOKEN in forked repositories is read-only. For more information about the GITHUB_TOKEN, see https://help.github.com/en/articles/virtual-environments-for-github-actions.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["submitted", "edited", "dismissed"] @@ -1427,11 +1575,19 @@ }, "pull_request_review_comment": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#pull-request-review-comment-event-pull_request_review_comment", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime a comment on a pull request's unified diff is modified, which triggers the pull_request_review_comment event. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/pulls/comments.\nNote: Workflows do not run on private base repositories when you open a pull request from a forked repository.\nWhen you create a pull request from a forked repository to the base repository, GitHub sends the pull_request event to the base repository and no pull request events occur on the forked repository.\nWorkflows don't run on forked repositories by default. You must enable GitHub Actions in the Actions tab of the forked repository.\nThe permissions for the GITHUB_TOKEN in forked repositories is read-only. For more information about the GITHUB_TOKEN, see https://help.github.com/en/articles/virtual-environments-for-github-actions.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["created", "edited", "deleted"] @@ -1453,7 +1609,11 @@ "type": "object", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": [ @@ -1572,11 +1732,19 @@ }, "registry_package": { "$comment": "https://help.github.com/en/actions/reference/events-that-trigger-workflows#registry-package-event-registry_package", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime a package is published or updated. For more information, see https://help.github.com/en/github/managing-packages-with-github-packages.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["published", "updated"] @@ -1587,11 +1755,19 @@ }, "release": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#release-event-release", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the release event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/repos/releases/ in the GitHub Developer documentation.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["published", "unpublished", "created", "edited", "deleted", "prereleased", "released"] @@ -1602,12 +1778,20 @@ }, "status": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#status-event-status", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the status of a Git commit changes, which triggers the status event. For information about the REST API, see https://developer.github.com/v3/repos/statuses/." }, "watch": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#watch-event-watch", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "Runs your workflow anytime the watch event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/activity/starring/." }, "workflow_call": { @@ -1724,11 +1908,19 @@ }, "workflow_run": { "$comment": "https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_run", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "This event occurs when a workflow run is requested or completed, and allows you to execute a workflow based on the finished result of another workflow. For example, if your pull_request workflow generates build artifacts, you can create a new workflow that uses workflow_run to analyze the results and add a comment to the original pull request.", "properties": { "types": { - "$ref": "#/definitions/types", + "allOf": [ + { + "$ref": "#/definitions/types" + } + ], "items": { "type": "string", "enum": ["requested", "completed", "in_progress"] @@ -1749,7 +1941,11 @@ }, "repository_dispatch": { "$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#external-events-repository_dispatch", - "$ref": "#/definitions/eventObject", + "allOf": [ + { + "$ref": "#/definitions/eventObject" + } + ], "description": "You can use the GitHub API to trigger a webhook event called repository_dispatch when you want to trigger a workflow for activity that happens outside of GitHub. For more information, see https://developer.github.com/v3/repos/#create-a-repository-dispatch-event.\nTo trigger the custom repository_dispatch webhook event, you must send a POST request to a GitHub API endpoint and provide an event_type name to describe the activity type. To trigger a workflow run, you must also configure your workflow to use the repository_dispatch event." }, "schedule": { From a619173dffa6721b1be74564d3fe486d473173f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Jun 2026 15:29:09 +0000 Subject: [PATCH 4/8] feat: cache supertonic model in actions/cache Add actions/cache/restore before server start and actions/cache/save after server is ready. Cache key is keyed by runner OS and installed package version (~/.cache/supertonic3/) so subsequent runs skip the ~400 MB model download from HuggingFace. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/daily-news.lock.yml | 20 +++++++++++++++++--- .github/workflows/shared/supertonic.md | 21 +++++++++++++++++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index f978b789108..f0de6c9758f 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"3d64dc35e4ebd3efaef53e388b1785f59b1e8c88f6139d3faddc8031d2cf3e2c","body_hash":"442d55be3544bee33ab60a8ca6b00b1a4ddd2be509e466db167953acb8d281d3","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"},"agent_image_runner":"aw-gpu-runner-T4"} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"aa537cb4f50e4f1bb15133ed9db6e4f8a82bc001171c6343d17300bdf398b38b","body_hash":"442d55be3544bee33ab60a8ca6b00b1a4ddd2be509e466db167953acb8d281d3","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"},"agent_image_runner":"aw-gpu-runner-T4"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN","TAVILY_API_KEY"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -531,7 +531,8 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" env: GH_TOKEN: ${{ github.token }} - - name: Install Supertonic with server support + - id: install-supertonic + name: Install Supertonic with server support run: | set -e mkdir -p /tmp/gh-aw/agent @@ -540,11 +541,24 @@ jobs: fi echo "/tmp/gh-aw/agent/venv/bin" >> "$GITHUB_PATH" /tmp/gh-aw/agent/venv/bin/pip install --quiet 'supertonic[serve]' - /tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(f'Supertonic {supertonic.__version__} installed with server support')" + SUPERTONIC_VERSION=$(/tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(supertonic.__version__)") + echo "version=$SUPERTONIC_VERSION" >> "$GITHUB_OUTPUT" + echo "Supertonic $SUPERTONIC_VERSION installed with server support" + - name: Restore Supertonic model cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + path: ~/.cache/supertonic3 + restore-keys: supertonic3-model-${{ runner.os }}- - name: Start Supertonic HTTP server run: "set -e\n# Start server in background; first run downloads the model (~400MB) from HuggingFace\nnohup /tmp/gh-aw/agent/venv/bin/supertonic serve \\\n --host 127.0.0.1 --port 7788 \\\n > /tmp/gh-aw/agent/supertonic.log 2>&1 &\nSTTC_PID=$!\necho $STTC_PID > /tmp/gh-aw/agent/supertonic.pid\necho \"Supertonic server PID: $STTC_PID β€” logs at /tmp/gh-aw/agent/supertonic.log\"\n" - name: Wait for Supertonic server readiness run: "# Allow up to 3 minutes (60 iterations Γ— 3s each) to accommodate model download on first run\nURL=\"http://127.0.0.1:7788/docs\"\nSTATUS=\"\"\nfor i in $(seq 1 60); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" \\\n --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Supertonic server ready at http://127.0.0.1:7788\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for Supertonic... ($i/60) (status: $STATUS)\" && sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Supertonic server failed to start after 3 minutes (final status: $STATUS)\"\n cat /tmp/gh-aw/agent/supertonic.log || true\n exit 1\nfi\n" + - name: Save Supertonic model cache + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + path: ~/.cache/supertonic3 - name: Setup Python environment run: "# Create working directory for Python scripts\nmkdir -p /tmp/gh-aw/python\nmkdir -p /tmp/gh-aw/python/data\nmkdir -p /tmp/gh-aw/python/charts\nmkdir -p /tmp/gh-aw/python/artifacts\n\necho \"Python environment setup complete\"\necho \"Working directory: /tmp/gh-aw/python\"\necho \"Data directory: /tmp/gh-aw/python/data\"\necho \"Charts directory: /tmp/gh-aw/python/charts\"\necho \"Artifacts directory: /tmp/gh-aw/python/artifacts\"\n" - name: Install Python scientific libraries diff --git a/.github/workflows/shared/supertonic.md b/.github/workflows/shared/supertonic.md index 90cb43c0fbb..458a9b8d80d 100644 --- a/.github/workflows/shared/supertonic.md +++ b/.github/workflows/shared/supertonic.md @@ -22,7 +22,8 @@ # - Recommended timeout-minutes: β‰₯ 20 to allow model download and server startup # # Note: The Supertonic model (~400MB) is downloaded from Hugging Face on the first -# run and cached in ~/.cache/supertonic3/. Subsequent runs are significantly faster. +# run and cached in ~/.cache/supertonic3/. The model cache is stored in +# actions/cache keyed by OS and package version, so subsequent runs are fast. tools: bash: @@ -42,6 +43,7 @@ network: steps: - name: Install Supertonic with server support + id: install-supertonic run: | set -e mkdir -p /tmp/gh-aw/agent @@ -50,7 +52,16 @@ steps: fi echo "/tmp/gh-aw/agent/venv/bin" >> "$GITHUB_PATH" /tmp/gh-aw/agent/venv/bin/pip install --quiet 'supertonic[serve]' - /tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(f'Supertonic {supertonic.__version__} installed with server support')" + SUPERTONIC_VERSION=$(/tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(supertonic.__version__)") + echo "version=$SUPERTONIC_VERSION" >> "$GITHUB_OUTPUT" + echo "Supertonic $SUPERTONIC_VERSION installed with server support" + + - name: Restore Supertonic model cache + uses: actions/cache/restore@v5.0.5 + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + restore-keys: supertonic3-model-${{ runner.os }}- + path: ~/.cache/supertonic3 - name: Start Supertonic HTTP server run: | @@ -80,6 +91,12 @@ steps: cat /tmp/gh-aw/agent/supertonic.log || true exit 1 fi + + - name: Save Supertonic model cache + uses: actions/cache/save@v5.0.5 + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + path: ~/.cache/supertonic3 --- ## Supertonic TTS HTTP Server Ready From 57afbd28a344f5a6a53e11856574e6011c711c1e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Jun 2026 23:47:36 +0000 Subject: [PATCH 5/8] feat: refactor supertonic into standalone supertonic-tts workflow - Create supertonic-tts.md: workflow_dispatch workflow accepting `text`, `issue-number`, and `pr-number` inputs; validates exactly one issue/PR target; imports shared/supertonic.md for TTS server; synthesizes WAV, uploads via upload-artifact, posts comment via add-comment - Update daily-news.md: remove shared/supertonic.md import, remove Voice Summary agent phase, restore timeout-minutes to 30 - shared/supertonic.md unchanged (server-setup + model-caching import) Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/daily-news.lock.yml | 54 +- .github/workflows/daily-news.md | 65 +- .github/workflows/supertonic-tts.lock.yml | 1668 +++++++++++++++++++++ .github/workflows/supertonic-tts.md | 140 ++ 4 files changed, 1821 insertions(+), 106 deletions(-) create mode 100644 .github/workflows/supertonic-tts.lock.yml create mode 100644 .github/workflows/supertonic-tts.md diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index f0de6c9758f..766142b0d0e 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"aa537cb4f50e4f1bb15133ed9db6e4f8a82bc001171c6343d17300bdf398b38b","body_hash":"442d55be3544bee33ab60a8ca6b00b1a4ddd2be509e466db167953acb8d281d3","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"},"agent_image_runner":"aw-gpu-runner-T4"} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"8d41a250f29248203bc447b1d39fe538173aa7b849fdbc6d8c2dadeb04b5d229","body_hash":"5843ee6b9c68bfefd446e6e2e850fe1786319fcad93fded7bf831fea4e9fcf44","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"},"agent_image_runner":"aw-gpu-runner-T4"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN","TAVILY_API_KEY"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -35,7 +35,6 @@ # - shared/repo-memory-standard.md # - shared/reporting.md # - shared/daily-audit-base.md -# - shared/supertonic.md # - shared/trends.md # # Secrets used: @@ -282,24 +281,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_cd53ff158bb0d1a6_EOF' + cat << 'GH_AW_PROMPT_821dea60e51933e9_EOF' - GH_AW_PROMPT_cd53ff158bb0d1a6_EOF + GH_AW_PROMPT_821dea60e51933e9_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_cd53ff158bb0d1a6_EOF' + cat << 'GH_AW_PROMPT_821dea60e51933e9_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_cd53ff158bb0d1a6_EOF + GH_AW_PROMPT_821dea60e51933e9_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_cd53ff158bb0d1a6_EOF' + cat << 'GH_AW_PROMPT_821dea60e51933e9_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -328,21 +327,20 @@ jobs: {{/if}} - GH_AW_PROMPT_cd53ff158bb0d1a6_EOF + GH_AW_PROMPT_821dea60e51933e9_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_cd53ff158bb0d1a6_EOF' + cat << 'GH_AW_PROMPT_821dea60e51933e9_EOF' {{#runtime-import .github/workflows/shared/mcp/tavily.md}} {{#runtime-import .github/skills/jqschema/SKILL.md}} {{#runtime-import .github/workflows/shared/trends.md}} - {{#runtime-import .github/workflows/shared/supertonic.md}} {{#runtime-import .github/workflows/shared/otlp.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/python-dataviz.md}} {{#runtime-import .github/shared/editorial.md}} {{#runtime-import .github/workflows/shared/noop-reminder.md}} {{#runtime-import .github/workflows/daily-news.md}} - GH_AW_PROMPT_cd53ff158bb0d1a6_EOF + GH_AW_PROMPT_821dea60e51933e9_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -531,34 +529,6 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" env: GH_TOKEN: ${{ github.token }} - - id: install-supertonic - name: Install Supertonic with server support - run: | - set -e - mkdir -p /tmp/gh-aw/agent - if [ ! -d /tmp/gh-aw/agent/venv ]; then - python3 -m venv /tmp/gh-aw/agent/venv - fi - echo "/tmp/gh-aw/agent/venv/bin" >> "$GITHUB_PATH" - /tmp/gh-aw/agent/venv/bin/pip install --quiet 'supertonic[serve]' - SUPERTONIC_VERSION=$(/tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(supertonic.__version__)") - echo "version=$SUPERTONIC_VERSION" >> "$GITHUB_OUTPUT" - echo "Supertonic $SUPERTONIC_VERSION installed with server support" - - name: Restore Supertonic model cache - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} - path: ~/.cache/supertonic3 - restore-keys: supertonic3-model-${{ runner.os }}- - - name: Start Supertonic HTTP server - run: "set -e\n# Start server in background; first run downloads the model (~400MB) from HuggingFace\nnohup /tmp/gh-aw/agent/venv/bin/supertonic serve \\\n --host 127.0.0.1 --port 7788 \\\n > /tmp/gh-aw/agent/supertonic.log 2>&1 &\nSTTC_PID=$!\necho $STTC_PID > /tmp/gh-aw/agent/supertonic.pid\necho \"Supertonic server PID: $STTC_PID β€” logs at /tmp/gh-aw/agent/supertonic.log\"\n" - - name: Wait for Supertonic server readiness - run: "# Allow up to 3 minutes (60 iterations Γ— 3s each) to accommodate model download on first run\nURL=\"http://127.0.0.1:7788/docs\"\nSTATUS=\"\"\nfor i in $(seq 1 60); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" \\\n --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Supertonic server ready at http://127.0.0.1:7788\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for Supertonic... ($i/60) (status: $STATUS)\" && sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Supertonic server failed to start after 3 minutes (final status: $STATUS)\"\n cat /tmp/gh-aw/agent/supertonic.log || true\n exit 1\nfi\n" - - name: Save Supertonic model cache - uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} - path: ~/.cache/supertonic3 - name: Setup Python environment run: "# Create working directory for Python scripts\nmkdir -p /tmp/gh-aw/python\nmkdir -p /tmp/gh-aw/python/data\nmkdir -p /tmp/gh-aw/python/charts\nmkdir -p /tmp/gh-aw/python/artifacts\n\necho \"Python environment setup complete\"\necho \"Working directory: /tmp/gh-aw/python\"\necho \"Data directory: /tmp/gh-aw/python/data\"\necho \"Charts directory: /tmp/gh-aw/python/charts\"\necho \"Artifacts directory: /tmp/gh-aw/python/artifacts\"\n" - name: Install Python scientific libraries @@ -1050,7 +1020,7 @@ jobs: - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): - timeout-minutes: 50 + timeout-minutes: 30 run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt @@ -1102,7 +1072,7 @@ jobs: GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_TIMEOUT_MINUTES: 50 + GH_AW_TIMEOUT_MINUTES: 30 GH_AW_VERSION: dev GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true @@ -1582,7 +1552,7 @@ jobs: GH_AW_FAILURE_REPORT_AS_ISSUE: "true" GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" - GH_AW_TIMEOUT_MINUTES: "50" + GH_AW_TIMEOUT_MINUTES: "30" GH_AW_CACHE_MEMORY_ENABLED: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/daily-news.md b/.github/workflows/daily-news.md index 54cdaa761c6..328c238b82f 100644 --- a/.github/workflows/daily-news.md +++ b/.github/workflows/daily-news.md @@ -20,7 +20,7 @@ engine: id: copilot bare: true -timeout-minutes: 50 # Increased from 30 to accommodate Supertonic model download (~400MB) and TTS synthesis; original value was 45 +timeout-minutes: 30 # Reduced from 45 since pre-fetching data is faster experiments: prompt_style: variants: [detailed, concise] @@ -319,7 +319,6 @@ imports: title-prefix: "[daily-news] " expires: 3d - shared/trends.md - - shared/supertonic.md - shared/otlp.md --- @@ -552,66 +551,4 @@ Create a new GitHub discussion with a title containing today's date (e.g., "Dail Only a new discussion should be created, do not close or update any existing discussions. {{/if}} -## πŸ”Š Voice Summary - -After creating the discussion, generate a short spoken summary of the day's news using the Supertonic TTS server (already running at `http://127.0.0.1:7788`). - -### Step 1 β€” Write the summary script - -Compose a concise spoken summary (2–4 sentences) covering the headline metrics and most notable event of the day. Keep it natural and conversational β€” this is text-to-speech, not markdown. - -Example: -> "Good morning! Today in the gh-aw repository, 12 pull requests were merged and 8 new issues were opened. The highlight was the release of version 0.47.0, which ships improved MCP Gateway support. Have a productive day!" - -### Step 2 β€” Synthesize the audio - -Write the summary text to a file first, then pass it to the API to avoid shell quoting issues: - -```bash -mkdir -p /tmp/gh-aw/agent - -# Write the summary text to a file (avoids shell quoting complexity) -cat > /tmp/gh-aw/agent/summary.txt << 'SUMMARY' - -SUMMARY - -# Synthesize to WAV via the Supertonic TTS server -SUMMARY_TEXT=$(cat /tmp/gh-aw/agent/summary.txt) -curl -sS -X POST http://127.0.0.1:7788/v1/tts \ - -H 'content-type: application/json' \ - --data-binary "{\"text\": $(jq -n --arg t "$SUMMARY_TEXT" '$t'), \"voice\": \"F1\", \"lang\": \"en\", \"steps\": 8}" \ - -o /tmp/gh-aw/agent/daily-voice-summary.wav -echo "Voice summary generated: $(ls -lh /tmp/gh-aw/agent/daily-voice-summary.wav)" -``` - -Replace the `` placeholder with the summary composed in Step 1. - -### Step 3 β€” Upload as a run artifact - -Stage the file and call the `upload_artifact` safe-output tool: - -```bash -mkdir -p "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts" -cp /tmp/gh-aw/agent/daily-voice-summary.wav \ - "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/daily-voice-summary.wav" -``` - -Call the safe-output tool: -```json -{ "type": "upload_artifact", "path": "daily-voice-summary.wav" } -``` - -### Step 4 β€” Add the artifact link to the discussion - -Update the discussion you created with a final section: - -```markdown -### πŸ”Š Voice Summary - -A spoken version of today's digest is available as a run artifact: -[🎧 Download daily-voice-summary.wav]() -``` - -Replace `` with the `slot_N_artifact_url` returned by the `upload_artifact` tool. - {{#runtime-import shared/noop-reminder.md}} \ No newline at end of file diff --git a/.github/workflows/supertonic-tts.lock.yml b/.github/workflows/supertonic-tts.lock.yml new file mode 100644 index 00000000000..51e2b6ff0ea --- /dev/null +++ b/.github/workflows/supertonic-tts.lock.yml @@ -0,0 +1,1668 @@ +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"1ad28cf36e7ee4e57daa1ba618acbe30d8fd09de7a487928efaa0b87a759bcc2","body_hash":"74b680ce64faef0ee63722ccdd04ccd2c8a0228898545e74983b60300c072e0d","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Converts text to speech using the Supertonic on-device TTS server, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request +# +# Resolved workflow manifest: +# Imports: +# - shared/supertonic.md +# +# Secrets used: +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# +# Custom actions used: +# - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 +# - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 +# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) +# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# +# Container images used: +# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 +# - ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 +# - ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa +# - ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + +name: "Supertonic TTS" +on: + workflow_dispatch: + inputs: + aw_context: + default: "" + description: "Agent caller context (used internally by Agentic Workflows)." + required: false + type: string + issue-number: + description: Issue number to post the artifact link to (mutually exclusive with pr-number) + required: false + type: string + pr-number: + description: Pull request number to post the artifact link to (mutually exclusive with issue-number) + required: false + type: string + text: + description: Text to convert to speech + required: true + type: string + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}" + +run-name: "Supertonic TTS" + +jobs: + activation: + runs-on: ubuntu-slim + permissions: + actions: read + contents: read + env: + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + outputs: + comment_id: "" + comment_repo: "" + daily_ai_credits_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }} + daily_ai_credits_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_threshold || '' }} + daily_ai_credits_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_total_effective_tokens || '' }} + engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + steps: + - name: Checkout actions folder + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false + - name: Setup Scripts + id: setup + uses: ./actions/setup + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/supertonic-tts.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Generate agentic run info + id: generate_aw_info + env: + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AGENT_VERSION: "1.0.60" + GH_AW_INFO_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","python"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_INFO_FRONTMATTER_EMOJI: "πŸ”Š" + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Restore daily AIC usage cache + id: restore-daily-aic-cache + if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + continue-on-error: true + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + key: agentic-workflow-usage-supertonictts-${{ github.run_id }} + restore-keys: agentic-workflow-usage-supertonictts- + path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl + - name: Check daily workflow token guardrail + id: daily-effective-workflow-guardrail + if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_WORKFLOW_ID: "supertonic-tts" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }} + GH_AW_HAS_SLASH_COMMAND: "false" + GH_AW_HAS_LABEL_COMMAND: "false" + GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + actions/setup + .antigravity + .claude + .codex + .crush + .gemini + .opencode + .pi + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" + - name: Check workflow lock file + id: check-lock-file + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_WORKFLOW_FILE: "supertonic-tts.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_80FB632A: ${{ github.event.inputs.pr-number }} + GH_AW_EXPR_FD3E9604: ${{ github.event.inputs.issue-number }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_INPUTS_TEXT: ${{ github.event.inputs.text }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + # poutine:ignore untrusted_checkout_exec + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" + { + cat << 'GH_AW_PROMPT_2031fcd43d20b981_EOF' + + GH_AW_PROMPT_2031fcd43d20b981_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_2031fcd43d20b981_EOF' + + Tools: add_comment, missing_tool, missing_data, noop + + GH_AW_PROMPT_2031fcd43d20b981_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" + cat << 'GH_AW_PROMPT_2031fcd43d20b981_EOF' + + The following GitHub context information is available for this workflow: + {{#if github.actor}} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if github.repository}} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if github.workspace}} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}} + - **issue-number**: #__GH_AW_EXPR_802A9F6A__ + {{/if}} + {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}} + - **discussion-number**: #__GH_AW_EXPR_1A3A194A__ + {{/if}} + {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}} + - **pull-request-number**: #__GH_AW_EXPR_463A214A__ + {{/if}} + {{#if github.event.comment.id || github.aw.context.comment_id}} + - **comment-id**: __GH_AW_EXPR_FF1D34CE__ + {{/if}} + {{#if github.run_id}} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_2031fcd43d20b981_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_2031fcd43d20b981_EOF' + + {{#runtime-import .github/workflows/shared/supertonic.md}} + {{#runtime-import .github/workflows/supertonic-tts.md}} + GH_AW_PROMPT_2031fcd43d20b981_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" + GH_AW_EXPR_FD3E9604: ${{ github.event.inputs.issue-number }} + GH_AW_EXPR_80FB632A: ${{ github.event.inputs.pr-number }} + GH_AW_GITHUB_EVENT_INPUTS_TEXT: ${{ github.event.inputs.text }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_80FB632A: ${{ github.event.inputs.pr-number }} + GH_AW_EXPR_FD3E9604: ${{ github.event.inputs.issue-number }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_INPUTS_TEXT: ${{ github.event.inputs.text }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` β€” run `safeoutputs --help` to see available tools' + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, + GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, + GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A, + GH_AW_EXPR_80FB632A: process.env.GH_AW_EXPR_80FB632A, + GH_AW_EXPR_FD3E9604: process.env.GH_AW_EXPR_FD3E9604, + GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_INPUTS_TEXT: process.env.GH_AW_GITHUB_EVENT_INPUTS_TEXT, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: activation + include-hidden-files: true + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/models.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw-prompts/prompt-template.txt + /tmp/gh-aw/aw-prompts/prompt-import-tree.json + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base + /tmp/gh-aw/.github/agents + /tmp/gh-aw/.github/skills + if-no-files-found: ignore + retention-days: 1 + + agent: + needs: activation + if: needs.activation.outputs.daily_ai_credits_exceeded != 'true' + runs-on: ubuntu-latest + permissions: + contents: read + copilot-requests: write + issues: read + pull-requests: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_PROJECT_UTC: "-08:00" + GH_AW_WORKFLOW_ID_SANITIZED: supertonictts + outputs: + agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} + ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }} + aic: ${{ steps.parse-mcp-gateway.outputs.aic }} + ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }} + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }} + mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }} + model: ${{ needs.activation.outputs.model }} + model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }} + steps: + - name: Checkout actions folder + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false + - name: Setup Scripts + id: setup + uses: ./actions/setup + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/supertonic-tts.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Set runtime paths + id: set-runtime-paths + run: | + { + echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" + echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" + echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" + } >> "$GITHUB_OUTPUT" + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh" + - name: Configure gh CLI for GitHub Enterprise + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" + env: + GH_TOKEN: ${{ github.token }} + - id: install-supertonic + name: Install Supertonic with server support + run: | + set -e + mkdir -p /tmp/gh-aw/agent + if [ ! -d /tmp/gh-aw/agent/venv ]; then + python3 -m venv /tmp/gh-aw/agent/venv + fi + echo "/tmp/gh-aw/agent/venv/bin" >> "$GITHUB_PATH" + /tmp/gh-aw/agent/venv/bin/pip install --quiet 'supertonic[serve]' + SUPERTONIC_VERSION=$(/tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(supertonic.__version__)") + echo "version=$SUPERTONIC_VERSION" >> "$GITHUB_OUTPUT" + echo "Supertonic $SUPERTONIC_VERSION installed with server support" + - name: Restore Supertonic model cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + path: ~/.cache/supertonic3 + restore-keys: supertonic3-model-${{ runner.os }}- + - name: Start Supertonic HTTP server + run: "set -e\n# Start server in background; first run downloads the model (~400MB) from HuggingFace\nnohup /tmp/gh-aw/agent/venv/bin/supertonic serve \\\n --host 127.0.0.1 --port 7788 \\\n > /tmp/gh-aw/agent/supertonic.log 2>&1 &\nSTTC_PID=$!\necho $STTC_PID > /tmp/gh-aw/agent/supertonic.pid\necho \"Supertonic server PID: $STTC_PID β€” logs at /tmp/gh-aw/agent/supertonic.log\"\n" + - name: Wait for Supertonic server readiness + run: "# Allow up to 3 minutes (60 iterations Γ— 3s each) to accommodate model download on first run\nURL=\"http://127.0.0.1:7788/docs\"\nSTATUS=\"\"\nfor i in $(seq 1 60); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" \\\n --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Supertonic server ready at http://127.0.0.1:7788\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for Supertonic... ($i/60) (status: $STATUS)\" && sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Supertonic server failed to start after 3 minutes (final status: $STATUS)\"\n cat /tmp/gh-aw/agent/supertonic.log || true\n exit 1\nfi\n" + - name: Save Supertonic model cache + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + path: ~/.cache/supertonic3 + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' && fromJSON(github.event.inputs.aw_context || '{}').item_type == 'pull_request' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" + - name: Restore inline sub-agents from activation artifact + env: + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.md" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh" + - name: Restore inline skills from activation artifact + env: + GH_AW_SKILL_DIR: ".github/skills" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + - name: Generate Safe Outputs Config + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_6f40227864c574a0_EOF' + {"add_comment":{"max":1},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":1,"retention-days":30,"skip-archive":true}} + GH_AW_SAFE_OUTPUTS_CONFIG_6f40227864c574a0_EOF + - name: Generate Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "reply_to_id": { + "type": "string", + "maxLength": 256 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + } + } + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + await main(); + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} + GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="8080" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_HOST_DOMAIN="localhost" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + case "${DOCKER_HOST:-}" in + unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; + /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; + * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; + esac + DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + + mkdir -p "$HOME/.copilot" + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_c6fee03c27b97257_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v1.1.2", + "env": { + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + }, + "guard-policies": { + "allow-only": { + "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", + "repos": "$GITHUB_MCP_GUARD_REPOS" + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_c6fee03c27b97257_EOF + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }} + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + await main(); + - name: Clean credentials + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Audit pre-agent workspace + id: pre_agent_audit + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool safeoutputs + # --allow-tool shell(cat) + # --allow-tool shell(cp) + # --allow-tool shell(curl:*) + # --allow-tool shell(date) + # --allow-tool shell(echo) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(kill) + # --allow-tool shell(ls) + # --allow-tool shell(mkdir) + # --allow-tool shell(printf) + # --allow-tool shell(pwd) + # --allow-tool shell(python) + # --allow-tool shell(python3) + # --allow-tool shell(safeoutputs:*) + # --allow-tool shell(sort) + # --allow-tool shell(tail) + # --allow-tool shell(uniq) + # --allow-tool shell(wc) + # --allow-tool shell(yq) + # --allow-tool write + timeout-minutes: 30 + run: | + set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + trap 'rm -f "$HOME/.copilot/settings.json"' EXIT + mkdir -p "$HOME/.copilot" + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json" + export XDG_CONFIG_HOME="$HOME" + export GH_AW_MCP_CONFIG="$HOME/.copilot/mcp-config.json" + touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN + export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-1000}" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.pythonhosted.org\",\"anaconda.org\",\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"binstar.org\",\"bootstrap.pypa.io\",\"conda.anaconda.org\",\"conda.binstar.org\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"files.pythonhosted.org\",\"github.com\",\"host.docker.internal\",\"json-schema.org\",\"json.schemastore.org\",\"keyserver.ubuntu.com\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"pip.pypa.io\",\"ppa.launchpad.net\",\"pypi.org\",\"pypi.python.org\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"repo.anaconda.com\",\"repo.continuum.io\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" + GH_AW_DOCKER_HOST="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST="${DOCKER_HOST}" + fi + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" + fi + GH_AW_TOOL_CACHE_MOUNT="" + GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}" + if [ -d "$GH_AW_TOOL_CACHE" ]; then + if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then + GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro" + fi + elif [ -d "/home/runner/work/_tool" ]; then + GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" + fi + # shellcheck disable=SC1003 + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts:${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts:rw" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner β€” check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(cp)'\'' --allow-tool '\''shell(curl:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(kill)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(mkdir)'\'' --allow-tool '\''shell(printf)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(python)'\'' --allow-tool '\''shell(python3)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --no-custom-instructions --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + AWF_REFLECT_ENABLED: 1 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode + COPILOT_GITHUB_TOKEN: ${{ github.token }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_PHASE: agent + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_TIMEOUT_MINUTES: 30 + GH_AW_VERSION: dev + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + RUNNER_TEMP: ${{ runner.temp }} + S2STOKENS: true + TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} + - name: Detect agent errors + if: always() + id: detect-agent-errors + continue-on-error: true + run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs" + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+rX /tmp/gh-aw/sandbox/firewall 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Parse token usage for step summary + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); + await main(); + - name: Print AWF reflect summary + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); + await main(); + - name: Write agent output placeholder if missing + if: always() + run: | + if [ ! -f /tmp/gh-aw/agent_output.json ]; then + echo '{"items":[]}' > /tmp/gh-aw/agent_output.json + fi + # Upload safe-outputs upload-artifact staging for the upload_artifact job + - name: Upload upload-artifact staging + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-upload-artifacts + path: ${{ runner.temp }}/gh-aw/safeoutputs/upload-artifacts/ + retention-days: 1 + if-no-files-found: ignore + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt + /tmp/gh-aw/agent/ + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/safeoutputs.jsonl + /tmp/gh-aw/agent_output.json + /tmp/gh-aw/aw-*.patch + /tmp/gh-aw/aw-*.bundle + /tmp/gh-aw/awf-config.json + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/sandbox/firewall/audit/ + /tmp/gh-aw/sandbox/firewall/awf-reflect.json + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_ai_credits_exceeded == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + pull-requests: write + concurrency: + group: "gh-aw-conclusion-supertonic-tts" + cancel-in-progress: false + queue: max + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Checkout actions folder + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false + - name: Setup Scripts + id: setup + uses: ./actions/setup + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/supertonic-tts.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Collect usage artifact files + if: always() + continue-on-error: true + run: | + mkdir -p /tmp/gh-aw/usage/agent /tmp/gh-aw/usage/detection + echo "Usage artifact source file status:" + for file in /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl; do + [ -f "$file" ] && echo "FOUND: $file" || echo "MISSING: $file" + done + [ -f /tmp/gh-aw/aw-info.jsonl ] && cp /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/usage/aw-info.jsonl || true + [ -f /tmp/gh-aw/agent_usage.jsonl ] && cp /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/usage/agent_usage.jsonl || true + [ -f /tmp/gh-aw/detection_usage.jsonl ] && cp /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/usage/detection_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/usage/agent/token_usage.jsonl ] || : > /tmp/gh-aw/usage/agent/token_usage.jsonl + [ -f /tmp/gh-aw/usage/detection/token_usage.jsonl ] || : > /tmp/gh-aw/usage/detection/token_usage.jsonl + find /tmp/gh-aw/usage -type f -print | sort + - name: Upload usage artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/detection/token_usage.jsonl + if-no-files-found: ignore + - name: Restore daily AIC usage cache + id: restore-daily-aic-cache-conclusion + if: always() + continue-on-error: true + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + key: agentic-workflow-usage-supertonictts-${{ github.run_id }} + restore-keys: agentic-workflow-usage-supertonictts- + path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl + - name: Write daily AIC usage cache entry + id: write-daily-aic-cache + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ github.token }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context); + const { main } = require('${{ runner.temp }}/gh-aw/actions/write_daily_aic_usage_cache.cjs'); + await main(); + - name: Save daily AIC usage cache + id: save-daily-aic-cache + if: always() + continue-on-error: true + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + key: agentic-workflow-usage-supertonictts-${{ github.run_id }} + path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl + - name: Process no-op messages + id: noop + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/supertonic-tts.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_WORKFLOW_ID: "supertonic-tts" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Log detection run + id: detection_runs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/supertonic-tts.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs'); + await main(); + - name: Record missing tool + id: missing_tool + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/supertonic-tts.md" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Record incomplete + id: report_incomplete + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/supertonic-tts.md" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/supertonic-tts.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_WORKFLOW_ID: "supertonic-tts" + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "12" + GH_AW_ENGINE_ID: "copilot" + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} + GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} + GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }} + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} + GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} + GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} + GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" + GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} + GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }} + GH_AW_DAILY_AI_CREDITS_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_ai_credits_total_effective_tokens }} + GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" + GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" + GH_AW_TIMEOUT_MINUTES: "30" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + + detection: + needs: + - activation + - agent + if: > + always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') + runs-on: ubuntu-latest + permissions: + contents: read + copilot-requests: write + outputs: + aic: ${{ steps.parse_detection_token_usage.outputs.aic }} + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_reason: ${{ steps.detection_conclusion.outputs.reason }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + steps: + - name: Checkout actions folder + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false + - name: Setup Scripts + id: setup + uses: ./actions/setup + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/supertonic-tts.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Checkout repository for patch context + if: needs.agent.outputs.has_patch == 'true' + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + # --- Threat Detection --- + - name: Clean stale firewall files from agent artifact + run: | + rm -rf /tmp/gh-aw/sandbox/firewall/logs + rm -rf /tmp/gh-aw/sandbox/firewall/audit + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + run: | + if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then + echo "run_detection=true" >> "$GITHUB_OUTPUT" + echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" + else + echo "run_detection=false" >> "$GITHUB_OUTPUT" + echo "Detection skipped: no agent outputs or patches to analyze" + fi + - name: Clear MCP Config for detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json" + rm -f "$HOME/.copilot/mcp-config.json" + rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" + - name: Prepare threat detection files + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection/aw-prompts + rm -f /tmp/gh-aw/agent_usage.json + cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true + if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then + echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context." + fi + cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true + for f in /tmp/gh-aw/aw-*.patch; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + for f in /tmp/gh-aw/aw-*.bundle; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + echo "Prepared threat detection files:" + ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true + - name: Setup threat detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + WORKFLOW_NAME: "Supertonic TTS" + WORKFLOW_DESCRIPTION: "Converts text to speech using the Supertonic on-device TTS server, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 + - name: Execute GitHub Copilot CLI + if: always() && steps.detection_guard.outputs.run_detection == 'true' + continue-on-error: true + id: detection_agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 + run: | + set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + trap 'rm -f "$HOME/.copilot/settings.json"' EXIT + mkdir -p "$HOME/.copilot" + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json" + export XDG_CONFIG_HOME="$HOME" + touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN + export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" + (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) + GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-400}" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"github.com\",\"host.docker.internal\",\"registry.npmjs.org\",\"telemetry.enterprise.githubcopilot.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" + GH_AW_DOCKER_HOST="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST="${DOCKER_HOST}" + fi + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" + fi + GH_AW_TOOL_CACHE_MOUNT="" + GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}" + if [ -d "$GH_AW_TOOL_CACHE" ]; then + if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then + GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro" + fi + elif [ -d "/home/runner/work/_tool" ]; then + GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" + fi + # shellcheck disable=SC1003 + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'set +o histexpand; GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner β€” check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + env: + AWF_REFLECT_ENABLED: 1 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode + COPILOT_GITHUB_TOKEN: ${{ github.token }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }} + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_PHASE: detection + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_TIMEOUT_MINUTES: 20 + GH_AW_VERSION: dev + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + RUNNER_TEMP: ${{ runner.temp }} + S2STOKENS: true + TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} + - name: Parse threat detection token usage for step summary + id: parse_detection_token_usage + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); + await main(); + - name: Upload threat detection log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: detection + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + - name: Parse and conclude threat detection + id: detection_conclusion + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + with: + script: | + try { + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + } catch (loadErr) { + const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false'; + const detectionExecutionFailed = process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME === 'failure'; + const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr)); + core.error(msg); + core.setOutput('reason', 'parse_error'); + if (continueOnError && !detectionExecutionFailed) { + core.warning('\u26A0\uFE0F ' + msg); + core.setOutput('conclusion', 'warning'); + core.setOutput('success', 'false'); + } else { + core.setOutput('conclusion', 'failure'); + core.setOutput('success', 'false'); + core.setFailed(msg); + } + } + + safe_outputs: + needs: + - activation + - agent + - detection + if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + pull-requests: write + timeout-minutes: 45 + env: + GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/supertonic-tts" + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.60" + GH_AW_PROJECT_UTC: "-08:00" + GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} + GH_AW_WORKFLOW_EMOJI: "πŸ”Š" + GH_AW_WORKFLOW_ID: "supertonic-tts" + GH_AW_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/supertonic-tts.md" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} + comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + upload_artifact_count: ${{ steps.process_safe_outputs.outputs.upload_artifact_count }} + upload_artifact_slot_0_tmp_id: ${{ steps.process_safe_outputs.outputs.slot_0_tmp_id }} + steps: + - name: Checkout actions folder + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false + - name: Setup Scripts + id: setup + uses: ./actions/setup + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + safe-output-artifact-client: 'true' + env: + GH_AW_SETUP_WORKFLOW_NAME: "Supertonic TTS" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/supertonic-tts.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input. + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Download upload-artifact staging + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: safe-outputs-upload-artifacts + path: ${{ runner.temp }}/gh-aw/safeoutputs/upload-artifacts/ + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} + GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{},\"upload_artifact\":{\"max-size-bytes\":104857600,\"max-uploads\":1,\"retention-days\":30,\"skip-archive\":true}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/temporary-id-map.json + if-no-files-found: ignore + diff --git a/.github/workflows/supertonic-tts.md b/.github/workflows/supertonic-tts.md new file mode 100644 index 00000000000..835443828ed --- /dev/null +++ b/.github/workflows/supertonic-tts.md @@ -0,0 +1,140 @@ +--- +emoji: "πŸ”Š" +name: Supertonic TTS +description: Converts text to speech using the Supertonic on-device TTS server, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request +on: + workflow_dispatch: + inputs: + text: + description: "Text to convert to speech" + required: true + type: string + issue-number: + description: "Issue number to post the artifact link to (mutually exclusive with pr-number)" + required: false + type: string + pr-number: + description: "Pull request number to post the artifact link to (mutually exclusive with issue-number)" + required: false + type: string + +timeout-minutes: 30 + +permissions: + contents: read + issues: read + pull-requests: read + copilot-requests: write + +engine: + id: copilot + bare: true + +imports: + - shared/supertonic.md + +network: + allowed: + - defaults + - python + +tools: + bash: + - "curl *" + - "jq *" + - "cp *" + - "mkdir *" + - "ls *" + - "echo *" + - "cat *" + +safe-outputs: + upload-artifact: + max-uploads: 1 + retention-days: 30 + skip-archive: true + add-comment: + max: 1 + noop: +--- + +# Supertonic TTS + +Convert the provided text to speech, upload the WAV as a run artifact, and post a comment with the download link on the target issue or pull request. + +## Inputs + +- **Text**: ${{ github.event.inputs.text }} +- **Issue number**: ${{ github.event.inputs.issue-number }} +- **PR number**: ${{ github.event.inputs.pr-number }} + +## Task + +### Step 1 β€” Validate inputs + +Exactly one of `issue-number` or `pr-number` must be provided. Check the inputs: + +- If **both** are set: call `noop` with message `"Both issue-number and pr-number were provided. Provide exactly one."` and stop. +- If **neither** is set: call `noop` with message `"Neither issue-number nor pr-number was provided. Provide exactly one."` and stop. +- Otherwise: proceed. + +### Step 2 β€” Synthesize speech + +The Supertonic TTS server is running at `http://127.0.0.1:7788`. Use `jq` to safely encode the input text and avoid shell escaping issues: + +```bash +mkdir -p /tmp/gh-aw/agent + +# Write the text to a file to avoid here-doc quoting issues +cat > /tmp/gh-aw/agent/tts-input.txt << 'TTS_EOF' +${{ github.event.inputs.text }} +TTS_EOF + +SUMMARY_TEXT=$(cat /tmp/gh-aw/agent/tts-input.txt) +curl -sS -X POST http://127.0.0.1:7788/v1/tts \ + -H 'content-type: application/json' \ + --data-binary "{\"text\": $(jq -n --arg t "$SUMMARY_TEXT" '$t'), \"voice\": \"F1\", \"lang\": \"en\", \"steps\": 8}" \ + -o /tmp/gh-aw/agent/tts-output.wav +echo "Audio generated: $(ls -lh /tmp/gh-aw/agent/tts-output.wav)" +``` + +### Step 3 β€” Upload as a run artifact + +Stage the WAV file and call the `upload_artifact` safe-output tool: + +```bash +mkdir -p "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts" +cp /tmp/gh-aw/agent/tts-output.wav \ + "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/tts-output.wav" +``` + +Call the safe-output tool: +```json +{ "type": "upload_artifact", "path": "tts-output.wav" } +``` + +The tool returns `slot_N_artifact_url` β€” the direct download link to the uploaded file. + +### Step 4 β€” Post comment with download link + +Use `add_comment` to post the artifact link on the target item. + +If `issue-number` is set (e.g., `42`): +```json +{ + "type": "add_comment", + "issue_number": 42, + "body": "πŸ”Š **Voice summary ready**\n\n[🎧 Download tts-output.wav]()" +} +``` + +If `pr-number` is set (e.g., `99`): +```json +{ + "type": "add_comment", + "pr_number": 99, + "body": "πŸ”Š **Voice summary ready**\n\n[🎧 Download tts-output.wav]()" +} +``` + +Replace `` with the `slot_N_artifact_url` returned by the `upload_artifact` tool. From 3a9840cec77a6d19f3066646a0f0f214002c9a7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Jun 2026 23:50:54 +0000 Subject: [PATCH 6/8] fix: reduce supertonic-tts timeout-minutes to 15 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/supertonic-tts.lock.yml | 8 ++++---- .github/workflows/supertonic-tts.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/supertonic-tts.lock.yml b/.github/workflows/supertonic-tts.lock.yml index 51e2b6ff0ea..a5f87646cd5 100644 --- a/.github/workflows/supertonic-tts.lock.yml +++ b/.github/workflows/supertonic-tts.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"1ad28cf36e7ee4e57daa1ba618acbe30d8fd09de7a487928efaa0b87a759bcc2","body_hash":"74b680ce64faef0ee63722ccdd04ccd2c8a0228898545e74983b60300c072e0d","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"4305db3b5071e2ffbdf11d144e752d7ad4367c3337668309c3977bd488227096","body_hash":"74b680ce64faef0ee63722ccdd04ccd2c8a0228898545e74983b60300c072e0d","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -826,7 +826,7 @@ jobs: # --allow-tool shell(wc) # --allow-tool shell(yq) # --allow-tool write - timeout-minutes: 30 + timeout-minutes: 15 run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt @@ -875,7 +875,7 @@ jobs: GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_TIMEOUT_MINUTES: 30 + GH_AW_TIMEOUT_MINUTES: 15 GH_AW_VERSION: dev GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true @@ -1285,7 +1285,7 @@ jobs: GH_AW_FAILURE_REPORT_AS_ISSUE: "true" GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" - GH_AW_TIMEOUT_MINUTES: "30" + GH_AW_TIMEOUT_MINUTES: "15" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/supertonic-tts.md b/.github/workflows/supertonic-tts.md index 835443828ed..2fda836ad55 100644 --- a/.github/workflows/supertonic-tts.md +++ b/.github/workflows/supertonic-tts.md @@ -18,7 +18,7 @@ on: required: false type: string -timeout-minutes: 30 +timeout-minutes: 15 permissions: contents: read From a179939b3ee3df0719460bc54b7eda1b42c02d9c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Jun 2026 00:16:50 +0000 Subject: [PATCH 7/8] refactor: make supertonic self-contained in a single safe-outputs job Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/shared/supertonic.md | 220 ---------------- .github/workflows/supertonic-tts.lock.yml | 304 ++++++++++++---------- .github/workflows/supertonic-tts.md | 185 ++++++++----- 3 files changed, 282 insertions(+), 427 deletions(-) delete mode 100644 .github/workflows/shared/supertonic.md diff --git a/.github/workflows/shared/supertonic.md b/.github/workflows/shared/supertonic.md deleted file mode 100644 index 458a9b8d80d..00000000000 --- a/.github/workflows/shared/supertonic.md +++ /dev/null @@ -1,220 +0,0 @@ ---- -# Supertonic TTS HTTP Server -# -# Shared workflow that installs the Supertonic Python SDK, downloads the model, -# starts the HTTP server on port 7788, and provides curl instructions. -# -# Usage: -# imports: -# - shared/supertonic.md -# -# This import provides: -# - Supertonic TTS HTTP server on http://127.0.0.1:7788 -# - /v1/tts endpoint (native Supertonic API) -# - /v1/audio/speech endpoint (OpenAI-compatible) -# - 10 built-in voices (M1–M5, F1–F5), 31 languages -# - WAV, FLAC, and OGG output formats -# -# Prerequisites: -# - Python 3.8+ available on runner -# - Network access to pypi.org (python ecosystem) -# - Sufficient disk space (~400MB for model download on first run) -# - Recommended timeout-minutes: β‰₯ 20 to allow model download and server startup -# -# Note: The Supertonic model (~400MB) is downloaded from Hugging Face on the first -# run and cached in ~/.cache/supertonic3/. The model cache is stored in -# actions/cache keyed by OS and package version, so subsequent runs are fast. - -tools: - bash: - - "curl *" - - "cat *" - - "echo *" - - "kill *" - - "cp *" - - "mkdir *" - - "ls *" - - "python3 *" - - "python *" - -network: - allowed: - - python - -steps: - - name: Install Supertonic with server support - id: install-supertonic - run: | - set -e - mkdir -p /tmp/gh-aw/agent - if [ ! -d /tmp/gh-aw/agent/venv ]; then - python3 -m venv /tmp/gh-aw/agent/venv - fi - echo "/tmp/gh-aw/agent/venv/bin" >> "$GITHUB_PATH" - /tmp/gh-aw/agent/venv/bin/pip install --quiet 'supertonic[serve]' - SUPERTONIC_VERSION=$(/tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(supertonic.__version__)") - echo "version=$SUPERTONIC_VERSION" >> "$GITHUB_OUTPUT" - echo "Supertonic $SUPERTONIC_VERSION installed with server support" - - - name: Restore Supertonic model cache - uses: actions/cache/restore@v5.0.5 - with: - key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} - restore-keys: supertonic3-model-${{ runner.os }}- - path: ~/.cache/supertonic3 - - - name: Start Supertonic HTTP server - run: | - set -e - # Start server in background; first run downloads the model (~400MB) from HuggingFace - nohup /tmp/gh-aw/agent/venv/bin/supertonic serve \ - --host 127.0.0.1 --port 7788 \ - > /tmp/gh-aw/agent/supertonic.log 2>&1 & - STTC_PID=$! - echo $STTC_PID > /tmp/gh-aw/agent/supertonic.pid - echo "Supertonic server PID: $STTC_PID β€” logs at /tmp/gh-aw/agent/supertonic.log" - - - name: Wait for Supertonic server readiness - run: | - # Allow up to 3 minutes (60 iterations Γ— 3s each) to accommodate model download on first run - URL="http://127.0.0.1:7788/docs" - STATUS="" - for i in $(seq 1 60); do - STATUS=$(curl -sS -o /dev/null -w "%{http_code}" \ - --connect-timeout 5 --max-time 5 "$URL" || true) - [ "$STATUS" = "200" ] && echo "Supertonic server ready at http://127.0.0.1:7788" && break - if [ -z "$STATUS" ]; then STATUS="curl_error"; fi - echo "Waiting for Supertonic... ($i/60) (status: $STATUS)" && sleep 3 - done - if [ "$STATUS" != "200" ]; then - echo "Supertonic server failed to start after 3 minutes (final status: $STATUS)" - cat /tmp/gh-aw/agent/supertonic.log || true - exit 1 - fi - - - name: Save Supertonic model cache - uses: actions/cache/save@v5.0.5 - with: - key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} - path: ~/.cache/supertonic3 ---- - -## Supertonic TTS HTTP Server Ready - -The Supertonic text-to-speech HTTP server is running at `http://127.0.0.1:7788`. - -### Generate Audio with curl - -#### Native `/v1/tts` endpoint β€” full Supertonic parameter set - -```bash -curl -X POST http://127.0.0.1:7788/v1/tts \ - -H 'content-type: application/json' \ - -d '{ - "text": "Hello, this is a test of the Supertonic TTS system.", - "voice": "M1", - "lang": "en", - "steps": 8, - "speed": 1.05, - "response_format": "wav" - }' \ - -o /tmp/gh-aw/agent/output.wav -echo "Audio saved to /tmp/gh-aw/agent/output.wav" -``` - -Response headers include: -- `X-Audio-Duration` β€” duration of the generated audio in seconds -- `X-Sample-Rate` β€” sample rate (44100 Hz) -- `X-Supertonic-Version` β€” model version - -#### OpenAI-compatible `/v1/audio/speech` endpoint - -```bash -curl -X POST http://127.0.0.1:7788/v1/audio/speech \ - -H 'content-type: application/json' \ - -d '{ - "model": "supertonic-3", - "input": "Hello, this is a test of the Supertonic TTS system.", - "voice": "M1", - "response_format": "wav" - }' \ - -o /tmp/gh-aw/agent/output.wav -``` - -### Available Endpoints - -| Endpoint | Method | Description | -|---|---|---| -| `/v1/tts` | POST | Native synthesis β€” full Supertonic parameter set | -| `/v1/audio/speech` | POST | OpenAI-compatible speech endpoint | -| `/v1/styles` | GET | List all available voice styles | -| `/v1/styles/import` | POST | Upload a custom voice-style JSON (`multipart/form-data`) | -| `/docs` | GET | Interactive OpenAPI documentation | - -### Built-in Voices (10) - -| Category | Voices | -|---|---| -| **Male** | M1, M2, M3, M4, M5 | -| **Female** | F1, F2, F3, F4, F5 | - -### Supported Languages (31) - -`ar`, `bg`, `hr`, `cs`, `da`, `nl`, `en`, `et`, `fi`, `fr`, `de`, `el`, `hi`, `hu`, `id`, `it`, `ja`, `ko`, `lv`, `lt`, `pl`, `pt`, `ro`, `ru`, `sk`, `sl`, `es`, `sv`, `tr`, `uk`, `vi` - -Pass `"lang": "na"` for automatic language detection. - -### Quality and Speed Controls - -| Parameter | Range | Default | Notes | -|---|---|---|---| -| `steps` | 5–12 | 8 | Higher = better quality, slower synthesis | -| `speed` | 0.7–2.0 | 1.05 | Higher = faster speech | - -### Multilingual Example - -```bash -# English -curl -X POST http://127.0.0.1:7788/v1/tts \ - -H 'content-type: application/json' \ - -d '{"text":"Hello from the Supertonic TTS system!","voice":"F1","lang":"en"}' \ - -o /tmp/gh-aw/agent/english.wav - -# Spanish -curl -X POST http://127.0.0.1:7788/v1/tts \ - -H 'content-type: application/json' \ - -d '{"text":"Β‘Hola desde el sistema Supertonic!","voice":"F1","lang":"es"}' \ - -o /tmp/gh-aw/agent/spanish.wav - -# Auto-detect language -curl -X POST http://127.0.0.1:7788/v1/tts \ - -H 'content-type: application/json' \ - -d '{"text":"γ“γ‚“γ«γ‘γ―γ€γ‚ΉγƒΌγƒ‘γƒΌγƒˆγƒ‹γƒƒγ‚―γ§γ™γ€‚","voice":"M2","lang":"na"}' \ - -o /tmp/gh-aw/agent/japanese.wav -``` - -### Upload Generated Audio as a Run Artifact - -Stage the WAV file and call the `upload_artifact` safe-output tool: - -```bash -# Stage the file for upload -mkdir -p "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts" -cp /tmp/gh-aw/agent/output.wav \ - "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/voice-summary.wav" -``` - -Then call the safe-output tool with: -```json -{ "type": "upload_artifact", "path": "voice-summary.wav" } -``` - -The tool returns `slot_N_artifact_url` β€” a direct download link to the uploaded artifact. -Include this URL in any report or discussion to give readers access to the audio file. - -### Stop the Server (Optional Cleanup) - -```bash -kill $(cat /tmp/gh-aw/agent/supertonic.pid) 2>/dev/null || true -rm -f /tmp/gh-aw/agent/supertonic.pid /tmp/gh-aw/agent/supertonic.log -``` diff --git a/.github/workflows/supertonic-tts.lock.yml b/.github/workflows/supertonic-tts.lock.yml index a5f87646cd5..a28a1b22c12 100644 --- a/.github/workflows/supertonic-tts.lock.yml +++ b/.github/workflows/supertonic-tts.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"4305db3b5071e2ffbdf11d144e752d7ad4367c3337668309c3977bd488227096","body_hash":"74b680ce64faef0ee63722ccdd04ccd2c8a0228898545e74983b60300c072e0d","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a50da28862196defc0582e2d6ee9d1cee7b37f82a4bba20e19d12ca578b56a88","body_hash":"368d3c563ebcbbfd464f10ba1fc5a0fb26a85e8dba5b7449dbe65ae0ab3e7d00","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -23,11 +23,7 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Converts text to speech using the Supertonic on-device TTS server, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request -# -# Resolved workflow manifest: -# Imports: -# - shared/supertonic.md +# Converts text to speech using the Supertonic on-device TTS SDK, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request # # Secrets used: # - GH_AW_GITHUB_MCP_SERVER_TOKEN @@ -134,7 +130,7 @@ jobs: GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","python"]' + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]' GH_AW_INFO_FIREWALL_ENABLED: "true" GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_AWMG_VERSION: "" @@ -231,20 +227,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_2031fcd43d20b981_EOF' + cat << 'GH_AW_PROMPT_8f4d2dcc7d2b82db_EOF' - GH_AW_PROMPT_2031fcd43d20b981_EOF + GH_AW_PROMPT_8f4d2dcc7d2b82db_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_2031fcd43d20b981_EOF' + cat << 'GH_AW_PROMPT_8f4d2dcc7d2b82db_EOF' - Tools: add_comment, missing_tool, missing_data, noop + Tools: missing_tool, missing_data, noop, supertonic_tts - GH_AW_PROMPT_2031fcd43d20b981_EOF + GH_AW_PROMPT_8f4d2dcc7d2b82db_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_2031fcd43d20b981_EOF' + cat << 'GH_AW_PROMPT_8f4d2dcc7d2b82db_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -273,13 +269,12 @@ jobs: {{/if}} - GH_AW_PROMPT_2031fcd43d20b981_EOF + GH_AW_PROMPT_8f4d2dcc7d2b82db_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_2031fcd43d20b981_EOF' + cat << 'GH_AW_PROMPT_8f4d2dcc7d2b82db_EOF' - {{#runtime-import .github/workflows/shared/supertonic.md}} {{#runtime-import .github/workflows/supertonic-tts.md}} - GH_AW_PROMPT_2031fcd43d20b981_EOF + GH_AW_PROMPT_8f4d2dcc7d2b82db_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -440,35 +435,6 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" env: GH_TOKEN: ${{ github.token }} - - id: install-supertonic - name: Install Supertonic with server support - run: | - set -e - mkdir -p /tmp/gh-aw/agent - if [ ! -d /tmp/gh-aw/agent/venv ]; then - python3 -m venv /tmp/gh-aw/agent/venv - fi - echo "/tmp/gh-aw/agent/venv/bin" >> "$GITHUB_PATH" - /tmp/gh-aw/agent/venv/bin/pip install --quiet 'supertonic[serve]' - SUPERTONIC_VERSION=$(/tmp/gh-aw/agent/venv/bin/python3 -c "import supertonic; print(supertonic.__version__)") - echo "version=$SUPERTONIC_VERSION" >> "$GITHUB_OUTPUT" - echo "Supertonic $SUPERTONIC_VERSION installed with server support" - - name: Restore Supertonic model cache - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} - path: ~/.cache/supertonic3 - restore-keys: supertonic3-model-${{ runner.os }}- - - name: Start Supertonic HTTP server - run: "set -e\n# Start server in background; first run downloads the model (~400MB) from HuggingFace\nnohup /tmp/gh-aw/agent/venv/bin/supertonic serve \\\n --host 127.0.0.1 --port 7788 \\\n > /tmp/gh-aw/agent/supertonic.log 2>&1 &\nSTTC_PID=$!\necho $STTC_PID > /tmp/gh-aw/agent/supertonic.pid\necho \"Supertonic server PID: $STTC_PID β€” logs at /tmp/gh-aw/agent/supertonic.log\"\n" - - name: Wait for Supertonic server readiness - run: "# Allow up to 3 minutes (60 iterations Γ— 3s each) to accommodate model download on first run\nURL=\"http://127.0.0.1:7788/docs\"\nSTATUS=\"\"\nfor i in $(seq 1 60); do\n STATUS=$(curl -sS -o /dev/null -w \"%{http_code}\" \\\n --connect-timeout 5 --max-time 5 \"$URL\" || true)\n [ \"$STATUS\" = \"200\" ] && echo \"Supertonic server ready at http://127.0.0.1:7788\" && break\n if [ -z \"$STATUS\" ]; then STATUS=\"curl_error\"; fi\n echo \"Waiting for Supertonic... ($i/60) (status: $STATUS)\" && sleep 3\ndone\nif [ \"$STATUS\" != \"200\" ]; then\n echo \"Supertonic server failed to start after 3 minutes (final status: $STATUS)\"\n cat /tmp/gh-aw/agent/supertonic.log || true\n exit 1\nfi\n" - - name: Save Supertonic model cache - uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} - path: ~/.cache/supertonic3 - - name: Configure Git credentials env: REPO_NAME: ${{ github.repository }} @@ -539,44 +505,45 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_6f40227864c574a0_EOF' - {"add_comment":{"max":1},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":1,"retention-days":30,"skip-archive":true}} - GH_AW_SAFE_OUTPUTS_CONFIG_6f40227864c574a0_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_6d922f8ab7cd5e7c_EOF' + {"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"supertonic-tts":{"description":"Install Supertonic TTS, synthesize speech from text, upload as artifact, and post comment","inputs":{"issue_number":{"default":null,"description":"Issue number to post the artifact link to","required":false,"type":"string"},"pr_number":{"default":null,"description":"Pull request number to post the artifact link to","required":false,"type":"string"},"text":{"default":null,"description":"Text to synthesize","required":true,"type":"string"}}}} + GH_AW_SAFE_OUTPUTS_CONFIG_6d922f8ab7cd5e7c_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | { - "description_suffixes": { - "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading." - }, + "description_suffixes": {}, "repo_params": {}, - "dynamic_tools": [] + "dynamic_tools": [ + { + "description": "Install Supertonic TTS, synthesize speech from text, upload as artifact, and post comment", + "inputSchema": { + "additionalProperties": false, + "properties": { + "issue_number": { + "description": "Issue number to post the artifact link to", + "type": "string" + }, + "pr_number": { + "description": "Pull request number to post the artifact link to", + "type": "string" + }, + "text": { + "description": "Text to synthesize", + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + }, + "name": "supertonic_tts" + } + ] } GH_AW_VALIDATION_JSON: | { - "add_comment": { - "defaultMax": 1, - "fields": { - "body": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - }, - "item_number": { - "issueOrPRNumber": true - }, - "reply_to_id": { - "type": "string", - "maxLength": 256 - }, - "repo": { - "type": "string", - "maxLength": 256 - } - } - }, "missing_data": { "defaultMax": 20, "fields": { @@ -802,30 +769,6 @@ jobs: - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): - # --allow-tool github - # --allow-tool safeoutputs - # --allow-tool shell(cat) - # --allow-tool shell(cp) - # --allow-tool shell(curl:*) - # --allow-tool shell(date) - # --allow-tool shell(echo) - # --allow-tool shell(grep) - # --allow-tool shell(head) - # --allow-tool shell(jq) - # --allow-tool shell(kill) - # --allow-tool shell(ls) - # --allow-tool shell(mkdir) - # --allow-tool shell(printf) - # --allow-tool shell(pwd) - # --allow-tool shell(python) - # --allow-tool shell(python3) - # --allow-tool shell(safeoutputs:*) - # --allow-tool shell(sort) - # --allow-tool shell(tail) - # --allow-tool shell(uniq) - # --allow-tool shell(wc) - # --allow-tool shell(yq) - # --allow-tool write timeout-minutes: 15 run: | set -o pipefail @@ -841,7 +784,7 @@ jobs: export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" (umask 177 && touch /tmp/gh-aw/agent-stdio.log) GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-1000}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.pythonhosted.org\",\"anaconda.org\",\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"binstar.org\",\"bootstrap.pypa.io\",\"conda.anaconda.org\",\"conda.binstar.org\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"files.pythonhosted.org\",\"github.com\",\"host.docker.internal\",\"json-schema.org\",\"json.schemastore.org\",\"keyserver.ubuntu.com\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"pip.pypa.io\",\"ppa.launchpad.net\",\"pypi.org\",\"pypi.python.org\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"repo.anaconda.com\",\"repo.continuum.io\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"json-schema.org\",\"json.schemastore.org\",\"keyserver.ubuntu.com\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST="" @@ -862,8 +805,8 @@ jobs: GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" fi # shellcheck disable=SC1003 - sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts:${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts:rw" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner β€” check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(cp)'\'' --allow-tool '\''shell(curl:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(kill)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(mkdir)'\'' --allow-tool '\''shell(printf)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(python)'\'' --allow-tool '\''shell(python3)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --no-custom-instructions --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner β€” check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --no-custom-instructions --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -954,7 +897,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -1025,15 +968,6 @@ jobs: if [ ! -f /tmp/gh-aw/agent_output.json ]; then echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi - # Upload safe-outputs upload-artifact staging for the upload_artifact job - - name: Upload upload-artifact staging - if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: safe-outputs-upload-artifacts - path: ${{ runner.temp }}/gh-aw/safeoutputs/upload-artifacts/ - retention-days: 1 - if-no-files-found: ignore - name: Upload agent artifacts if: always() continue-on-error: true @@ -1066,14 +1000,12 @@ jobs: - agent - detection - safe_outputs + - supertonic_tts if: > always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_ai_credits_exceeded == 'true') runs-on: ubuntu-slim - permissions: - contents: read - issues: write - pull-requests: write + permissions: {} concurrency: group: "gh-aw-conclusion-supertonic-tts" cancel-in-progress: false @@ -1400,7 +1332,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: WORKFLOW_NAME: "Supertonic TTS" - WORKFLOW_DESCRIPTION: "Converts text to speech using the Supertonic on-device TTS server, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request" + WORKFLOW_DESCRIPTION: "Converts text to speech using the Supertonic on-device TTS SDK, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1553,10 +1485,7 @@ jobs: - detection if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' runs-on: ubuntu-slim - permissions: - contents: read - issues: write - pull-requests: write + permissions: {} timeout-minutes: 45 env: GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }} @@ -1578,14 +1507,10 @@ jobs: outputs: code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} - comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} - comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} - upload_artifact_count: ${{ steps.process_safe_outputs.outputs.upload_artifact_count }} - upload_artifact_slot_0_tmp_id: ${{ steps.process_safe_outputs.outputs.slot_0_tmp_id }} steps: - name: Checkout actions folder uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -1602,7 +1527,6 @@ jobs: job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} - safe-output-artifact-client: 'true' env: GH_AW_SETUP_WORKFLOW_NAME: "Supertonic TTS" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/supertonic-tts.lock.yml@${{ github.ref }} @@ -1633,22 +1557,17 @@ jobs: GH_HOST="${GITHUB_SERVER_URL#https://}" GH_HOST="${GH_HOST#http://}" echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - - name: Download upload-artifact staging - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: safe-outputs-upload-artifacts - path: ${{ runner.temp }}/gh-aw/safeoutputs/upload-artifacts/ - name: Process Safe Outputs id: process_safe_outputs uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} - GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{},\"upload_artifact\":{\"max-size-bytes\":104857600,\"max-uploads\":1,\"retention-days\":30,\"skip-archive\":true}}" + GH_AW_SAFE_OUTPUT_JOBS: "{\"supertonic_tts\":\"\"}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1666,3 +1585,118 @@ jobs: /tmp/gh-aw/temporary-id-map.json if-no-files-found: ignore + supertonic_tts: + needs: + - agent + - detection + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'supertonic_tts') + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write + steps: + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: ${{ runner.temp }}/gh-aw/safe-jobs/ + - name: Install Supertonic with server support + id: install-supertonic + run: | + set -e + mkdir -p /tmp/gh-aw/tts + python3 -m venv /tmp/gh-aw/tts/venv + /tmp/gh-aw/tts/venv/bin/pip install --quiet 'supertonic[serve]' + SUPERTONIC_VERSION=$(/tmp/gh-aw/tts/venv/bin/python3 -c "import supertonic; print(supertonic.__version__)") + echo "version=$SUPERTONIC_VERSION" >> "$GITHUB_OUTPUT" + echo "Supertonic $SUPERTONIC_VERSION installed" + env: + GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json + - name: Restore Supertonic model cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + env: + GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + path: ~/.cache/supertonic3 + restore-keys: supertonic3-model-${{ runner.os }}- + - name: Start Supertonic HTTP server + run: | + set -e + nohup /tmp/gh-aw/tts/venv/bin/supertonic serve \ + --host 127.0.0.1 --port 7788 \ + > /tmp/gh-aw/tts/supertonic.log 2>&1 & + echo $! > /tmp/gh-aw/tts/supertonic.pid + echo "Server PID: $(cat /tmp/gh-aw/tts/supertonic.pid)" + env: + GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json + - name: Wait for Supertonic server readiness + run: | + URL="http://127.0.0.1:7788/docs" + STATUS="" + for i in $(seq 1 60); do + STATUS=$(curl -sS -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 5 "$URL" || true) + [ "$STATUS" = "200" ] && echo "Server ready at http://127.0.0.1:7788" && break + [ -z "$STATUS" ] && STATUS="curl_error" + echo "Waiting for server... ($i/60, status: $STATUS)" && sleep 3 + done + if [ "$STATUS" != "200" ]; then + cat /tmp/gh-aw/tts/supertonic.log || true + exit 1 + fi + env: + GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json + - name: Synthesize speech + id: synthesize + run: | + set -e + TEXT=$(jq -r '.items[] | select(.type == "supertonic_tts") | .text' "$GH_AW_AGENT_OUTPUT" | head -1) + ISSUE_NUMBER=$(jq -r '.items[] | select(.type == "supertonic_tts") | .issue_number // empty' "$GH_AW_AGENT_OUTPUT" | head -1) + PR_NUMBER=$(jq -r '.items[] | select(.type == "supertonic_tts") | .pr_number // empty' "$GH_AW_AGENT_OUTPUT" | head -1) + echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT" + echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" + curl -sS -X POST http://127.0.0.1:7788/v1/tts \ + -H 'content-type: application/json' \ + --data-binary "$(jq -n --arg t "$TEXT" '{"text": $t, "voice": "F1", "lang": "en", "steps": 8}')" \ + -o /tmp/gh-aw/tts/output.wav + echo "Audio generated: $(ls -lh /tmp/gh-aw/tts/output.wav)" + env: + GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json + - name: Save Supertonic model cache + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + env: + GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + path: ~/.cache/supertonic3 + - name: Upload audio artifact + id: upload + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + env: + GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json + with: + name: tts-output + path: /tmp/gh-aw/tts/output.wav + retention-days: 30 + - name: Post comment with artifact link + run: | + ITEM_NUMBER="${ISSUE_NUMBER:-$PR_NUMBER}" + if [ -z "$ITEM_NUMBER" ]; then + echo "No target item number found in agent output, skipping comment" + exit 0 + fi + mkdir -p /tmp/gh-aw/tts + jq -n --arg url "$ARTIFACT_URL" \ + '{"body": ("πŸ”Š **Voice summary ready**\n\n[🎧 Download tts-output.wav](" + $url + ")")}' \ + > /tmp/gh-aw/tts/comment.json + gh api "repos/$REPO/issues/$ITEM_NUMBER/comments" --input /tmp/gh-aw/tts/comment.json + env: + ARTIFACT_URL: ${{ steps.upload.outputs.artifact-url }} + GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json + GH_TOKEN: ${{ github.token }} + ISSUE_NUMBER: ${{ steps.synthesize.outputs.issue_number }} + PR_NUMBER: ${{ steps.synthesize.outputs.pr_number }} + REPO: ${{ github.repository }} + diff --git a/.github/workflows/supertonic-tts.md b/.github/workflows/supertonic-tts.md index 2fda836ad55..86c8f739978 100644 --- a/.github/workflows/supertonic-tts.md +++ b/.github/workflows/supertonic-tts.md @@ -1,7 +1,7 @@ --- emoji: "πŸ”Š" name: Supertonic TTS -description: Converts text to speech using the Supertonic on-device TTS server, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request +description: Converts text to speech using the Supertonic on-device TTS SDK, uploads the generated audio as a run artifact, and posts a comment with the download link on the target issue or pull request on: workflow_dispatch: inputs: @@ -30,32 +30,112 @@ engine: id: copilot bare: true -imports: - - shared/supertonic.md - -network: - allowed: - - defaults - - python - -tools: - bash: - - "curl *" - - "jq *" - - "cp *" - - "mkdir *" - - "ls *" - - "echo *" - - "cat *" - safe-outputs: - upload-artifact: - max-uploads: 1 - retention-days: 30 - skip-archive: true - add-comment: - max: 1 noop: + jobs: + supertonic-tts: + description: "Install Supertonic TTS, synthesize speech from text, upload as artifact, and post comment" + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write + inputs: + text: + type: string + required: true + description: "Text to synthesize" + issue_number: + type: string + required: false + description: "Issue number to post the artifact link to" + pr_number: + type: string + required: false + description: "Pull request number to post the artifact link to" + steps: + - name: Install Supertonic with server support + id: install-supertonic + run: | + set -e + mkdir -p /tmp/gh-aw/tts + python3 -m venv /tmp/gh-aw/tts/venv + /tmp/gh-aw/tts/venv/bin/pip install --quiet 'supertonic[serve]' + SUPERTONIC_VERSION=$(/tmp/gh-aw/tts/venv/bin/python3 -c "import supertonic; print(supertonic.__version__)") + echo "version=$SUPERTONIC_VERSION" >> "$GITHUB_OUTPUT" + echo "Supertonic $SUPERTONIC_VERSION installed" + - name: Restore Supertonic model cache + uses: actions/cache/restore@v5.0.5 + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + restore-keys: supertonic3-model-${{ runner.os }}- + path: ~/.cache/supertonic3 + - name: Start Supertonic HTTP server + run: | + set -e + nohup /tmp/gh-aw/tts/venv/bin/supertonic serve \ + --host 127.0.0.1 --port 7788 \ + > /tmp/gh-aw/tts/supertonic.log 2>&1 & + echo $! > /tmp/gh-aw/tts/supertonic.pid + echo "Server PID: $(cat /tmp/gh-aw/tts/supertonic.pid)" + - name: Wait for Supertonic server readiness + run: | + URL="http://127.0.0.1:7788/docs" + STATUS="" + for i in $(seq 1 60); do + STATUS=$(curl -sS -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 5 "$URL" || true) + [ "$STATUS" = "200" ] && echo "Server ready at http://127.0.0.1:7788" && break + [ -z "$STATUS" ] && STATUS="curl_error" + echo "Waiting for server... ($i/60, status: $STATUS)" && sleep 3 + done + if [ "$STATUS" != "200" ]; then + cat /tmp/gh-aw/tts/supertonic.log || true + exit 1 + fi + - name: Synthesize speech + id: synthesize + run: | + set -e + TEXT=$(jq -r '.items[] | select(.type == "supertonic_tts") | .text' "$GH_AW_AGENT_OUTPUT" | head -1) + ISSUE_NUMBER=$(jq -r '.items[] | select(.type == "supertonic_tts") | .issue_number // empty' "$GH_AW_AGENT_OUTPUT" | head -1) + PR_NUMBER=$(jq -r '.items[] | select(.type == "supertonic_tts") | .pr_number // empty' "$GH_AW_AGENT_OUTPUT" | head -1) + echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT" + echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" + curl -sS -X POST http://127.0.0.1:7788/v1/tts \ + -H 'content-type: application/json' \ + --data-binary "$(jq -n --arg t "$TEXT" '{"text": $t, "voice": "F1", "lang": "en", "steps": 8}')" \ + -o /tmp/gh-aw/tts/output.wav + echo "Audio generated: $(ls -lh /tmp/gh-aw/tts/output.wav)" + - name: Save Supertonic model cache + uses: actions/cache/save@v5.0.5 + with: + key: supertonic3-model-${{ runner.os }}-${{ steps.install-supertonic.outputs.version }} + path: ~/.cache/supertonic3 + - name: Upload audio artifact + id: upload + uses: actions/upload-artifact@v7.0.1 + with: + name: tts-output + path: /tmp/gh-aw/tts/output.wav + retention-days: 30 + - name: Post comment with artifact link + run: | + ITEM_NUMBER="${ISSUE_NUMBER:-$PR_NUMBER}" + if [ -z "$ITEM_NUMBER" ]; then + echo "No target item number found in agent output, skipping comment" + exit 0 + fi + mkdir -p /tmp/gh-aw/tts + jq -n --arg url "$ARTIFACT_URL" \ + '{"body": ("πŸ”Š **Voice summary ready**\n\n[🎧 Download tts-output.wav](" + $url + ")")}' \ + > /tmp/gh-aw/tts/comment.json + gh api "repos/$REPO/issues/$ITEM_NUMBER/comments" --input /tmp/gh-aw/tts/comment.json + env: + GH_TOKEN: ${{ github.token }} + ARTIFACT_URL: ${{ steps.upload.outputs.artifact-url }} + ISSUE_NUMBER: ${{ steps.synthesize.outputs.issue_number }} + PR_NUMBER: ${{ steps.synthesize.outputs.pr_number }} + REPO: ${{ github.repository }} --- # Supertonic TTS @@ -78,63 +158,24 @@ Exactly one of `issue-number` or `pr-number` must be provided. Check the inputs: - If **neither** is set: call `noop` with message `"Neither issue-number nor pr-number was provided. Provide exactly one."` and stop. - Otherwise: proceed. -### Step 2 β€” Synthesize speech - -The Supertonic TTS server is running at `http://127.0.0.1:7788`. Use `jq` to safely encode the input text and avoid shell escaping issues: - -```bash -mkdir -p /tmp/gh-aw/agent - -# Write the text to a file to avoid here-doc quoting issues -cat > /tmp/gh-aw/agent/tts-input.txt << 'TTS_EOF' -${{ github.event.inputs.text }} -TTS_EOF - -SUMMARY_TEXT=$(cat /tmp/gh-aw/agent/tts-input.txt) -curl -sS -X POST http://127.0.0.1:7788/v1/tts \ - -H 'content-type: application/json' \ - --data-binary "{\"text\": $(jq -n --arg t "$SUMMARY_TEXT" '$t'), \"voice\": \"F1\", \"lang\": \"en\", \"steps\": 8}" \ - -o /tmp/gh-aw/agent/tts-output.wav -echo "Audio generated: $(ls -lh /tmp/gh-aw/agent/tts-output.wav)" -``` - -### Step 3 β€” Upload as a run artifact +### Step 2 β€” Submit TTS request -Stage the WAV file and call the `upload_artifact` safe-output tool: - -```bash -mkdir -p "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts" -cp /tmp/gh-aw/agent/tts-output.wav \ - "$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/tts-output.wav" -``` - -Call the safe-output tool: -```json -{ "type": "upload_artifact", "path": "tts-output.wav" } -``` - -The tool returns `slot_N_artifact_url` β€” the direct download link to the uploaded file. - -### Step 4 β€” Post comment with download link - -Use `add_comment` to post the artifact link on the target item. +Call the `supertonic_tts` safe-output tool with the text and the target issue or PR number. If `issue-number` is set (e.g., `42`): ```json { - "type": "add_comment", - "issue_number": 42, - "body": "πŸ”Š **Voice summary ready**\n\n[🎧 Download tts-output.wav]()" + "type": "supertonic_tts", + "text": "${{ github.event.inputs.text }}", + "issue_number": "42" } ``` If `pr-number` is set (e.g., `99`): ```json { - "type": "add_comment", - "pr_number": 99, - "body": "πŸ”Š **Voice summary ready**\n\n[🎧 Download tts-output.wav]()" + "type": "supertonic_tts", + "text": "${{ github.event.inputs.text }}", + "pr_number": "99" } ``` - -Replace `` with the `slot_N_artifact_url` returned by the `upload_artifact` tool. From 321ee5a924ea27032fb48db09a4c49db0941917b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Jun 2026 00:20:00 +0000 Subject: [PATCH 8/8] fix: validate text field and rename ITEM_NUMBER to TARGET_NUMBER Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/supertonic-tts.lock.yml | 12 ++++++++---- .github/workflows/supertonic-tts.md | 10 +++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/supertonic-tts.lock.yml b/.github/workflows/supertonic-tts.lock.yml index a28a1b22c12..398a1dee920 100644 --- a/.github/workflows/supertonic-tts.lock.yml +++ b/.github/workflows/supertonic-tts.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a50da28862196defc0582e2d6ee9d1cee7b37f82a4bba20e19d12ca578b56a88","body_hash":"368d3c563ebcbbfd464f10ba1fc5a0fb26a85e8dba5b7449dbe65ae0ab3e7d00","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"348cdadb534858d2f00ef13f9c48861e6d9b7e147a34c23532538cf69bf7364f","body_hash":"368d3c563ebcbbfd464f10ba1fc5a0fb26a85e8dba5b7449dbe65ae0ab3e7d00","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -1655,6 +1655,10 @@ jobs: TEXT=$(jq -r '.items[] | select(.type == "supertonic_tts") | .text' "$GH_AW_AGENT_OUTPUT" | head -1) ISSUE_NUMBER=$(jq -r '.items[] | select(.type == "supertonic_tts") | .issue_number // empty' "$GH_AW_AGENT_OUTPUT" | head -1) PR_NUMBER=$(jq -r '.items[] | select(.type == "supertonic_tts") | .pr_number // empty' "$GH_AW_AGENT_OUTPUT" | head -1) + if [ -z "$TEXT" ]; then + echo "Error: no text found in supertonic_tts agent output item" + exit 1 + fi echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT" echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" curl -sS -X POST http://127.0.0.1:7788/v1/tts \ @@ -1682,8 +1686,8 @@ jobs: retention-days: 30 - name: Post comment with artifact link run: | - ITEM_NUMBER="${ISSUE_NUMBER:-$PR_NUMBER}" - if [ -z "$ITEM_NUMBER" ]; then + TARGET_NUMBER="${ISSUE_NUMBER:-$PR_NUMBER}" + if [ -z "$TARGET_NUMBER" ]; then echo "No target item number found in agent output, skipping comment" exit 0 fi @@ -1691,7 +1695,7 @@ jobs: jq -n --arg url "$ARTIFACT_URL" \ '{"body": ("πŸ”Š **Voice summary ready**\n\n[🎧 Download tts-output.wav](" + $url + ")")}' \ > /tmp/gh-aw/tts/comment.json - gh api "repos/$REPO/issues/$ITEM_NUMBER/comments" --input /tmp/gh-aw/tts/comment.json + gh api "repos/$REPO/issues/$TARGET_NUMBER/comments" --input /tmp/gh-aw/tts/comment.json env: ARTIFACT_URL: ${{ steps.upload.outputs.artifact-url }} GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json diff --git a/.github/workflows/supertonic-tts.md b/.github/workflows/supertonic-tts.md index 86c8f739978..c11b303b793 100644 --- a/.github/workflows/supertonic-tts.md +++ b/.github/workflows/supertonic-tts.md @@ -99,6 +99,10 @@ safe-outputs: TEXT=$(jq -r '.items[] | select(.type == "supertonic_tts") | .text' "$GH_AW_AGENT_OUTPUT" | head -1) ISSUE_NUMBER=$(jq -r '.items[] | select(.type == "supertonic_tts") | .issue_number // empty' "$GH_AW_AGENT_OUTPUT" | head -1) PR_NUMBER=$(jq -r '.items[] | select(.type == "supertonic_tts") | .pr_number // empty' "$GH_AW_AGENT_OUTPUT" | head -1) + if [ -z "$TEXT" ]; then + echo "Error: no text found in supertonic_tts agent output item" + exit 1 + fi echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT" echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" curl -sS -X POST http://127.0.0.1:7788/v1/tts \ @@ -120,8 +124,8 @@ safe-outputs: retention-days: 30 - name: Post comment with artifact link run: | - ITEM_NUMBER="${ISSUE_NUMBER:-$PR_NUMBER}" - if [ -z "$ITEM_NUMBER" ]; then + TARGET_NUMBER="${ISSUE_NUMBER:-$PR_NUMBER}" + if [ -z "$TARGET_NUMBER" ]; then echo "No target item number found in agent output, skipping comment" exit 0 fi @@ -129,7 +133,7 @@ safe-outputs: jq -n --arg url "$ARTIFACT_URL" \ '{"body": ("πŸ”Š **Voice summary ready**\n\n[🎧 Download tts-output.wav](" + $url + ")")}' \ > /tmp/gh-aw/tts/comment.json - gh api "repos/$REPO/issues/$ITEM_NUMBER/comments" --input /tmp/gh-aw/tts/comment.json + gh api "repos/$REPO/issues/$TARGET_NUMBER/comments" --input /tmp/gh-aw/tts/comment.json env: GH_TOKEN: ${{ github.token }} ARTIFACT_URL: ${{ steps.upload.outputs.artifact-url }}