Aeon #35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Aeon | |
| "on": | |
| workflow_dispatch: | |
| inputs: | |
| skill: | |
| description: Skill name | |
| required: false | |
| default: digest | |
| var: | |
| description: Skill var | |
| required: false | |
| default: "" | |
| model: | |
| description: Model override | |
| required: false | |
| default: "" | |
| charon_approval: | |
| description: Charon approval id | |
| required: false | |
| default: "" | |
| jobs: | |
| run: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| actions: write | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - id: work | |
| run: echo "mode=skill" >> "$GITHUB_OUTPUT" | |
| - id: skill | |
| run: echo "name=${{ inputs.skill || 'digest' }}" >> "$GITHUB_OUTPUT" | |
| - name: Charon approval | |
| if: inputs.charon_approval != '' | |
| run: | | |
| { | |
| echo "### Charon approval" | |
| echo "" | |
| echo "- review: \`${{ inputs.charon_approval }}\`" | |
| echo "- preflight: \`approved by Telegram callback\`" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| # >>> charon aeon preflight | |
| - name: Charon preflight | |
| id: charon_preflight | |
| if: steps.work.outputs.mode != '' && inputs.charon_approval == '' | |
| env: | |
| SKILL: ${{ steps.skill.outputs.name }} | |
| SKILL_VAR: ${{ inputs.var }} | |
| AEON_ACTOR: ${{ github.actor }} | |
| AEON_TRIGGER: ${{ github.event_name == 'repository_dispatch' && github.event.action || github.event_name }} | |
| run: | | |
| set +e | |
| mkdir -p .charon/aeon | |
| npx -y github:CharonAI-code/charon aeon preflight \ | |
| --skill "$SKILL" \ | |
| --var "$SKILL_VAR" \ | |
| --trigger "$AEON_TRIGGER" \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --run-id "$GITHUB_RUN_ID" \ | |
| --actor "$AEON_ACTOR" \ | |
| --policy charon.aeon.yml \ | |
| --review > .charon/aeon/preflight.json | |
| code=$? | |
| cat .charon/aeon/preflight.json | |
| if [ "$code" = "125" ]; then | |
| npx -y github:CharonAI-code/charon aeon telegram send latest || true | |
| elif [ "$code" = "126" ]; then | |
| npx -y github:CharonAI-code/charon aeon telegram send --preflight .charon/aeon/preflight.json || true | |
| fi | |
| exit "$code" | |
| - name: Charon review export | |
| if: always() | |
| id: charon_review | |
| run: | | |
| npx -y github:CharonAI-code/charon aeon review export latest --github-output "$GITHUB_OUTPUT" || true | |
| for file in .charon/aeon/exports/*.md; do | |
| if [ -f "$file" ]; then cat "$file" >> "$GITHUB_STEP_SUMMARY"; fi | |
| done | |
| # <<< charon aeon preflight | |
| - name: Run pre-fetch scripts | |
| run: echo "prefetch" | |
| - name: Run | |
| id: aeon_run | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| ANTHROPIC_BASE_URL: ${{ vars.ANTHROPIC_BASE_URL }} | |
| BANKR_LLM_KEY: ${{ secrets.BANKR_LLM_KEY }} | |
| OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} | |
| USEPOD_TOKEN: ${{ secrets.USEPOD_TOKEN }} | |
| VENICE_API_KEY: ${{ secrets.VENICE_API_KEY }} | |
| SURPLUS_API_KEY: ${{ secrets.SURPLUS_API_KEY }} | |
| OPENROUTER_MODEL: ${{ vars.OPENROUTER_MODEL }} | |
| OPENROUTER_MODEL_SONNET: ${{ vars.OPENROUTER_MODEL_SONNET }} | |
| OPENROUTER_MODEL_HAIKU: ${{ vars.OPENROUTER_MODEL_HAIKU }} | |
| USEPOD_MODEL: ${{ vars.USEPOD_MODEL }} | |
| USEPOD_MODEL_SONNET: ${{ vars.USEPOD_MODEL_SONNET }} | |
| USEPOD_MODEL_HAIKU: ${{ vars.USEPOD_MODEL_HAIKU }} | |
| VENICE_MODEL: ${{ vars.VENICE_MODEL }} | |
| VENICE_BASE_URL: ${{ vars.VENICE_BASE_URL }} | |
| VENICE_CLEANCACHE: ${{ vars.VENICE_CLEANCACHE }} | |
| SURPLUS_MODEL: ${{ vars.SURPLUS_MODEL }} | |
| CCR_LOG: ${{ vars.CCR_LOG }} | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} | |
| INPUT_MODEL: ${{ inputs.model }} | |
| SKILL_NAME: ${{ steps.skill.outputs.name }} | |
| SKILL_VAR: ${{ inputs.var }} | |
| run: | | |
| if ! command -v claude >/dev/null 2>&1; then | |
| npm install -g @anthropic-ai/claude-code@2.1.168 >/dev/null | |
| fi | |
| CONFIG_MODEL="$(grep -E '^model:' aeon.yml | sed 's/^model: *//' | tr -d ' \"')" | |
| SKILL_MODEL="$(grep "^ ${SKILL_NAME}:" aeon.yml | sed -n 's/.*model: *\"\([^\"]*\)\".*/\1/p')" | |
| if [ -n "$INPUT_MODEL" ] && [ "$INPUT_MODEL" != "(config default)" ]; then | |
| MODEL="$INPUT_MODEL" | |
| elif [ -n "$SKILL_MODEL" ]; then | |
| MODEL="$SKILL_MODEL" | |
| else | |
| MODEL="${CONFIG_MODEL:-claude-opus-4-8}" | |
| fi | |
| echo "Using model: $MODEL" | |
| echo "SKILL_MODEL=$MODEL" >> "$GITHUB_OUTPUT" | |
| BASE_MODEL="$MODEL" | |
| GW="${GITHUB_WORKSPACE}/scripts/llm-gateway.sh" | |
| GATEWAY=$(grep -A1 '^gateway:' aeon.yml | grep 'provider:' | sed 's/.*provider:[[:space:]]*//' | sed "s/[\"' ]//g" || true) | |
| GATEWAY="${GATEWAY:-auto}" | |
| if [ "$GATEWAY" = "auto" ]; then | |
| CANDIDATES=$(AEON_LIST_CANDIDATES=1 bash "$GW") | |
| else | |
| CANDIDATES="$GATEWAY" | |
| fi | |
| echo "Gateway: $GATEWAY | cascade order: $CANDIDATES" | |
| cat > ./notify <<'NOTIFY' | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| msg="$1" | |
| touch .aeon-notified | |
| if [ -n "${TELEGRAM_BOT_TOKEN:-}" ] && [ -n "${TELEGRAM_CHAT_ID:-}" ]; then | |
| curl -fsS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ | |
| -d "chat_id=${TELEGRAM_CHAT_ID}" \ | |
| --data-urlencode "text=${msg}" \ | |
| -d "disable_web_page_preview=true" >/dev/null || true | |
| fi | |
| NOTIFY | |
| chmod +x ./notify | |
| ALLOWED="Bash(git:*),Bash(./notify:*),Write,Edit" | |
| prompt="$(printf 'Run AEON skill: %s\n\nTask:\n%s\n\nWhen finished, send the user a concise result through ./notify. Include what changed or what happened. Do not only say complete.' "$SKILL_NAME" "$SKILL_VAR")" | |
| CLAUDE_OK=0 | |
| USED_GATEWAY="" | |
| for cand in $CANDIDATES; do | |
| echo "::notice::Routing attempt via '$cand'" | |
| if CLAUDE_OUTPUT=$( | |
| GATEWAY="$cand" | |
| MODEL="$BASE_MODEL" | |
| source "$GW" >&2 | |
| echo "$prompt" | claude -p - --model "$MODEL" --allowedTools "$ALLOWED" --output-format json 2>&1 | |
| ); then | |
| USED_GATEWAY="$cand" | |
| CLAUDE_OK=1 | |
| break | |
| fi | |
| echo "::warning::provider '$cand' failed - $(printf '%s' "$CLAUDE_OUTPUT" | tail -c 160 | tr '\n' ' ')" | |
| done | |
| if [ "$CLAUDE_OK" != "1" ]; then | |
| echo "::error::All gateway providers failed ($CANDIDATES). Last output: $CLAUDE_OUTPUT" | |
| exit 1 | |
| fi | |
| echo "GATEWAY=$USED_GATEWAY" >> "$GITHUB_OUTPUT" | |
| RESULT_TEXT="$(echo "$CLAUDE_OUTPUT" | jq -r '.result // empty')" | |
| printf '%s\n' "$RESULT_TEXT" | |
| if [ ! -f .aeon-notified ]; then | |
| summary="$(printf '%s' "$RESULT_TEXT" | tail -c 3000)" | |
| ./notify "$(printf 'AEON result\n\n%s' "$summary")" || true | |
| fi |