mirror of
https://github.com/openai/codex.git
synced 2026-03-28 19:16:30 +03:00
Compare commits
4 Commits
latest-alp
...
pr16056
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a547507e48 | ||
|
|
f4f6eca871 | ||
|
|
d65deec617 | ||
|
|
307e427a9b |
8
.github/workflows/bazel.yml
vendored
8
.github/workflows/bazel.yml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
name: Local Bazel build on ${{ matrix.os }} for ${{ matrix.target }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel CI
|
||||
id: setup_bazel
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled() && steps.setup_bazel.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
~/.cache/bazel-repo-cache
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
name: Bazel clippy on ${{ matrix.os }} for ${{ matrix.target }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel CI
|
||||
id: setup_bazel
|
||||
@@ -136,7 +136,7 @@ jobs:
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled() && steps.setup_bazel.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
~/.cache/bazel-repo-cache
|
||||
|
||||
2
.github/workflows/blob-size-policy.yml
vendored
2
.github/workflows/blob-size-policy.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
name: Blob size policy
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
6
.github/workflows/cargo-deny.yml
vendored
6
.github/workflows/cargo-deny.yml
vendored
@@ -14,13 +14,13 @@ jobs:
|
||||
working-directory: ./codex-rs
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
||||
|
||||
- name: Run cargo-deny
|
||||
uses: EmbarkStudios/cargo-deny-action@v2
|
||||
uses: EmbarkStudios/cargo-deny-action@82eb9f621fbc699dd0918f3ea06864c14cc84246 # v2
|
||||
with:
|
||||
rust-version: stable
|
||||
manifest-path: ./codex-rs/Cargo.toml
|
||||
|
||||
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@@ -12,15 +12,15 @@ jobs:
|
||||
NODE_OPTIONS: --max-old-space-size=4096
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v5
|
||||
uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
# stage_npm_packages.py requires DotSlash when staging releases.
|
||||
- uses: facebook/install-dotslash@v2
|
||||
- uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
- name: Stage npm package
|
||||
id: stage_npm_package
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
echo "pack_output=$PACK_OUTPUT" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload staged npm package artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: codex-npm-staging
|
||||
path: ${{ steps.stage_npm_package.outputs.pack_output }}
|
||||
|
||||
2
.github/workflows/cla.yml
vendored
2
.github/workflows/cla.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
if: ${{ github.repository_owner == 'openai' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: contributor-assistant/github-action@v2.6.1
|
||||
- uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
|
||||
# Run on close only if the PR was merged. This will lock the PR to preserve
|
||||
# the CLA agreement. We don't want to lock PRs that have been closed without
|
||||
# merging because the contributor may want to respond with additional comments.
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Close inactive PRs from contributors
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
||||
2
.github/workflows/codespell.yml
vendored
2
.github/workflows/codespell.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- name: Annotate locations with typos
|
||||
uses: codespell-project/codespell-problem-matcher@b80729f885d32f78a716c2f107b4db1025001c42 # v1
|
||||
- name: Codespell
|
||||
|
||||
10
.github/workflows/issue-deduplicator.yml
vendored
10
.github/workflows/issue-deduplicator.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
reason: ${{ steps.normalize-all.outputs.reason }}
|
||||
has_matches: ${{ steps.normalize-all.outputs.has_matches }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Prepare Codex inputs
|
||||
env:
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
# .github/prompts/issue-deduplicator.txt file is obsolete and removed.
|
||||
- id: codex-all
|
||||
name: Find duplicates (pass 1, all issues)
|
||||
uses: openai/codex-action@main
|
||||
uses: openai/codex-action@0b91f4a2703c23df3102c3f0967d3c6db34eedef # v1
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
@@ -155,7 +155,7 @@ jobs:
|
||||
reason: ${{ steps.normalize-open.outputs.reason }}
|
||||
has_matches: ${{ steps.normalize-open.outputs.has_matches }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Prepare Codex inputs
|
||||
env:
|
||||
@@ -195,7 +195,7 @@ jobs:
|
||||
|
||||
- id: codex-open
|
||||
name: Find duplicates (pass 2, open issues)
|
||||
uses: openai/codex-action@main
|
||||
uses: openai/codex-action@0b91f4a2703c23df3102c3f0967d3c6db34eedef # v1
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
@@ -342,7 +342,7 @@ jobs:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Comment on issue
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
|
||||
env:
|
||||
CODEX_OUTPUT: ${{ needs.select-final.outputs.codex_output }}
|
||||
with:
|
||||
|
||||
4
.github/workflows/issue-labeler.yml
vendored
4
.github/workflows/issue-labeler.yml
vendored
@@ -17,10 +17,10 @@ jobs:
|
||||
outputs:
|
||||
codex_output: ${{ steps.codex.outputs.final-message }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- id: codex
|
||||
uses: openai/codex-action@main
|
||||
uses: openai/codex-action@0b91f4a2703c23df3102c3f0967d3c6db34eedef # v1
|
||||
with:
|
||||
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
|
||||
allow-users: "*"
|
||||
|
||||
58
.github/workflows/rust-ci.yml
vendored
58
.github/workflows/rust-ci.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
codex: ${{ steps.detect.outputs.codex }}
|
||||
workflows: ${{ steps.detect.outputs.workflows }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Detect changed paths (no external action)
|
||||
@@ -66,8 +66,8 @@ jobs:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
components: rustfmt
|
||||
- name: cargo fmt
|
||||
@@ -82,8 +82,8 @@ jobs:
|
||||
run:
|
||||
working-directory: codex-rs
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2
|
||||
with:
|
||||
tool: cargo-shear
|
||||
@@ -97,14 +97,14 @@ jobs:
|
||||
needs: changed
|
||||
if: ${{ needs.changed.outputs.argument_comment_lint_package == 'true' || github.event_name == 'push' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
toolchain: nightly-2025-09-18
|
||||
components: llvm-tools-preview, rustc-dev, rust-src
|
||||
- name: Cache cargo-dylint tooling
|
||||
id: cargo_dylint_cache
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/cargo-dylint
|
||||
@@ -141,18 +141,18 @@ jobs:
|
||||
group: codex-runners
|
||||
labels: codex-windows-x64
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- name: Install Linux sandbox build dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
toolchain: nightly-2025-09-18
|
||||
components: llvm-tools-preview, rustc-dev, rust-src
|
||||
- uses: facebook/install-dotslash@v2
|
||||
- uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
- name: Run argument comment lint on codex-rs
|
||||
shell: bash
|
||||
run: ./tools/argument-comment-lint/run-prebuilt-linter.sh
|
||||
@@ -258,7 +258,7 @@ jobs:
|
||||
labels: codex-windows-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- name: Install Linux build dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
@@ -272,7 +272,7 @@ jobs:
|
||||
fi
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "${packages[@]}"
|
||||
fi
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
components: clippy
|
||||
@@ -301,7 +301,7 @@ jobs:
|
||||
# avoid caching the large target dir on the gnu-dev job.
|
||||
- name: Restore cargo home cache
|
||||
id: cache_cargo_home_restore
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
@@ -346,7 +346,7 @@ jobs:
|
||||
- name: Restore sccache cache (fallback)
|
||||
if: ${{ env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true' }}
|
||||
id: cache_sccache_restore
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: ${{ github.workspace }}/.sccache/
|
||||
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
||||
@@ -373,7 +373,7 @@ jobs:
|
||||
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
||||
name: Restore APT cache (musl)
|
||||
id: cache_apt_restore
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
/var/cache/apt
|
||||
@@ -486,7 +486,7 @@ jobs:
|
||||
|
||||
- name: Upload Cargo timings (clippy)
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: cargo-timings-rust-ci-clippy-${{ matrix.target }}-${{ matrix.profile }}
|
||||
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
||||
@@ -497,7 +497,7 @@ jobs:
|
||||
- name: Save cargo home cache
|
||||
if: always() && !cancelled() && steps.cache_cargo_home_restore.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
@@ -513,7 +513,7 @@ jobs:
|
||||
- name: Save sccache cache (fallback)
|
||||
if: always() && !cancelled() && env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: ${{ github.workspace }}/.sccache/
|
||||
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
||||
@@ -538,7 +538,7 @@ jobs:
|
||||
- name: Save APT cache (musl)
|
||||
if: always() && !cancelled() && (matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl') && steps.cache_apt_restore.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
/var/cache/apt
|
||||
@@ -598,9 +598,9 @@ jobs:
|
||||
labels: codex-windows-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- name: Set up Node.js for js_repl tests
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version-file: codex-rs/node-version.txt
|
||||
- name: Install Linux build dependencies
|
||||
@@ -616,9 +616,9 @@ jobs:
|
||||
# Some integration tests rely on DotSlash being installed.
|
||||
# See https://github.com/openai/codex/pull/7617.
|
||||
- name: Install DotSlash
|
||||
uses: facebook/install-dotslash@v2
|
||||
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
@@ -633,7 +633,7 @@ jobs:
|
||||
|
||||
- name: Restore cargo home cache
|
||||
id: cache_cargo_home_restore
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
@@ -673,7 +673,7 @@ jobs:
|
||||
- name: Restore sccache cache (fallback)
|
||||
if: ${{ env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true' }}
|
||||
id: cache_sccache_restore
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: ${{ github.workspace }}/.sccache/
|
||||
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
||||
@@ -715,7 +715,7 @@ jobs:
|
||||
|
||||
- name: Upload Cargo timings (nextest)
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: cargo-timings-rust-ci-nextest-${{ matrix.target }}-${{ matrix.profile }}
|
||||
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
||||
@@ -724,7 +724,7 @@ jobs:
|
||||
- name: Save cargo home cache
|
||||
if: always() && !cancelled() && steps.cache_cargo_home_restore.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
@@ -736,7 +736,7 @@ jobs:
|
||||
- name: Save sccache cache (fallback)
|
||||
if: always() && !cancelled() && env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: ${{ github.workspace }}/.sccache/
|
||||
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
||||
|
||||
@@ -53,9 +53,9 @@ jobs:
|
||||
labels: codex-windows-x64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
toolchain: nightly-2025-09-18
|
||||
targets: ${{ matrix.target }}
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
(cd "${RUNNER_TEMP}" && tar -czf "$GITHUB_WORKSPACE/$archive_path" argument-comment-lint)
|
||||
fi
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: argument-comment-lint-${{ matrix.target }}
|
||||
path: dist/argument-comment-lint/${{ matrix.target }}/*
|
||||
|
||||
4
.github/workflows/rust-release-prepare.yml
vendored
4
.github/workflows/rust-release-prepare.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
if: github.repository == 'openai/codex'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
curl --http1.1 --fail --show-error --location "${headers[@]}" "${url}" | jq '.' > codex-rs/core/models.json
|
||||
|
||||
- name: Open pull request (if changed)
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8
|
||||
with:
|
||||
commit-message: "Update models.json"
|
||||
title: "Update models.json"
|
||||
|
||||
18
.github/workflows/rust-release-windows.yml
vendored
18
.github/workflows/rust-release-windows.yml
vendored
@@ -67,7 +67,7 @@ jobs:
|
||||
labels: codex-windows-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- name: Print runner specs (Windows)
|
||||
shell: powershell
|
||||
run: |
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
Write-Host "Total RAM: $ramGiB GiB"
|
||||
Write-Host "Disk usage:"
|
||||
Get-PSDrive -PSProvider FileSystem | Format-Table -AutoSize Name, @{Name='Size(GB)';Expression={[math]::Round(($_.Used + $_.Free) / 1GB, 1)}}, @{Name='Free(GB)';Expression={[math]::Round($_.Free / 1GB, 1)}}
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
cargo build --target ${{ matrix.target }} --release --timings ${{ matrix.build_args }}
|
||||
|
||||
- name: Upload Cargo timings
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: cargo-timings-rust-release-windows-${{ matrix.target }}-${{ matrix.bundle }}
|
||||
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Upload Windows binaries
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: windows-binaries-${{ matrix.target }}-${{ matrix.bundle }}
|
||||
path: |
|
||||
@@ -147,16 +147,16 @@ jobs:
|
||||
labels: codex-windows-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Download prebuilt Windows primary binaries
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: windows-binaries-${{ matrix.target }}-primary
|
||||
path: codex-rs/target/${{ matrix.target }}/release
|
||||
|
||||
- name: Download prebuilt Windows helper binaries
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: windows-binaries-${{ matrix.target }}-helpers
|
||||
path: codex-rs/target/${{ matrix.target }}/release
|
||||
@@ -193,7 +193,7 @@ jobs:
|
||||
cp target/${{ matrix.target }}/release/codex-command-runner.exe "$dest/codex-command-runner-${{ matrix.target }}.exe"
|
||||
|
||||
- name: Install DotSlash
|
||||
uses: facebook/install-dotslash@v2
|
||||
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
- name: Compress artifacts
|
||||
shell: bash
|
||||
@@ -257,7 +257,7 @@ jobs:
|
||||
"${GITHUB_WORKSPACE}/.github/workflows/zstd" -T0 -19 "$dest/$base"
|
||||
done
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
path: |
|
||||
|
||||
8
.github/workflows/rust-release-zsh.yml
vendored
8
.github/workflows/rust-release-zsh.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
git \
|
||||
libncursesw5-dev
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Build, smoke-test, and stage zsh artifact
|
||||
shell: bash
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
"${GITHUB_WORKSPACE}/.github/scripts/build-zsh-release-artifact.sh" \
|
||||
"dist/zsh/${{ matrix.target }}/${{ matrix.archive_name }}"
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: codex-zsh-${{ matrix.target }}
|
||||
path: dist/zsh/${{ matrix.target }}/*
|
||||
@@ -81,7 +81,7 @@ jobs:
|
||||
brew install autoconf
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Build, smoke-test, and stage zsh artifact
|
||||
shell: bash
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
"${GITHUB_WORKSPACE}/.github/scripts/build-zsh-release-artifact.sh" \
|
||||
"dist/zsh/${{ matrix.target }}/${{ matrix.archive_name }}"
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: codex-zsh-${{ matrix.target }}
|
||||
path: dist/zsh/${{ matrix.target }}/*
|
||||
|
||||
32
.github/workflows/rust-release.yml
vendored
32
.github/workflows/rust-release.yml
vendored
@@ -19,8 +19,8 @@ jobs:
|
||||
tag-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: dtolnay/rust-toolchain@1.92
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- uses: dtolnay/rust-toolchain@c2b55edffaf41a251c410bb32bed22afefa800f1 # 1.92
|
||||
- name: Validate tag matches Cargo.toml version
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -79,7 +79,7 @@ jobs:
|
||||
target: aarch64-unknown-linux-gnu
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- name: Print runner specs (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
@@ -125,7 +125,7 @@ jobs:
|
||||
sudo apt-get update -y
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y libubsan1
|
||||
fi
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
@@ -235,7 +235,7 @@ jobs:
|
||||
cargo build --target ${{ matrix.target }} --release --timings --bin codex --bin codex-responses-api-proxy
|
||||
|
||||
- name: Upload Cargo timings
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: cargo-timings-rust-release-${{ matrix.target }}
|
||||
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
||||
@@ -374,7 +374,7 @@ jobs:
|
||||
zstd -T0 -19 --rm "$dest/$base"
|
||||
done
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
# Upload the per-binary .zst files as well as the new .tar.gz
|
||||
@@ -420,7 +420,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Generate release notes from tag commit message
|
||||
id: release_notes
|
||||
@@ -442,7 +442,7 @@ jobs:
|
||||
|
||||
echo "path=${notes_path}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
path: dist
|
||||
|
||||
@@ -492,12 +492,12 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v5
|
||||
uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node.js for npm packaging
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
@@ -505,7 +505,7 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
# stage_npm_packages.py requires DotSlash when staging releases.
|
||||
- uses: facebook/install-dotslash@v2
|
||||
- uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
- name: Stage npm packages
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
@@ -523,7 +523,7 @@ jobs:
|
||||
cp scripts/install/install.ps1 dist/install.ps1
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2
|
||||
with:
|
||||
name: ${{ steps.release_name.outputs.name }}
|
||||
tag_name: ${{ github.ref_name }}
|
||||
@@ -533,21 +533,21 @@ jobs:
|
||||
# (e.g. -alpha, -beta). Otherwise publish a normal release.
|
||||
prerelease: ${{ contains(steps.release_name.outputs.name, '-') }}
|
||||
|
||||
- uses: facebook/dotslash-publish-release@v2
|
||||
- uses: facebook/dotslash-publish-release@9c9ec027515c34db9282a09a25a9cab5880b2c52 # v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag: ${{ github.ref_name }}
|
||||
config: .github/dotslash-config.json
|
||||
|
||||
- uses: facebook/dotslash-publish-release@v2
|
||||
- uses: facebook/dotslash-publish-release@9c9ec027515c34db9282a09a25a9cab5880b2c52 # v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag: ${{ github.ref_name }}
|
||||
config: .github/dotslash-zsh-config.json
|
||||
|
||||
- uses: facebook/dotslash-publish-release@v2
|
||||
- uses: facebook/dotslash-publish-release@9c9ec027515c34db9282a09a25a9cab5880b2c52 # v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
@@ -582,7 +582,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version: 22
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
16
.github/workflows/rusty-v8-release.yml
vendored
16
.github/workflows/rusty-v8-release.yml
vendored
@@ -25,10 +25,10 @@ jobs:
|
||||
v8_version: ${{ steps.v8_version.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
@@ -75,13 +75,13 @@ jobs:
|
||||
target: aarch64-unknown-linux-musl
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazelbuild/setup-bazelisk@v3
|
||||
uses: bazelbuild/setup-bazelisk@6ecf4fd8b7d1f9721785f1dd656a689acf9add47 # v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
@@ -135,7 +135,7 @@ jobs:
|
||||
--output-dir "dist/${TARGET}"
|
||||
|
||||
- name: Upload staged musl artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: rusty-v8-${{ needs.metadata.outputs.v8_version }}-${{ matrix.target }}
|
||||
path: dist/${{ matrix.target }}/*
|
||||
@@ -174,12 +174,12 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
path: dist
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2
|
||||
with:
|
||||
tag_name: ${{ needs.metadata.outputs.release_tag }}
|
||||
name: ${{ needs.metadata.outputs.release_tag }}
|
||||
|
||||
8
.github/workflows/sdk.yml
vendored
8
.github/workflows/sdk.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Install Linux bwrap build dependencies
|
||||
shell: bash
|
||||
@@ -23,17 +23,17 @@ jobs:
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v5
|
||||
uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
|
||||
- uses: dtolnay/rust-toolchain@1.93.0
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
|
||||
- name: build codex
|
||||
run: cargo build --bin codex
|
||||
|
||||
12
.github/workflows/v8-canary.yml
vendored
12
.github/workflows/v8-canary.yml
vendored
@@ -38,10 +38,10 @@ jobs:
|
||||
v8_version: ${{ steps.v8_version.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
@@ -72,13 +72,13 @@ jobs:
|
||||
target: aarch64-unknown-linux-musl
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazelbuild/setup-bazelisk@v3
|
||||
uses: bazelbuild/setup-bazelisk@6ecf4fd8b7d1f9721785f1dd656a689acf9add47 # v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
@@ -126,7 +126,7 @@ jobs:
|
||||
--output-dir "dist/${TARGET}"
|
||||
|
||||
- name: Upload staged musl artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: v8-canary-${{ needs.metadata.outputs.v8_version }}-${{ matrix.target }}
|
||||
path: dist/${{ matrix.target }}/*
|
||||
|
||||
@@ -35,9 +35,9 @@ In the codex-rs folder where the rust code lives:
|
||||
- If a file exceeds roughly 800 LoC, add new functionality in a new module instead of extending
|
||||
the existing file unless there is a strong documented reason not to.
|
||||
- This rule applies especially to high-touch files that already attract unrelated changes, such
|
||||
as `codex-rs/tui/src/app.rs`, `codex-rs/tui/src/bottom_pane/chat_composer.rs`,
|
||||
`codex-rs/tui/src/bottom_pane/footer.rs`, `codex-rs/tui/src/chatwidget.rs`,
|
||||
`codex-rs/tui/src/bottom_pane/mod.rs`, and similarly central orchestration modules.
|
||||
as `codex-rs/tui_app_server/src/app.rs`, `codex-rs/tui_app_server/src/bottom_pane/chat_composer.rs`,
|
||||
`codex-rs/tui_app_server/src/bottom_pane/footer.rs`, `codex-rs/tui_app_server/src/chatwidget.rs`,
|
||||
`codex-rs/tui_app_server/src/bottom_pane/mod.rs`, and similarly central orchestration modules.
|
||||
- When extracting code from a large module, move the related tests and module/type docs toward
|
||||
the new implementation so the invariants stay close to the code that owns them.
|
||||
- When running Rust commands (e.g. `just fix` or `cargo test`) be patient with the command and never try to kill them using the PID. Rust lock can make the execution slow, this is expected.
|
||||
@@ -66,7 +66,7 @@ Likewise, when reviewing code, do not hesitate to push back on PRs that would un
|
||||
|
||||
## TUI style conventions
|
||||
|
||||
See `codex-rs/tui/styles.md`.
|
||||
See `codex-rs/tui_app_server/styles.md`.
|
||||
|
||||
## TUI code conventions
|
||||
|
||||
|
||||
97
codex-rs/Cargo.lock
generated
97
codex-rs/Cargo.lock
generated
@@ -1636,7 +1636,6 @@ dependencies = [
|
||||
"codex-stdio-to-uds",
|
||||
"codex-terminal-detection",
|
||||
"codex-tui",
|
||||
"codex-tui-app-server",
|
||||
"codex-utils-cargo-bin",
|
||||
"codex-utils-cli",
|
||||
"codex-windows-sandbox",
|
||||
@@ -2624,102 +2623,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "codex-tui"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arboard",
|
||||
"assert_matches",
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
"clap",
|
||||
"codex-ansi-escape",
|
||||
"codex-app-server-client",
|
||||
"codex-app-server-protocol",
|
||||
"codex-arg0",
|
||||
"codex-backend-client",
|
||||
"codex-chatgpt",
|
||||
"codex-cli",
|
||||
"codex-client",
|
||||
"codex-cloud-requirements",
|
||||
"codex-core",
|
||||
"codex-exec-server",
|
||||
"codex-features",
|
||||
"codex-feedback",
|
||||
"codex-file-search",
|
||||
"codex-git-utils",
|
||||
"codex-login",
|
||||
"codex-otel",
|
||||
"codex-protocol",
|
||||
"codex-shell-command",
|
||||
"codex-state",
|
||||
"codex-terminal-detection",
|
||||
"codex-tui-app-server",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-approval-presets",
|
||||
"codex-utils-cargo-bin",
|
||||
"codex-utils-cli",
|
||||
"codex-utils-elapsed",
|
||||
"codex-utils-fuzzy-match",
|
||||
"codex-utils-oss",
|
||||
"codex-utils-pty",
|
||||
"codex-utils-sandbox-summary",
|
||||
"codex-utils-sleep-inhibitor",
|
||||
"codex-utils-string",
|
||||
"codex-windows-sandbox",
|
||||
"color-eyre",
|
||||
"cpal",
|
||||
"crossterm",
|
||||
"derive_more 2.1.1",
|
||||
"diffy",
|
||||
"dirs",
|
||||
"dunce",
|
||||
"hound",
|
||||
"image",
|
||||
"insta",
|
||||
"itertools 0.14.0",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"pathdiff",
|
||||
"pretty_assertions",
|
||||
"pulldown-cmark",
|
||||
"rand 0.9.2",
|
||||
"ratatui",
|
||||
"ratatui-macros",
|
||||
"regex-lite",
|
||||
"reqwest",
|
||||
"rmcp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serial_test",
|
||||
"shlex",
|
||||
"strum 0.27.2",
|
||||
"strum_macros 0.28.0",
|
||||
"supports-color 3.0.2",
|
||||
"syntect",
|
||||
"tempfile",
|
||||
"textwrap 0.16.2",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
"tracing-subscriber",
|
||||
"two-face",
|
||||
"unicode-segmentation",
|
||||
"unicode-width 0.2.1",
|
||||
"url",
|
||||
"uuid",
|
||||
"vt100",
|
||||
"webbrowser",
|
||||
"which 8.0.0",
|
||||
"windows-sys 0.52.0",
|
||||
"winsplit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-tui-app-server"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arboard",
|
||||
|
||||
@@ -49,7 +49,6 @@ members = [
|
||||
"sandboxing",
|
||||
"stdio-to-uds",
|
||||
"otel",
|
||||
"tui",
|
||||
"tui_app_server",
|
||||
"tools",
|
||||
"v8-poc",
|
||||
@@ -86,7 +85,7 @@ members = [
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
version = "0.118.0-alpha.3"
|
||||
version = "0.0.0"
|
||||
# Track the edition for all workspace crates in one place. Individual
|
||||
# crates can still override this value, but keeping it here means new
|
||||
# crates created with `cargo new -w ...` automatically inherit the 2024
|
||||
@@ -150,8 +149,7 @@ codex-state = { path = "state" }
|
||||
codex-stdio-to-uds = { path = "stdio-to-uds" }
|
||||
codex-terminal-detection = { path = "terminal-detection" }
|
||||
codex-tools = { path = "tools" }
|
||||
codex-tui = { path = "tui" }
|
||||
codex-tui-app-server = { path = "tui_app_server" }
|
||||
codex-tui = { path = "tui_app_server" }
|
||||
codex-v8-poc = { path = "v8-poc" }
|
||||
codex-utils-absolute-path = { path = "utils/absolute-path" }
|
||||
codex-utils-approval-presets = { path = "utils/approval-presets" }
|
||||
|
||||
@@ -4,9 +4,8 @@ This module implements the websocket-backed app-server client transport.
|
||||
It owns the remote connection lifecycle, including the initialize/initialized
|
||||
handshake, JSON-RPC request/response routing, server-request resolution, and
|
||||
notification streaming. The rest of the crate uses the same `AppServerEvent`
|
||||
surface for both in-process and remote transports, so callers such as
|
||||
`tui_app_server` can switch between them without changing their higher-level
|
||||
session logic.
|
||||
surface for both in-process and remote transports, so callers such as the TUI
|
||||
can switch between them without changing their higher-level session logic.
|
||||
*/
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -88,7 +88,7 @@ use toml::Value as TomlValue;
|
||||
use tracing::Instrument;
|
||||
|
||||
const EXTERNAL_AUTH_REFRESH_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
const TUI_APP_SERVER_CLIENT_NAME: &str = "codex-tui";
|
||||
const TUI_CLIENT_NAME: &str = "codex-tui";
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ExternalAuthRefreshBridge {
|
||||
@@ -569,9 +569,9 @@ impl MessageProcessor {
|
||||
} = params.client_info;
|
||||
session.app_server_client_name = Some(name.clone());
|
||||
session.client_version = Some(version.clone());
|
||||
let originator = if name == TUI_APP_SERVER_CLIENT_NAME {
|
||||
// TODO: Remove this temporary workaround once app-server clients no longer
|
||||
// need to retain the legacy TUI `codex_cli_rs` originator behavior.
|
||||
let originator = if name == TUI_CLIENT_NAME {
|
||||
// TODO: Remove this temporary workaround once the TUI no longer
|
||||
// needs to retain the `codex_cli_rs` originator behavior.
|
||||
DEFAULT_ORIGINATOR.to_string()
|
||||
} else {
|
||||
name.clone()
|
||||
|
||||
@@ -41,7 +41,6 @@ codex-state = { workspace = true }
|
||||
codex-stdio-to-uds = { workspace = true }
|
||||
codex-terminal-detection = { workspace = true }
|
||||
codex-tui = { workspace = true }
|
||||
codex-tui-app-server = { workspace = true }
|
||||
libc = { workspace = true }
|
||||
owo-colors = { workspace = true }
|
||||
regex-lite = { workspace = true }
|
||||
|
||||
@@ -24,10 +24,10 @@ use codex_execpolicy::ExecPolicyCheckCommand;
|
||||
use codex_responses_api_proxy::Args as ResponsesApiProxyArgs;
|
||||
use codex_state::StateRuntime;
|
||||
use codex_state::state_db_path;
|
||||
use codex_tui::AppExitInfo;
|
||||
use codex_tui::Cli as TuiCli;
|
||||
use codex_tui::ExitReason;
|
||||
use codex_tui::update_action::UpdateAction;
|
||||
use codex_tui_app_server::AppExitInfo;
|
||||
use codex_tui_app_server::Cli as TuiCli;
|
||||
use codex_tui_app_server::ExitReason;
|
||||
use codex_tui_app_server::update_action::UpdateAction;
|
||||
use codex_utils_cli::CliConfigOverrides;
|
||||
use owo_colors::OwoColorize;
|
||||
use std::io::IsTerminal;
|
||||
@@ -525,7 +525,7 @@ struct FeatureToggles {
|
||||
|
||||
#[derive(Debug, Default, Parser, Clone)]
|
||||
struct InteractiveRemoteOptions {
|
||||
/// Connect the app-server-backed TUI to a remote app server websocket endpoint.
|
||||
/// Connect the TUI to a remote app server websocket endpoint.
|
||||
///
|
||||
/// Accepted forms: `ws://host:port` or `wss://host:port`.
|
||||
#[arg(long = "remote", value_name = "ADDR")]
|
||||
@@ -1226,7 +1226,6 @@ async fn run_interactive_tui(
|
||||
}
|
||||
}
|
||||
|
||||
let use_app_server_tui = codex_tui::should_use_app_server_tui(&interactive).await?;
|
||||
let normalized_remote = remote
|
||||
.as_deref()
|
||||
.map(codex_tui_app_server::normalize_remote_addr)
|
||||
@@ -1237,93 +1236,19 @@ async fn run_interactive_tui(
|
||||
"`--remote-auth-token-env` requires `--remote`.",
|
||||
));
|
||||
}
|
||||
if normalized_remote.is_some() && !use_app_server_tui {
|
||||
return Ok(AppExitInfo::fatal(
|
||||
"`--remote` requires the `tui_app_server` feature flag to be enabled.",
|
||||
));
|
||||
}
|
||||
if use_app_server_tui {
|
||||
let remote_auth_token = remote_auth_token_env
|
||||
.as_deref()
|
||||
.map(read_remote_auth_token_from_env_var)
|
||||
.transpose()
|
||||
.map_err(std::io::Error::other)?;
|
||||
codex_tui_app_server::run_main(
|
||||
into_app_server_tui_cli(interactive),
|
||||
arg0_paths,
|
||||
codex_core::config_loader::LoaderOverrides::default(),
|
||||
normalized_remote,
|
||||
remote_auth_token,
|
||||
)
|
||||
.await
|
||||
.map(into_legacy_app_exit_info)
|
||||
} else {
|
||||
codex_tui::run_main(
|
||||
interactive,
|
||||
arg0_paths,
|
||||
codex_core::config_loader::LoaderOverrides::default(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
fn into_app_server_tui_cli(cli: TuiCli) -> codex_tui_app_server::Cli {
|
||||
codex_tui_app_server::Cli {
|
||||
prompt: cli.prompt,
|
||||
images: cli.images,
|
||||
resume_picker: cli.resume_picker,
|
||||
resume_last: cli.resume_last,
|
||||
resume_session_id: cli.resume_session_id,
|
||||
resume_show_all: cli.resume_show_all,
|
||||
fork_picker: cli.fork_picker,
|
||||
fork_last: cli.fork_last,
|
||||
fork_session_id: cli.fork_session_id,
|
||||
fork_show_all: cli.fork_show_all,
|
||||
model: cli.model,
|
||||
oss: cli.oss,
|
||||
oss_provider: cli.oss_provider,
|
||||
config_profile: cli.config_profile,
|
||||
sandbox_mode: cli.sandbox_mode,
|
||||
approval_policy: cli.approval_policy,
|
||||
full_auto: cli.full_auto,
|
||||
dangerously_bypass_approvals_and_sandbox: cli.dangerously_bypass_approvals_and_sandbox,
|
||||
cwd: cli.cwd,
|
||||
web_search: cli.web_search,
|
||||
add_dir: cli.add_dir,
|
||||
no_alt_screen: cli.no_alt_screen,
|
||||
config_overrides: cli.config_overrides,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_legacy_update_action(
|
||||
action: codex_tui_app_server::update_action::UpdateAction,
|
||||
) -> UpdateAction {
|
||||
match action {
|
||||
codex_tui_app_server::update_action::UpdateAction::NpmGlobalLatest => {
|
||||
UpdateAction::NpmGlobalLatest
|
||||
}
|
||||
codex_tui_app_server::update_action::UpdateAction::BunGlobalLatest => {
|
||||
UpdateAction::BunGlobalLatest
|
||||
}
|
||||
codex_tui_app_server::update_action::UpdateAction::BrewUpgrade => UpdateAction::BrewUpgrade,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_legacy_exit_reason(reason: codex_tui_app_server::ExitReason) -> ExitReason {
|
||||
match reason {
|
||||
codex_tui_app_server::ExitReason::UserRequested => ExitReason::UserRequested,
|
||||
codex_tui_app_server::ExitReason::Fatal(message) => ExitReason::Fatal(message),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_legacy_app_exit_info(exit_info: codex_tui_app_server::AppExitInfo) -> AppExitInfo {
|
||||
AppExitInfo {
|
||||
token_usage: exit_info.token_usage,
|
||||
thread_id: exit_info.thread_id,
|
||||
thread_name: exit_info.thread_name,
|
||||
update_action: exit_info.update_action.map(into_legacy_update_action),
|
||||
exit_reason: into_legacy_exit_reason(exit_info.exit_reason),
|
||||
}
|
||||
let remote_auth_token = remote_auth_token_env
|
||||
.as_deref()
|
||||
.map(read_remote_auth_token_from_env_var)
|
||||
.transpose()
|
||||
.map_err(std::io::Error::other)?;
|
||||
codex_tui_app_server::run_main(
|
||||
interactive,
|
||||
arg0_paths,
|
||||
codex_core::config_loader::LoaderOverrides::default(),
|
||||
normalized_remote,
|
||||
remote_auth_token,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
fn confirm(prompt: &str) -> std::io::Result<bool> {
|
||||
|
||||
@@ -24,7 +24,7 @@ codex-client = { workspace = true }
|
||||
codex-core = { path = "../core" }
|
||||
codex-git-utils = { workspace = true }
|
||||
codex-login = { path = "../login" }
|
||||
codex-tui = { path = "../tui" }
|
||||
codex-tui = { workspace = true }
|
||||
codex-utils-cli = { workspace = true }
|
||||
crossterm = { workspace = true, features = ["event-stream"] }
|
||||
ratatui = { workspace = true }
|
||||
|
||||
@@ -930,7 +930,8 @@ pub async fn run_main(cli: Cli, _codex_linux_sandbox_exe: Option<PathBuf>) -> an
|
||||
if let Some(page) = app.new_task.as_mut() {
|
||||
if page.composer.flush_paste_burst_if_due() { needs_redraw = true; }
|
||||
if page.composer.is_in_paste_burst() {
|
||||
let _ = frame_tx.send(Instant::now() + codex_tui::ComposerInput::recommended_flush_delay());
|
||||
let _ = frame_tx
|
||||
.send(Instant::now() + codex_tui_app_server::ComposerInput::recommended_flush_delay());
|
||||
}
|
||||
}
|
||||
// Keep spinner pulsing only while loading.
|
||||
@@ -1491,7 +1492,9 @@ pub async fn run_main(cli: Cli, _codex_linux_sandbox_exe: Option<PathBuf>) -> an
|
||||
_ => {
|
||||
if page.submitting {
|
||||
// Ignore input while submitting
|
||||
} else if let codex_tui::ComposerAction::Submitted(text) = page.composer.input(key) {
|
||||
} else if let codex_tui_app_server::ComposerAction::Submitted(text) =
|
||||
page.composer.input(key)
|
||||
{
|
||||
// Submit only if we have an env id
|
||||
if let Some(env) = page.env_id.clone() {
|
||||
append_error_log(format!(
|
||||
@@ -1521,7 +1524,10 @@ pub async fn run_main(cli: Cli, _codex_linux_sandbox_exe: Option<PathBuf>) -> an
|
||||
needs_redraw = true;
|
||||
// If paste‑burst is active, schedule a micro‑flush frame.
|
||||
if page.composer.is_in_paste_burst() {
|
||||
let _ = frame_tx.send(Instant::now() + codex_tui::ComposerInput::recommended_flush_delay());
|
||||
let _ = frame_tx.send(
|
||||
Instant::now()
|
||||
+ codex_tui_app_server::ComposerInput::recommended_flush_delay(),
|
||||
);
|
||||
}
|
||||
// Always schedule an immediate redraw for key edits in the composer.
|
||||
let _ = frame_tx.send(Instant::now());
|
||||
@@ -2130,8 +2136,8 @@ mod tests {
|
||||
use codex_cloud_tasks_client::TaskId;
|
||||
use codex_cloud_tasks_client::TaskStatus;
|
||||
use codex_cloud_tasks_client::TaskSummary;
|
||||
use codex_tui::ComposerAction;
|
||||
use codex_tui::ComposerInput;
|
||||
use codex_tui_app_server::ComposerAction;
|
||||
use codex_tui_app_server::ComposerInput;
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
use crossterm::event::KeyModifiers;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use codex_tui::ComposerInput;
|
||||
use codex_tui_app_server::ComposerInput;
|
||||
|
||||
pub struct NewTaskPage {
|
||||
pub composer: ComposerInput,
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::app::AttemptView;
|
||||
use crate::util::format_relative_time_now;
|
||||
use codex_cloud_tasks_client::AttemptStatus;
|
||||
use codex_cloud_tasks_client::TaskStatus;
|
||||
use codex_tui::render_markdown_text;
|
||||
use codex_tui_app_server::render_markdown_text;
|
||||
|
||||
pub fn draw(frame: &mut Frame, app: &mut App) {
|
||||
let area = frame.area();
|
||||
|
||||
@@ -3,7 +3,7 @@ use codex_app_server_protocol::AppInfo;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
const TUI_APP_SERVER_CLIENT_NAME: &str = "codex-tui";
|
||||
const TUI_CLIENT_NAME: &str = "codex-tui";
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
@@ -96,7 +96,7 @@ pub(crate) fn filter_tool_suggest_discoverable_tools_for_client(
|
||||
discoverable_tools: Vec<DiscoverableTool>,
|
||||
app_server_client_name: Option<&str>,
|
||||
) -> Vec<DiscoverableTool> {
|
||||
if app_server_client_name != Some(TUI_APP_SERVER_CLIENT_NAME) {
|
||||
if app_server_client_name != Some(TUI_CLIENT_NAME) {
|
||||
return discoverable_tools;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,11 @@ fn to_abs_path(cwd: &Path, path: &Path) -> Option<AbsolutePathBuf> {
|
||||
AbsolutePathBuf::resolve_path_against_base(path, cwd).ok()
|
||||
}
|
||||
|
||||
fn write_permissions_for_paths(file_paths: &[AbsolutePathBuf]) -> Option<PermissionProfile> {
|
||||
fn write_permissions_for_paths(
|
||||
file_paths: &[AbsolutePathBuf],
|
||||
file_system_sandbox_policy: &codex_protocol::permissions::FileSystemSandboxPolicy,
|
||||
cwd: &Path,
|
||||
) -> Option<PermissionProfile> {
|
||||
let write_paths = file_paths
|
||||
.iter()
|
||||
.map(|path| {
|
||||
@@ -76,6 +80,7 @@ fn write_permissions_for_paths(file_paths: &[AbsolutePathBuf]) -> Option<Permiss
|
||||
.unwrap_or_else(|| path.clone())
|
||||
.into_path_buf()
|
||||
})
|
||||
.filter(|path| !file_system_sandbox_policy.can_write_path_with_cwd(path.as_path(), cwd))
|
||||
.collect::<BTreeSet<_>>()
|
||||
.into_iter()
|
||||
.map(AbsolutePathBuf::from_absolute_path)
|
||||
@@ -107,16 +112,16 @@ async fn effective_patch_permissions(
|
||||
session.granted_session_permissions().await.as_ref(),
|
||||
session.granted_turn_permissions().await.as_ref(),
|
||||
);
|
||||
let effective_additional_permissions = apply_granted_turn_permissions(
|
||||
session,
|
||||
crate::sandboxing::SandboxPermissions::UseDefault,
|
||||
write_permissions_for_paths(&file_paths),
|
||||
)
|
||||
.await;
|
||||
let file_system_sandbox_policy = effective_file_system_sandbox_policy(
|
||||
&turn.file_system_sandbox_policy,
|
||||
granted_permissions.as_ref(),
|
||||
);
|
||||
let effective_additional_permissions = apply_granted_turn_permissions(
|
||||
session,
|
||||
crate::sandboxing::SandboxPermissions::UseDefault,
|
||||
write_permissions_for_paths(&file_paths, &file_system_sandbox_policy, turn.cwd.as_path()),
|
||||
)
|
||||
.await;
|
||||
|
||||
(
|
||||
file_paths,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use super::*;
|
||||
use codex_apply_patch::MaybeApplyPatchVerified;
|
||||
use codex_protocol::permissions::FileSystemSandboxPolicy;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tempfile::TempDir;
|
||||
|
||||
@@ -26,3 +28,53 @@ fn approval_keys_include_move_destination() {
|
||||
let keys = file_paths_for_action(&action);
|
||||
assert_eq!(keys.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_permissions_for_paths_skip_dirs_already_writable_under_workspace_root() {
|
||||
let tmp = TempDir::new().expect("tmp");
|
||||
let cwd = tmp.path();
|
||||
let nested = cwd.join("nested");
|
||||
std::fs::create_dir_all(&nested).expect("create nested dir");
|
||||
let file_path = AbsolutePathBuf::try_from(nested.join("file.txt"))
|
||||
.expect("nested file path should be absolute");
|
||||
let sandbox_policy = FileSystemSandboxPolicy::from(&SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
read_only_access: Default::default(),
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: false,
|
||||
});
|
||||
|
||||
let permissions = write_permissions_for_paths(&[file_path], &sandbox_policy, cwd);
|
||||
|
||||
assert_eq!(permissions, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_permissions_for_paths_keep_dirs_outside_workspace_root() {
|
||||
let tmp = TempDir::new().expect("tmp");
|
||||
let cwd = tmp.path().join("workspace");
|
||||
let outside = tmp.path().join("outside");
|
||||
std::fs::create_dir_all(&cwd).expect("create cwd");
|
||||
std::fs::create_dir_all(&outside).expect("create outside dir");
|
||||
let file_path = AbsolutePathBuf::try_from(outside.join("file.txt"))
|
||||
.expect("outside file path should be absolute");
|
||||
let sandbox_policy = FileSystemSandboxPolicy::from(&SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
read_only_access: Default::default(),
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
});
|
||||
|
||||
let permissions = write_permissions_for_paths(&[file_path], &sandbox_policy, &cwd);
|
||||
let expected_outside = AbsolutePathBuf::from_absolute_path(dunce::simplified(
|
||||
&outside.canonicalize().expect("canonicalize outside dir"),
|
||||
))
|
||||
.expect("outside dir should be absolute");
|
||||
|
||||
assert_eq!(
|
||||
permissions.and_then(|profile| profile.file_system.and_then(|fs| fs.write)),
|
||||
Some(vec![expected_outside])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ pub enum Feature {
|
||||
VoiceTranscription,
|
||||
/// Enable experimental realtime voice conversation mode in the TUI.
|
||||
RealtimeConversation,
|
||||
/// Route interactive startup to the app-server-backed TUI implementation.
|
||||
/// Removed compatibility flag. The TUI now always uses the app-server implementation.
|
||||
TuiAppServer,
|
||||
/// Prevent idle system sleep while a turn is actively running.
|
||||
PreventIdleSleep,
|
||||
@@ -371,10 +371,16 @@ impl Features {
|
||||
Feature::WebSearchCached,
|
||||
);
|
||||
}
|
||||
"tui_app_server" => {
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match feature_for_key(k) {
|
||||
Some(feat) => {
|
||||
if matches!(feat, Feature::TuiAppServer) {
|
||||
continue;
|
||||
}
|
||||
if k != feat.key() {
|
||||
self.record_legacy_usage(k.as_str(), feat);
|
||||
}
|
||||
@@ -822,7 +828,7 @@ pub const FEATURES: &[FeatureSpec] = &[
|
||||
FeatureSpec {
|
||||
id: Feature::TuiAppServer,
|
||||
key: "tui_app_server",
|
||||
stage: Stage::Stable,
|
||||
stage: Stage::Removed,
|
||||
default_enabled: true,
|
||||
},
|
||||
FeatureSpec {
|
||||
|
||||
@@ -340,6 +340,13 @@ mod tests {
|
||||
args.iter().map(ToString::to_string).collect()
|
||||
}
|
||||
|
||||
fn assert_unsafe_parsed_command(words: &[&str]) {
|
||||
assert!(
|
||||
!is_safe_powershell_command(&vec_str(words)),
|
||||
"expected parsed command {words:?} to require approval",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recognizes_safe_powershell_wrappers() {
|
||||
assert!(is_safe_command_windows(&vec_str(&[
|
||||
@@ -441,136 +448,69 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn rejects_git_global_override_options() {
|
||||
let Some(pwsh) = try_find_pwsh_executable_blocking() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let pwsh: String = pwsh.as_path().to_str().unwrap().into();
|
||||
for script in [
|
||||
"git -c core.pager=cat show HEAD:foo.rs",
|
||||
"git --config-env core.pager=PAGER show HEAD:foo.rs",
|
||||
"git --config-env=core.pager=PAGER show HEAD:foo.rs",
|
||||
"git --git-dir .evil-git diff HEAD~1..HEAD",
|
||||
"git --git-dir=.evil-git diff HEAD~1..HEAD",
|
||||
"git --work-tree . status",
|
||||
"git --work-tree=. status",
|
||||
"git --exec-path .git/helpers show HEAD:foo.rs",
|
||||
"git --exec-path=.git/helpers show HEAD:foo.rs",
|
||||
"git --namespace attacker show HEAD:foo.rs",
|
||||
"git --namespace=attacker show HEAD:foo.rs",
|
||||
"git --super-prefix attacker/ show HEAD:foo.rs",
|
||||
"git --super-prefix=attacker/ show HEAD:foo.rs",
|
||||
for words in [
|
||||
&["git", "-c", "core.pager=cat", "show", "HEAD:foo.rs"][..],
|
||||
&[
|
||||
"git",
|
||||
"--config-env",
|
||||
"core.pager=PAGER",
|
||||
"show",
|
||||
"HEAD:foo.rs",
|
||||
][..],
|
||||
&[
|
||||
"git",
|
||||
"--config-env=core.pager=PAGER",
|
||||
"show",
|
||||
"HEAD:foo.rs",
|
||||
][..],
|
||||
&["git", "--git-dir", ".evil-git", "diff", "HEAD~1..HEAD"][..],
|
||||
&["git", "--git-dir=.evil-git", "diff", "HEAD~1..HEAD"][..],
|
||||
&["git", "--work-tree", ".", "status"][..],
|
||||
&["git", "--work-tree=.", "status"][..],
|
||||
&["git", "--exec-path", ".git/helpers", "show", "HEAD:foo.rs"][..],
|
||||
&["git", "--exec-path=.git/helpers", "show", "HEAD:foo.rs"][..],
|
||||
&["git", "--namespace", "attacker", "show", "HEAD:foo.rs"][..],
|
||||
&["git", "--namespace=attacker", "show", "HEAD:foo.rs"][..],
|
||||
&["git", "--super-prefix", "attacker/", "show", "HEAD:foo.rs"][..],
|
||||
&["git", "--super-prefix=attacker/", "show", "HEAD:foo.rs"][..],
|
||||
] {
|
||||
assert!(
|
||||
!is_safe_command_windows(&[
|
||||
pwsh.clone(),
|
||||
"-NoLogo".to_string(),
|
||||
"-NoProfile".to_string(),
|
||||
"-Command".to_string(),
|
||||
script.to_string(),
|
||||
]),
|
||||
"expected {script:?} to require approval due to unsafe git global option",
|
||||
);
|
||||
assert_unsafe_parsed_command(words);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_powershell_commands_with_side_effects() {
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-NoLogo",
|
||||
"-Command",
|
||||
"Remove-Item foo.txt",
|
||||
])));
|
||||
fn rejects_parsed_powershell_commands_with_side_effects() {
|
||||
for words in [
|
||||
&["Remove-Item", "foo.txt"][..],
|
||||
&["rg", "--pre", "cat"][..],
|
||||
&["Set-Content", "foo.txt", "hello"][..],
|
||||
&["Out-File", "y"][..],
|
||||
&["Write-Output", "(Set-Content", "foo6.txt", "abc)"][..],
|
||||
&["Write-Host", "(Remove-Item", "foo.txt)"][..],
|
||||
&["Get-Content", "(New-Item", "bar.txt)"][..],
|
||||
] {
|
||||
assert_unsafe_parsed_command(words);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-NoProfile",
|
||||
"-Command",
|
||||
"rg --pre cat",
|
||||
])));
|
||||
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"Set-Content foo.txt 'hello'",
|
||||
])));
|
||||
|
||||
// Redirections are blocked
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
#[test]
|
||||
fn rejects_parser_only_powershell_side_effect_patterns() {
|
||||
for script in [
|
||||
"echo hi > out.txt",
|
||||
])));
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"Get-Content x | Out-File y",
|
||||
])));
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"Write-Output foo 2> err.txt",
|
||||
])));
|
||||
|
||||
// Call operator is blocked
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"& Remove-Item foo",
|
||||
])));
|
||||
|
||||
// Chained safe + unsafe must fail
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"Get-ChildItem; Remove-Item foo",
|
||||
])));
|
||||
// Nested unsafe cmdlet inside safe command must fail
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"Write-Output (Set-Content foo6.txt 'abc')",
|
||||
])));
|
||||
// Additional nested unsafe cmdlet examples must fail
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"Write-Host (Remove-Item foo.txt)",
|
||||
])));
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"Get-Content (New-Item bar.txt)",
|
||||
])));
|
||||
|
||||
// Unsafe @ expansion.
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"ls @(calc.exe)"
|
||||
])));
|
||||
|
||||
// Unsupported constructs that the AST parser refuses (no fallback to manual splitting).
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"ls && pwd"
|
||||
])));
|
||||
|
||||
// Sub-expressions are rejected even if they contain otherwise safe commands.
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"Write-Output $(Get-Content foo)"
|
||||
])));
|
||||
|
||||
// Empty words from the parser (e.g. '') are rejected.
|
||||
assert!(!is_safe_command_windows(&vec_str(&[
|
||||
"powershell.exe",
|
||||
"-Command",
|
||||
"''"
|
||||
])));
|
||||
"ls @(calc.exe)",
|
||||
"ls && pwd",
|
||||
"Write-Output $(Get-Content foo)",
|
||||
"''",
|
||||
] {
|
||||
assert!(
|
||||
!is_safe_command_windows(&vec_str(&["powershell.exe", "-Command", script,])),
|
||||
"expected {script:?} to require approval",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
load("//:defs.bzl", "codex_rust_crate")
|
||||
|
||||
codex_rust_crate(
|
||||
name = "tui",
|
||||
crate_name = "codex_tui",
|
||||
compile_data = glob(
|
||||
include = ["**"],
|
||||
exclude = [
|
||||
"**/* *",
|
||||
"BUILD.bazel",
|
||||
"Cargo.toml",
|
||||
],
|
||||
allow_empty = True,
|
||||
),
|
||||
test_data_extra = glob(["src/**/snapshots/**"]) + ["//codex-rs/core:model_availability_nux_fixtures"],
|
||||
integration_compile_data_extra = ["src/test_backend.rs"],
|
||||
extra_binaries = [
|
||||
"//codex-rs/cli:codex",
|
||||
],
|
||||
)
|
||||
@@ -1,150 +0,0 @@
|
||||
[package]
|
||||
name = "codex-tui"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "codex-tui"
|
||||
path = "src/main.rs"
|
||||
|
||||
[lib]
|
||||
name = "codex_tui"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["voice-input"]
|
||||
# Enable vt100-based tests (emulator) when running with `--features vt100-tests`.
|
||||
vt100-tests = []
|
||||
# Gate verbose debug logging inside the TUI implementation.
|
||||
debug-logs = []
|
||||
voice-input = ["dep:cpal", "dep:hound"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
chrono = { workspace = true, features = ["serde"] }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
codex-ansi-escape = { workspace = true }
|
||||
codex-app-server-client = { workspace = true }
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-arg0 = { workspace = true }
|
||||
codex-backend-client = { workspace = true }
|
||||
codex-chatgpt = { workspace = true }
|
||||
codex-client = { workspace = true }
|
||||
codex-cloud-requirements = { workspace = true }
|
||||
codex-core = { workspace = true }
|
||||
codex-exec-server = { workspace = true }
|
||||
codex-features = { workspace = true }
|
||||
codex-feedback = { workspace = true }
|
||||
codex-file-search = { workspace = true }
|
||||
codex-git-utils = { workspace = true }
|
||||
codex-login = { workspace = true }
|
||||
codex-otel = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
codex-shell-command = { workspace = true }
|
||||
codex-state = { workspace = true }
|
||||
codex-terminal-detection = { workspace = true }
|
||||
codex-tui-app-server = { workspace = true }
|
||||
codex-utils-approval-presets = { workspace = true }
|
||||
codex-utils-absolute-path = { workspace = true }
|
||||
codex-utils-cli = { workspace = true }
|
||||
codex-utils-elapsed = { workspace = true }
|
||||
codex-utils-fuzzy-match = { workspace = true }
|
||||
codex-utils-oss = { workspace = true }
|
||||
codex-utils-sandbox-summary = { workspace = true }
|
||||
codex-utils-sleep-inhibitor = { workspace = true }
|
||||
codex-utils-string = { workspace = true }
|
||||
color-eyre = { workspace = true }
|
||||
crossterm = { workspace = true, features = ["bracketed-paste", "event-stream"] }
|
||||
derive_more = { workspace = true, features = ["is_variant"] }
|
||||
diffy = { workspace = true }
|
||||
dirs = { workspace = true }
|
||||
dunce = { workspace = true }
|
||||
image = { workspace = true, features = ["jpeg", "png", "gif", "webp"] }
|
||||
itertools = { workspace = true }
|
||||
lazy_static = { workspace = true }
|
||||
pathdiff = { workspace = true }
|
||||
pulldown-cmark = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
ratatui = { workspace = true, features = [
|
||||
"scrolling-regions",
|
||||
"unstable-backend-writer",
|
||||
"unstable-rendered-line-info",
|
||||
"unstable-widget-ref",
|
||||
] }
|
||||
ratatui-macros = { workspace = true }
|
||||
regex-lite = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json", "multipart"] }
|
||||
rmcp = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true, features = ["preserve_order"] }
|
||||
shlex = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
strum_macros = { workspace = true }
|
||||
supports-color = { workspace = true }
|
||||
tempfile = { workspace = true }
|
||||
textwrap = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = [
|
||||
"io-std",
|
||||
"macros",
|
||||
"process",
|
||||
"rt-multi-thread",
|
||||
"signal",
|
||||
"test-util",
|
||||
"time",
|
||||
] }
|
||||
tokio-stream = { workspace = true, features = ["sync"] }
|
||||
toml = { workspace = true }
|
||||
tracing = { workspace = true, features = ["log"] }
|
||||
tracing-appender = { workspace = true }
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"] }
|
||||
syntect = "5"
|
||||
two-face = { version = "0.5", default-features = false, features = ["syntect-default-onig"] }
|
||||
unicode-segmentation = { workspace = true }
|
||||
unicode-width = { workspace = true }
|
||||
url = { workspace = true }
|
||||
webbrowser = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
|
||||
codex-windows-sandbox = { workspace = true }
|
||||
tokio-util = { workspace = true, features = ["time"] }
|
||||
|
||||
[target.'cfg(not(target_os = "linux"))'.dependencies]
|
||||
cpal = { version = "0.15", optional = true }
|
||||
hound = { version = "3.5", optional = true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = { workspace = true }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
which = { workspace = true }
|
||||
windows-sys = { version = "0.52", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_System_Console",
|
||||
] }
|
||||
winsplit = "0.1"
|
||||
|
||||
# Clipboard support via `arboard` is not available on Android/Termux.
|
||||
# Only include it for non-Android targets so the crate builds on Android.
|
||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||
arboard = { workspace = true }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
codex-cli = { workspace = true }
|
||||
codex-core = { workspace = true }
|
||||
codex-utils-cargo-bin = { workspace = true }
|
||||
codex-utils-pty = { workspace = true }
|
||||
assert_matches = { workspace = true }
|
||||
chrono = { workspace = true, features = ["serde"] }
|
||||
insta = { workspace = true }
|
||||
pretty_assertions = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serial_test = { workspace = true }
|
||||
vt100 = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓▒▓▒██▒▒██▒
|
||||
▒▒█▓█▒█▓█▒▒░░▒▒ ▒ █▒
|
||||
█░█░███ ▒░ ░ █░ ░▒░░░█
|
||||
▓█▒▒████▒ ▓█░▓░█
|
||||
▒▒▓▓█▒░▒░▒▒ ▓░▒▒█
|
||||
░█ █░ ░█▓▓░░█ █▓▒░░█
|
||||
█▒ ▓█ █▒░█▓ ░▒ ░▓░
|
||||
░░▒░░ █▓▓░▓░█ ░░
|
||||
░▒░█░ ▓░░▒▒░ ▓░██████▒██ ▒ ░
|
||||
▒░▓█ ▒▓█░ ▓█ ░ ░▒▒▒▓▓███░▓█▓█░
|
||||
▒▒▒ ▒ ▒▒█▓▓░ ░▒████ ▒█ ▓█▓▒▓
|
||||
█▒█ █ ░ ██▓█▒░
|
||||
▒▒█░▒█▒ ▒▒▒█░▒█
|
||||
▒██▒▒ ██▓▓▒▓▓▓▒██▒█░█
|
||||
░█ █░░░▒▒▒█▒▓██
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒████▒██▒
|
||||
██░███▒░▓▒██
|
||||
▒▒█░░▓░░▓░█▒██
|
||||
░▒▒▓▒░▓▒▓▒███▒▒█
|
||||
▓ ▓░░ ░▒ ██▓▒▓░▓
|
||||
░░ █░█░▓▓▒ ░▒ ░
|
||||
▒ ░█ █░░░░█ ░▓█
|
||||
░░▒█▓█░░▓▒░▓▒░░
|
||||
░▒ ▒▒░▓░░█▒█▓░░
|
||||
░ █░▒█░▒▓▒█▒▒▒░█░
|
||||
█ ░░░░░ ▒█ ▒░░
|
||||
▒░██▒██ ▒░ █▓▓
|
||||
░█ ░░░░██▓█▓░▓░
|
||||
▓░██▓░█▓▒ ▓▓█
|
||||
██ ▒█▒▒█▓█
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
███████▒
|
||||
▓ ▓░░░▒▒█
|
||||
▓ ▒▒░░▓▒█▓▒█
|
||||
░▒▒░░▒▓█▒▒▓▓
|
||||
▒ ▓▓▒░█▒█▓▒░░█
|
||||
░█░░░█▒▓▓░▒▓░░
|
||||
██ █░░░░░░▒░▒▒
|
||||
░ ░░▓░░▒▓ ░ ░
|
||||
▓ █░▓░░█▓█░▒░
|
||||
██ ▒░▓▒█ ▓░▒░▒
|
||||
█░▓ ░░░░▒▓░▒▒░
|
||||
▒▒▓▓░▒█▓██▓░░
|
||||
▒ █░▒▒▒▒░▓
|
||||
▒█ █░░█▒▓█░
|
||||
▒▒ ███▒█░
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
█████▓
|
||||
█▒░▒▓░█▒
|
||||
░▓▒██
|
||||
▓█░░░▒▒ ░
|
||||
░ █░░░░▓▓░
|
||||
░█▓▓█▒ ▒░
|
||||
░ ░▓▒░░▒
|
||||
░ ▓█▒░░
|
||||
██ ░▓░░█░░
|
||||
░ ▓░█▓█▒
|
||||
░▓ ░ ▒██▓
|
||||
█ █░ ▒█░
|
||||
▓ ██░██▒░
|
||||
█▒▓ █░▒░░
|
||||
▒ █░▒▓▓
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▓████
|
||||
░▒▒░░
|
||||
░░▒░
|
||||
░██░▒
|
||||
█ ░░
|
||||
▓▓░░
|
||||
█ ░░
|
||||
█ ░
|
||||
▓█ ▒░▓
|
||||
░ █▒░
|
||||
█░▓▓ ░░
|
||||
░▒▒▒░
|
||||
░██░▒
|
||||
█▒▒░▒
|
||||
█ ▓ ▒
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
████▓
|
||||
█▓▒▒▓▒
|
||||
░▒░░▓ ░
|
||||
░░▓░ ▒░█
|
||||
░░░▒ ░
|
||||
░█░░ █░
|
||||
░░░░ ▓ █
|
||||
░░▒░░ ▒
|
||||
░░░░
|
||||
▒▓▓ ▓▓
|
||||
▒░ █▓█░
|
||||
░█░░▒▒▒░
|
||||
▓ ░▒▒▒░
|
||||
░▒▓█▒▒▓
|
||||
▒█ █▒▓
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
█████░▒
|
||||
░█▒░░▒▓██
|
||||
▓▓░█▒▒░ █░
|
||||
░▓░ ▓▓█▓▒▒░
|
||||
░░▒ ▒▒░░▓ ▒░
|
||||
▒░░▓░░▓▓░
|
||||
░░ ░░░░░░█░
|
||||
░░▓░░█░░░ █▓░
|
||||
░░████░░░▒▓▓░
|
||||
░▒░▓▓░▒░█▓ ▓░
|
||||
░▓░░░░▒░ ░ ▓
|
||||
░██▓▒░░▒▓ ▒
|
||||
█░▒█ ▓▓▓░ ▓░
|
||||
░▒░░▒▒▓█▒▓
|
||||
▒▒█▒▒▒▒▓
|
||||
░░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▒█ ███░▒
|
||||
▓▒░░█░░▒░▒▒
|
||||
░▓▓ ▒▓▒▒░░ █▒
|
||||
▓▓▓ ▓█▒▒░▒░░██░
|
||||
░░▓▒▓██▒░░█▓░░▒
|
||||
░░░█░█ ░▒▒ ░ ░▓░
|
||||
▒▒░ ▓░█░░░░▓█ █ ░
|
||||
░▓▓ ░░░░▓░░░ ▓ ░░
|
||||
▒▒░░░█░▓▒░░ ██ ▓
|
||||
█ ▒▒█▒▒▒█░▓▒░ █▒░
|
||||
░░░█ ▓█▒░▓ ▓▓░░░
|
||||
░░█ ░░ ░▓▓█ ▓
|
||||
▒░█ ░ ▓█▓▒█░
|
||||
▒░░ ▒█░▓▓█▒░
|
||||
█▓▓▒▒▓▒▒▓█
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
█▒███▓▓░█▒
|
||||
▒▓██░░░█▒█░█ ▒█
|
||||
██▒▓▒▒▒░██ ░░░▒ ▒
|
||||
▓░▓▒▓░ ▒░ █░▓▒░░░▒▒
|
||||
░▓▒ ░ ░ ▓▒▒▒▓▓ █
|
||||
░▒██▓░ █▓▓░ ▓█▒▓░▓▓
|
||||
█ ▓▓░ █▓▓░▒ █ ░░▓▒░
|
||||
▓ ▒░ ▓▓░░▓░█░░▒▓█
|
||||
█▓█▓▒▒▒█░▒▒░▒▒▓▒░░░ ░
|
||||
░ ▒▓▒▒░▓█▒▓░░▒ ▒███▒
|
||||
▒▒▒▓ ████▒▒░█▓▓▒ ▒█
|
||||
▒░░▒█ ░▓░░░ ▓
|
||||
▒▒▒ █▒▒ ███▓▒▒▓
|
||||
█ ░██▒▒█░▒▓█▓░█
|
||||
░█▓▓▒██░█▒██
|
||||
░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▒▒█▒▒█▓░█▒
|
||||
▒█ ▒▓███░▒▒█ █▓▓▒
|
||||
▒▓▓░█ █▒ █ ▓▒ █▓▓▒ █
|
||||
█░░█▓█▒ █ █▒░▒▓▒░▒▓▒▒▒█
|
||||
▒▒▓▓ ▓░ ▒ █▒▒▓░▓░▒▒▓▒▒▒
|
||||
▓▒░ ██░▓▒▒▒▓███░█▓▓▒▓░▓░
|
||||
░░▒▓▓ █▓█▓░ ▒▓ █░▒░▒█
|
||||
▒▓░░ ▒▒ ░░▓▒ ░▓░
|
||||
▒ █▒▒▒▓▒▓█░░█░█▓▒█ ░█░░
|
||||
▒▒▒░█▒█ ░░▓▒▒▒▒░░░▒▓░░▒ █
|
||||
░▓░▒░ █████░ ▒▒▒▓░▓█▓░▓░
|
||||
▒▒ █▒█ ░░█ ▓█▒█
|
||||
▒▒██▒▒▓ ▒█▒▒▓▒█░
|
||||
█░▓████▒▒▒▒██▒▓▒██
|
||||
░░▒▓▒▒█▓█ ▓█
|
||||
░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▒▒▒█░█▒▒░▓▒
|
||||
▒█░░░▒▓▒▒▒▒█▒█░███
|
||||
██▓▓▓ ░██░ ░█▓█░█▓▒
|
||||
▓▓░██▒░ ▒▒▒██▒░██
|
||||
░░▓░▓░ █░▒ ▓ ░▒ ░▒█
|
||||
░▒▓██ ▒░█░▓ ▓▓ █▓█░
|
||||
▒▒░░█ ▓█▒▓░██░ ▓▓▓█░
|
||||
░░░░ ░▓ ▒░ █ ░ ░░░
|
||||
░█░▒█▒▓▓▒▒▒░░░░██▓█░▓ ▒ ░░
|
||||
▒▓▓█░▒█▓▒██▒█░█ ▒▒ ▓▒▒▒█▓▓░▒
|
||||
█▒ ▓█░ ██ ▒▒▒▓░▓▓ ▓▓█
|
||||
▒▒▒█▒▒ ░▓▓▒▓▓█
|
||||
█ ▒▒░░██ █▓▒▓▓░▓░
|
||||
█ ▓░█▓░█▒▒▒▓▓█ ▓█░█
|
||||
░▓▒▓▓█▒█▓▒█▓▒
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓▒▓▒█▒▒▒██▒
|
||||
▒██▓█▓█░░░▒░░▒▒█░██▒
|
||||
█░█░▒██░█░░ ░ █▒█▓░░▓░█
|
||||
▒░▓▒▓████▒ ▓█▒░▓░█
|
||||
█▒ ▓█▒░▒▒▒▒▒ ▒█░▒░█
|
||||
█▓█ ░ ░█▒█▓▒█ ▒▒░█░
|
||||
█░██░ ▒▓░▓░▒░█ ▓ ░ ░
|
||||
░ ▒░ █░█░░▓█ ░█▓▓░
|
||||
█ ▒░ ▓░▒▒▒░ ▓░█████████░▒░░█
|
||||
▒▒█░ ▓░░█ ▓█ ░▒▒▒▒▒▒▓▓▒▒░█▓ ░
|
||||
▒▒▒ █ █▒▓▓░█ ░ ███████ ░██░░
|
||||
█▒▒▓▓█ ░ ██▓▓██
|
||||
▓▒▒▒░██ █▒▒█ ▒░
|
||||
░░▒▓▒▒ ██▓▓▒▓▓▓▒█░▒░░█
|
||||
░████░░▒▒▒▒░▓▓█
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▒█▒░░▒█▒█▒▒
|
||||
█▓▒ ▓█▒█▒▒▒░░▒▒█▒██
|
||||
██ ▒██ ░█ ░ ▒ ▒██░█▒
|
||||
▒░ ▒█░█ ▒██░▒▓█▒▒
|
||||
▒░ █░█ ▒▓ ▒░░▒█▒░░▒
|
||||
▓░█░█ ███▓░ ▓ █▒░░▒
|
||||
▓░▓█░ ██ ▓██▒ █▒░▓
|
||||
░▒▒▓░ ▓▓░ █ ░░ ░
|
||||
░▓░░▓█▒▓▒▒▒▒▒▒▒██▓▒▒▒▒█ ▓ ░▒
|
||||
█░▒░▒ ▓░░▒▒▒▒░▒ █▒▒ ░▒▒ █▓ ░░
|
||||
▒█▒▒█ █ ▒█▒░░█░ ▓▒
|
||||
█ ▒█▓█ ▒▓█▓░▓
|
||||
▒▒▒██░▒ █▓█░▓██
|
||||
▒█▓▓ ░█▒▓▓█▓ ░ ░█▓██
|
||||
░██░▒ ▒▒▒▒▒░█
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▒█▒█▒▒█▒██▒▒
|
||||
███░░▒▒█░▒░█▓▒░▓██▒
|
||||
▓█▒▒██▒ ░ ░▒░██▒░██
|
||||
██░▓ █ ▒█▓██▓██
|
||||
▓█▓█░ █░▓▒▒ ▒▒▒▒█
|
||||
▓ ▓░ ███▒▓▓ ▒▒▒█
|
||||
░█░░ ▒ ▓░█▓█ ▒▓▒
|
||||
░▒ ▒▓ ░█ ░ ░
|
||||
░ ░ ██▓▓▓▓▓███ ▒░█ ░█ ▓▓ ░
|
||||
░ ░▒ ░▒ ▒█░ ▒ ░█░█ ▓ ▓▓
|
||||
▓ ▓ ░░ █░ ██▒█▓ ▓░ █
|
||||
██ ▓▓▒ ▒█ ▓
|
||||
█▒ ▒▓▒ ▒▓▓██ █░
|
||||
█▒▒ █ ██▓░░▓▓▒█ ▓░
|
||||
███▓█▒▒▒▒█▒▓██░
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒██▒█▒▒█▒██▒
|
||||
▒█▓█░▓▒▓░▓▒░░▓░█▓██▒
|
||||
█▓█▓░▒██░ ░ █▒███▒▒██
|
||||
▓█░██ ██░░░▒█▒
|
||||
▒░░▓█ █▒▓░▒░▓▓▓█░
|
||||
▒░█▓░ █░▓░▓▒▓░ ▒░▒▒░
|
||||
░██▒▓ ░█░▒█▓█ ░░▓░
|
||||
░░▒░░ ░▒░░▒▒ ░▒░ ░
|
||||
░░█ █ █░▒▒▓▓▓▒██▒▒█░▒ ▒█ ▒░▓
|
||||
▒░▒ █▒▒▒█ ▓█ ░▓▓░ ▒█▓▒ ░██ ▓▒▒
|
||||
▒▒▒▒░ ██ ░ ░▓██▒▓▓▓ █░
|
||||
▒█▒▒▒█ ▒██ ░██
|
||||
█ █▓ ██▒ ▒▓██ █▒▓
|
||||
█▓███ █░▓▒█▓▓▓▒█ ███
|
||||
░ ░▒▓▒▒▒▓▒▒▓▒█░
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒██▒▒████▒█▒▒
|
||||
▒▒░█░▒▒█▒▒▒█░▒░█░█▒
|
||||
█ █░██▓█░ ░▓█░▒▓░░█
|
||||
▓▓░█▓▓░ ▒▓▓▒░░▓▒
|
||||
▓▓░░▓█ █▓████▓█▒░▒
|
||||
█▒░ ▓░ ▒█████▓██░░▒░█
|
||||
░░░ ░ ▓▓▓▓ ▒░░ ░██
|
||||
░▓░ ░ ░ ░█▒▒█ ░ █▓░
|
||||
▒ ▒ ░█░▓▒▒▒▒▒▓▒░▒█░▒ ▒▒ ░ ░░░
|
||||
░▒▒▒░ ▒ ▓░▒ ▒░▒▒█░ ▒▒░
|
||||
▓█░ ░ ░ █░▓▓▒░▒▓▒▓░
|
||||
█░░▒░▓ █▓░▒▒▓░
|
||||
▒ ░██▓▒▒ ▒▓ ▓█▓█▓
|
||||
▒▒▒█▓██▒░▒▒▒██ ▓▒██░
|
||||
░ █▒▒░▒▒█▒▒██░
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒░▒▓███▒▒█▒
|
||||
█ ▒▓ ░▒▒░▒▒██▒██
|
||||
█ █▓▒▓█ ░ ▓░▓█░███ ▒
|
||||
██▓▓█▓░▒█▒░░▓░ ▒█▒░▒▒█
|
||||
█ ▓▓▒▓█ ░ ▓▒▒░░░▒░██
|
||||
░█▒█▒░ ███▓ ▓░▓ ▓ ▒
|
||||
░ ░░ █▓▒█▓ ▓▒▒░▒▒░▒
|
||||
░ ▒░░ ░█▒▓▒▒░░▒▓▓░░░
|
||||
░▓ ░▓▓▓▓██░░░██▒██▒░ ░ ░░
|
||||
▒ ▓ █░▓██▓▓██░▓▒▒██░ ░█░
|
||||
▒ █▒░▒█ ░ ▒█▓█▒░▒▓█░
|
||||
▒ ▒██▒ ░ ▓▓▓
|
||||
▒▓█▒░░▓ ▒▒ ▒▓▓▒█
|
||||
▓▓██▒▒ ░░▓▒▒▓░▒▒▓░
|
||||
█▓▒██▓▒▒▒▒▒██
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒█▒█▓████▒
|
||||
█ ███░▒▓▒░█░░█
|
||||
▓░▓▓██ ▓░█▒▒▒░░░▒
|
||||
░██░ ▓ ▒░ ▒░██▒▓
|
||||
█▒▒▒█▓█▒▓▓▒░ ░▓▓▒▓█
|
||||
▒█░░░▒██▓▒░▓ ▓░█░▓▓░█
|
||||
░▓░█░ ░▒▒▓▒▒▓░▒▓▒ ░▒░
|
||||
░░░▓░▓ ░▒▒▒▓░▒▒░▒░░▒
|
||||
▒█▒░ ░▒▒▒▒▒▒█░░▒▒░██░▒
|
||||
▓▓ ░▓░█░▒░░▓█▒░▒█▒▓▒░
|
||||
▒░█▓▒░░ ██▓░▒░▓░░
|
||||
░▒ ░▓█▓▒▓██▓▒▓█▓▓░▓
|
||||
▒░▒░▒▒▒█▓▓█▒▓▒░░▓
|
||||
▒▓▓▒▒▒█▒░██ █░█
|
||||
░█ █▒██▒█░█
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓███ ██
|
||||
▓█░▓▓▒░█▓░█
|
||||
▓█ ░▓▒░▒ ▒█
|
||||
▓█ █░░░▒░░▒█▓▒
|
||||
░▒█▒░▓░ █▒▓▓░▒▓
|
||||
▒ ░▓▓▓ █▒▒ ▒▒▓
|
||||
░ ██▒░░▓░░▓▓ █
|
||||
▓▓ ▒░░░▒▒▒░░▓░░
|
||||
░ ▓▒█▓█░█▒▒▓▒░░
|
||||
▓▒░▓█░▒▒██▒▒█░
|
||||
░░ ▓░█ ▒█▓░█▒░░
|
||||
▒▒░░▓▒ ▓▓ ░░░
|
||||
█ █░▒ ▒░▓░▓█
|
||||
░ █▒▒ █▒██▓
|
||||
▒▓▓▒█░▒▒█
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▓█████
|
||||
░▓▓▓░▓▒
|
||||
▓█░ █░▓█░
|
||||
░░░▒░░▓░░
|
||||
░ ░░▒▓█▒
|
||||
░▒▓▒ ░░░░░
|
||||
▒ ░░▒█░░
|
||||
░ ░░░░▒ ░░
|
||||
░▓ ▓ ░█░░░░
|
||||
█▒ ▓ ▒░▒█░░
|
||||
░▓ ▒▒███▓█
|
||||
░░██░░▒▓░
|
||||
░▒▒█▒█▓░▒
|
||||
▒▒▒░▒▒▓▓
|
||||
█▒ ▒▒▓
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▓██▓
|
||||
░█▒░░
|
||||
▒ ▓░░
|
||||
░▓░█░
|
||||
░ ░░
|
||||
░ ▓ ░
|
||||
▒░░ ▒░
|
||||
░▓ ░
|
||||
▓▒ ▒░
|
||||
░░▓▓░░
|
||||
░ ▒░
|
||||
░▒█▒░
|
||||
░▒█░░
|
||||
█▒▒▓░
|
||||
░ ▓█░
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
██████
|
||||
█░█▓ █▒
|
||||
▒█░░ █ ░
|
||||
░░░░▒▒█▓
|
||||
▒ ░ ░ ░
|
||||
░█░░░ ▒▒
|
||||
░▒▒░░░ ▒
|
||||
░░▒░░
|
||||
░░░█░ ░
|
||||
▒░▒░░ ░
|
||||
█░░▓░▒ ▒
|
||||
░▓░░░ ▒░
|
||||
░░░░░░▒░
|
||||
░▒░█▓ ░█
|
||||
░░█ ▓█
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓▒▓██▒▒▒▒█▒
|
||||
▒██▓▒░░█░ ▒▒░▓▒▒░██▒
|
||||
█▓▓█▓░█ ░ ░ ░ ███▓▒░█
|
||||
▓█▓▒░▓██▒ ░▒█ ░░▒
|
||||
█▓█░▓▒▓░░█▒▒ ▒▒▒░░▒
|
||||
▓░▒▒▓ ▓█░▒▓▒▒ ░ ▒▒░
|
||||
▒█ ░ ██▒░▒ ░█ ▓█▓░█
|
||||
█▓░█░ █▓░ ▓▒░ ░▒░▒░
|
||||
▓ █░ ▓░██░░█▓░▒██▒▒▒██▒░▒ ▓░
|
||||
█▒▓▒█ ▓▓█▓▓▓░ ░█░▒▒█ ▒▓█▓▒░░▒░░
|
||||
█▒░ ░ ░░██ ███ ███▓▓▓█▓
|
||||
██░ ▒█ ░ ▓▒█▒▓▓
|
||||
▒▒▓▓█▒█ ██▓▓ █░█
|
||||
▒▒██▒██▒▒▓▒▓█▓▒█▓░▒█
|
||||
░███▒▓░▒▒▒▒░▓▓▒
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓ ████
|
||||
▒▓▓░░▒██▒▒
|
||||
█▒░█▒▒░██▒
|
||||
░░▒░▓░▒▒░▒ ▒█
|
||||
▒█░░░▒░█░█ ░
|
||||
░█░▒█ █░░░░▓░
|
||||
▒▓░░░▒▒ ▒▓▒░ ▒░
|
||||
░ ██▒░█░ ░▓ ░
|
||||
░▒ ▒░▒░▒▓░█ ░
|
||||
░░▒░▒▒░░ ██ ░
|
||||
▒░░▓▒▒█░░░█░░
|
||||
░█▓▓█▓█▒░░ ░
|
||||
▒░▒░░▓█░░█░▓
|
||||
█▒██▒▒▓░█▓█
|
||||
▒▓▓░▒▒▒▓█
|
||||
░░░░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓▓████▒█
|
||||
▒██▓██▒ █▒███
|
||||
█░▒▓▓█▒▒░▓ ░▒█▒
|
||||
█░▓█▒▒█▓▒█▒▒░▒░░▒
|
||||
▒░░░░█▓█▒▒█ ▒░▓▒▒
|
||||
▓░▒░░▒░█ ▒▓██▓▓░█ ░
|
||||
▓░░ ░▒█░▒▓▒▓▓█░█░▓░
|
||||
▒▒█ ░░ ░▒ ░▒ ░░▒▓░
|
||||
░▒█▒░█▒░░░▓█░░░▒ ░
|
||||
░░░▓▓░░▒▒▒▒▒░▒░░ █
|
||||
▒█▒▓█░█ ▓███░▓░█░▒
|
||||
░░░▒▒▒█ ▒▒█ ░
|
||||
▓░█▒▒ █ ▓ ░█░▓░
|
||||
▓░▒░▓▒░░█░ █░░
|
||||
█ ▒░▒██▓▓▓█
|
||||
░░░░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
█████▓▓░█▒
|
||||
▓█░██░▒░░██░░█
|
||||
▓▒█▒▒██▒▓▓░█░█▒███
|
||||
█▓▓░▒█░▓▓ ▓ █▒▒░██ █
|
||||
▓▓░█░█▒██░▓ █░█░▒▓▒█▒█
|
||||
▒▓▒▒█▒█░░▓░░█▒ ░█▓ █
|
||||
█░ ▓█░█▒░░██░█▒░▓▒▓▓░█▒
|
||||
░░░█▒ ▒░░ ▓█░▓▓▒ ▒░ ░
|
||||
▒░░▓▒ █▒░ ▒▒░███░░░▒░ ▒░
|
||||
█ ▒░░█▒█▒▒▒▒▒▒░░█░▓░▓▒
|
||||
█▒█░░▓ ░█ ███▒▓▓▓▓▓▓
|
||||
▒█░▒▒▒ █▒░▓█░
|
||||
███░░░█▒ ▒▓▒░▓ █
|
||||
▒▓▒ ░█░▓▒█░▒█ ▒▓
|
||||
░▓▒▒▒██▓█▒
|
||||
░░░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒██▒█▒█▒░▓▒
|
||||
▒██░░▒█▒░▓░▓░█░█▓
|
||||
▒▓▒░████▒ ░ █▓░░█ █
|
||||
█▒▓░▓▒░█▒ █░░▒▒█
|
||||
▒▓░▓░░░▓▒▒▒ ░█▒▒▒
|
||||
▓▓█ ▒▒▒▒░▒█ ▓▒▓▒▒
|
||||
░░█ ▒██░▒░▒ ░█░░
|
||||
█░██ ███▒▓▒█ ▒ ░█
|
||||
░░░ ░ █░ ▓████▓▒▒█░░█▓▒░▒░
|
||||
▒▓░█ ▓▓█▓░░░▒▒▒▒▒░░█▒▒▒░░▓
|
||||
▒▒▒█ ░▓░▓ ▓ ███ ░░█▓▒░
|
||||
▒█▒██ █ ▓▓▓▓▒▓
|
||||
█▒ ███▓█ ▒█░█▓█▒█
|
||||
▒░ █▒█░█▓█▒ ▓█▒█░█
|
||||
▒▒██▒▒▒▒██▓▓
|
||||
░░░░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒█▒████▒░█▒
|
||||
▒███▓▒▓░ ░██▒██▓█▒▒
|
||||
▒▓▓█░█ ▓░█░ ░▒▒▒█ ███
|
||||
█▓▒░█▒▓█▒ █░██▒▒
|
||||
▓▓░▒▓▓░ ░ █ ▒▒█▒▒
|
||||
█▓▒░░▓ ▒▒ ░▒█▒ ▒█▒░▒
|
||||
░█▒░▒ █▒▒█░▒▒ ░▓░▒
|
||||
▒░▒ ▓ ░█▒░▓ ░ ▓ ▒▒
|
||||
██▓▓ ▓▒▓▓ ▒▒▒██████░▒▒ ░▒░
|
||||
░░▒█▓██▒ ▓▓█░░░▒░▓▒▒▒█▓▒░░░░▒
|
||||
▓▒▒█ ░▒░█▒ ██░░░░▒ █▓█▒░█
|
||||
▓█▒▓▒▒▒ ▓▓▓░▓█
|
||||
▒█░░█▒▓█ ▒█▒ ▒▓█░
|
||||
▓▒▓░ ░██▓██▒█▒█░██▓█
|
||||
░▒▓▒▒▒▒▒▒▓▒█▒▒
|
||||
░░░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒██▓▒███▒██▒
|
||||
██▒█▓░███ ░█░▓ ░█▒▒
|
||||
▒▓▓░▓██░▒█ ░ ░ █▒█▓ ░██
|
||||
█▓▓█▓█▓█▒ ██▒▒░▒
|
||||
▓▓░░▓▓▒ ▒██ ░▒█░█
|
||||
▓▓▓▓█░ █░▒ ▓▓█▒ ░▒▒░
|
||||
▒ ▓▓ ▒▒ ██▒▓ ░▒▒▒
|
||||
░░░▓ ▓▒▒▓▓█ ▓ ▓
|
||||
▓ █▒ █░░▓▓ ▓░▒▒▒▓▒▒█░░ ░░▒█
|
||||
░█▒▓█ ▓▓▓ ██▓░▓ ▒█▒▒▒▒▓ ░▓█ ░█
|
||||
▓░▒██▓▒▒░▓▒░ ░ ▒▒▒▒█▒▒█▓▓▒█░
|
||||
▓▒▒▓░ ▒▓█ █▒
|
||||
▒▓░▒▓█▓█ █▓▓▒███
|
||||
▒▒ ░█░▓▓░░█░▓▓█ ▒▓▓
|
||||
▒░▓▒▒▒▓▒▒███ ▒
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▒█▒████▒██▒
|
||||
▒▒ ▒█▓▓▓█▒█▓██ ███▒
|
||||
█▒█▒███▓█ ░░ ░ █░██░██░█
|
||||
▒░ ██▒▒▒▒ ██░▒ ░
|
||||
█▓▒▓▒█░▒░▒█▓ ▒▒▓█
|
||||
▓ █▓░ █▒ ░▓█ ▒▒█
|
||||
░ ▓ ░ ▒ ▒▒ ░▒░█
|
||||
░░▒░ ▒▒ ▒▓▓ ▒░ ░
|
||||
░█ ░ ▓▓ ██ ████▒█████▒ ░▒░░
|
||||
▒█░▒ █░▒▒▓░▓ ░░▒▒▒▒▒▒▒░░ ▒▓█░
|
||||
█ █░▒ █▒█▓▒ ██▒▒▒▒▒ ░█ ▓
|
||||
██ ▒▓▓ █▓░ ▓
|
||||
▒▓░░█░█ ███ ▓█░
|
||||
██▒ ██▒▒▓░▒█░▓ ▓ █▓██
|
||||
░██▓░▒██▒██████
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓▒▓█▒▒█▒██▒
|
||||
▒▓ ██░▓ ░▒▒▓█▓░ ▓██▒
|
||||
██▒░░░██ ░ ░▒░▒▒█░▓▒▒▒
|
||||
▓▓░█░ ▓██ ░██▒█▒
|
||||
▓░▓▒░▒░▒▓▒░█ ▒ ▒░█▒
|
||||
▓░░▒░ █▒░░▓█▒ █ ▒▒░█
|
||||
▒░▓░ ███▒█ ░█ █ ▓░
|
||||
░▓▒ █░▓█▒░░ ░░░
|
||||
▒░ ░▒ ▓░▓ ▒▓▓█░███▒▒▒▒██ ░░█
|
||||
░▒▓ ░ █▓▓▓█▒░░▒▒░█▓▒█▓▓▒▓░▓▓ ░
|
||||
░░▓█▒█▒▒█▒▓ ████████▒▓░░░░
|
||||
█░▒ ░▒░ █▒▓▓███
|
||||
▒▒█▓▒ █▒ ▒▓▒██▓░▓
|
||||
░░░▒▒██▒▓▓▒▓██▒██▒░█░
|
||||
█▒▒░▓░▒▒▒▒▒▓▓█░
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓▒▓▓█▒▒▒██▒
|
||||
▒█ █▓█▓░░█░▒█▓▒░ ██
|
||||
█▒▓▒█░█ ░ ▒▒░█▒ ███
|
||||
█░▓░▓░▓▒█ ▓▒░░░░▒
|
||||
█▒▓█▓▒▒█░▒▒█ ░ ▒░▒░▒
|
||||
░░░░▓ ▒▒░▒▓▓░▒ █▓░░
|
||||
░▓░ █ ░▒▒░▒ ░█ ██░█░█
|
||||
░▓░▒ █▒▒░▓▒░ █░▒░
|
||||
░█░▒█ ▓▒░ █░█▒▒░█░▒▒▒██▒ ░▓░
|
||||
▒▒░▒██▓██ ░ ▓▓▒▒▒█▒▓█▓░▓█░░
|
||||
▒█░░█░█▒▒▓█░ ██ █░▓░▒▓
|
||||
▒▒█▓▒▒ ░ ▓▒▓██▒
|
||||
▒▓█▒░▒█▒ ▒▒████▓█
|
||||
▒░█░███▒▓░▒▒██▒█▒░▓█
|
||||
▒▓█▒█ ▒▒▒▓▒███░
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓▒▓▓█▒▒██▒▒
|
||||
█▒▓▓█░▒██░██▓▒███▒
|
||||
███░░░█ ░ ░▓▒███▓▒▒
|
||||
▓█░█░█▒▒█ ▒█░░░░█
|
||||
█▒░░░█▒▒██▒ ▓▒▒░▒█
|
||||
▓▓▓░▓░▒█▓░▒▒░█ ▓▒▒▓░
|
||||
▒ █░░ ▒▒░▓▒▒ ▒█░▒░
|
||||
░ ░░░ ▒░▒░▓░░ ░█▒░░
|
||||
▒▓░▓░ ▓█░░█▓▓█▒░█░▒▒██▒▓▒▓░
|
||||
░░▒█▓▒▒▒▓█ ░▓▒██░░█▓▒▒▒░█░▒
|
||||
▓ ░ ▓░░░▓▓ █ ██ ░▒▒▓░
|
||||
█ ▓ ▓█░ █▓▒▓▓░░
|
||||
▓░▒▒███ ▒█▒▒▓███
|
||||
░ ░██ █ ▓░▒▒████ ▓▓█
|
||||
▒▓▓███▒▒▒░▒███
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▓░▓██▒▒██▒
|
||||
██░█▒░███▒▒▒▓ ░██
|
||||
█ █░░░█░ ░▒░░ █▓▒██
|
||||
▒▒░░░░▓█ ▒░▒█░▓█
|
||||
░█░█░░▒░▓▒█ ▓ █░░▒
|
||||
░ ▓░░ ░█▒▓░▒ █▓░░░
|
||||
░▒ ░ ▒▒░▒░▒░ ██▒░░
|
||||
▒ ▓░░ ▒█▓░█░░ █ ░░░
|
||||
▓ ░█ █ ▒▓░▒▓░░▓▓▒░░▒▓█▒░░
|
||||
░██░░▒▓░░▓█░▓▒░░▒▒█▒█▓▒░▒░
|
||||
▒ ▒▒▓█░█▒▓ ██████ ▒▓░░
|
||||
█▒ ▓▒▓▒░ █ ▓▓▓▓█
|
||||
█▓██▒▒▒▒ █▒░██▓██
|
||||
▒▒█▒░█▒▓░▒▒▒██░██▓
|
||||
░█ ░▓░▒▒█▒▓██
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▒▒█▒▓██▒██▒
|
||||
█ █▓░░░█▒▒ ░ █
|
||||
▒░▒█░▓▓█ █ ░▓░█▒█▒█
|
||||
▒█▒█▓░██░ █ ▒▒░░▒
|
||||
█ ▓░▓█▒░▓▒ ▓█▒░░█
|
||||
░██░▒▒▒▒▒░▒█ ▒█░░░
|
||||
░█░░░ █▒▓▒░░░ ░▒░▓░█
|
||||
▒█░░▓ ░█▒▓░██▓ ▓░▓░░
|
||||
▒ ▒░░▒▒ ▓█▒░░▓█████▒░░░
|
||||
▒█▓▒▒░ █░█░░▓░▒▒▒░░▒█
|
||||
▓▓▒▒░▒░░░▓█▒█▒█ ▒█ ▓▒░
|
||||
██ ░▒░░░ ▓█▓▓▓█
|
||||
█▒▒█▒▒▒▒ ▒▓▒▒░█▓█
|
||||
▓▓█░██ ▓▓██▓▓▒█░░
|
||||
░░▒██▒░▒██▓▒░
|
||||
░░
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
▓▒▒█▓██▒█
|
||||
▓█▒▓░░█ ▒ ▒▓▒▒
|
||||
▓ █░░▓█▒▒▒▓ ▒▒░█
|
||||
░░▓▓▒▒ ▒▒█░▒▒░██
|
||||
▓█ ▓▒█ ░██ █▓██▓█░░
|
||||
░ ░░░ ▒░▒▓▒▒ ░█░█░░░
|
||||
░ ░█▒░██░▒▒█ ▓█▓ ░░░
|
||||
░ ░▓▒█▒░░░▒▓▒▒▒░ ░░
|
||||
█░ ▓░ ░░░░█░░█░░░
|
||||
░▒░░░▒█░▒░▒░░░░▒▒░░░
|
||||
░▒▓▒▒░▓ ████░░ ▓▒░
|
||||
▒░░░▒█░ █▓ ▒▓░░
|
||||
▒█▒░▒▒ ▓▓▒▓░▓█
|
||||
▒▓ ▒▒░█▓█▒▓▓█░░
|
||||
█▓▒ █▒▒░▓█▓
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eoeddccddcoe
|
||||
edoocecocedxxde ecce
|
||||
oxcxccccee eccecxdxxxc
|
||||
dceeccooe ocxdxo
|
||||
eedocexeeee coxeeo
|
||||
xc ce xcodxxo coexxo
|
||||
cecoc cexcocxe xox
|
||||
xxexe oooxdxc cex
|
||||
xdxce dxxeexcoxcccccceco dc x
|
||||
exdc edce oc xcxeeeodoooxoooox
|
||||
eeece eeoooe eecccc eccoodeo
|
||||
ceo co e ococex
|
||||
eeoeece edecxecc
|
||||
ecoee ccdddddodcceoxc
|
||||
ecccxxxeeeoedccc
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eccccecce
|
||||
ccecccexoeco
|
||||
eeoxxoxxoxceoo
|
||||
xeeoexdeoeocceeo
|
||||
o dxxcxe cooeoxo
|
||||
xe cxcxooe eecx
|
||||
e xcccxxxxc xoo
|
||||
c xxecocxxoeeoexx
|
||||
c xe eexdxxcecdxx
|
||||
x oxeoxeoeceeexce
|
||||
o cxxxxxcc eocexe
|
||||
eecoeocc exccooo
|
||||
xc xxxxcodooxoe
|
||||
deccoxcde ooc
|
||||
co eceeodc
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
occcccce
|
||||
oc dxxxeeo
|
||||
oceexxdecoeo
|
||||
xeexxddoedoo
|
||||
ecodexcecdexxo
|
||||
xcexxceddxeoxx
|
||||
cc oxxxxxxexde
|
||||
x xxoxxeo xcx
|
||||
o cxoxxcocxex
|
||||
cc exodocoxexe
|
||||
ceo xxxxdoxeex
|
||||
eeooxecoccdxe
|
||||
e cxeeeexdc
|
||||
ec cxxoeoce
|
||||
ee cccece
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
ccccco
|
||||
odeeoxoe
|
||||
c xoeco
|
||||
ocxxxddcx
|
||||
x cxxxxoox
|
||||
xcoocecexc
|
||||
x xoexxe
|
||||
x ocexxc
|
||||
co xoxxcxx
|
||||
x oxcdce
|
||||
xo xcdcco
|
||||
o cx eox
|
||||
o ccxocex
|
||||
ceocoxexe
|
||||
e cxeoo
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
occco
|
||||
xeexx
|
||||
xeexc
|
||||
xccxe
|
||||
c xx
|
||||
cdoxx
|
||||
o xx
|
||||
c cx
|
||||
oc exo
|
||||
xc cdx
|
||||
ceoo xe
|
||||
xeeex
|
||||
xcoxe
|
||||
ceexd
|
||||
o ocd
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
ccccd
|
||||
ooeeoe
|
||||
xexxo x
|
||||
xxoxcexo
|
||||
xxxe x
|
||||
xcxx cx
|
||||
xxxx o c
|
||||
xxexe e
|
||||
xxxx c
|
||||
ceoo do
|
||||
exccooox
|
||||
xcxxeeex
|
||||
o cxddde
|
||||
xeoceeo
|
||||
ec cdo
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
cccccxe
|
||||
eodxxedco
|
||||
ooxcdexccx
|
||||
xoe ooooeex
|
||||
xxdcdexxocex
|
||||
exxoxxoox c
|
||||
xx xxxxxxox
|
||||
xxoxxcxxx cox
|
||||
xxcoocxxxeodx
|
||||
xexdoxexco ox
|
||||
xoxxxxex e d
|
||||
xccoexxeo d
|
||||
cxeo oooe de
|
||||
xexxeeoceo
|
||||
eeceeeeo
|
||||
ee
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
edcccccxe
|
||||
oexxcxxexde
|
||||
xooceodexx ce
|
||||
ooo dceexexxccx
|
||||
xxdeoccdxxcoxee
|
||||
xxxcxc xed x xox
|
||||
eex oeoxxxxocco x
|
||||
xod xexxoxxxcd ex
|
||||
eexxxcxoexxccc o
|
||||
cceeoddecxoex oex
|
||||
xxxcccocexdcdoxxe
|
||||
xxc xe eooo o
|
||||
exc x oooeox
|
||||
exxcecxoocex
|
||||
cdoeddeedc
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
odcccddxoe
|
||||
edccxxxcdcxoceo
|
||||
oceoeddecocxxxece
|
||||
oxoeoxcee cxdexxxde
|
||||
xoe x xcoedeoo o
|
||||
edcooe odox oodoxoo
|
||||
c dox oooxe ccxxodx
|
||||
ocdx ooxxoxoxxddc
|
||||
oocoeddcxeexeedexxx x
|
||||
xcedeexoceoxxe eccce
|
||||
eeeoccccccceexcooe ec
|
||||
exxec eoxxe d
|
||||
eee cee ocooeeo
|
||||
o xccdeceedcdxc
|
||||
ecdoeocxcecc
|
||||
e
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eddcddcdxoe
|
||||
eccedoccxeeoccdde
|
||||
eodxcccdcocoeccooe c
|
||||
oxxcooecc ceeeodxedeeeo
|
||||
eeoo ox ecceeoxoxeedeee
|
||||
oex ooxoeeeoocoxcooeoeox
|
||||
xxedo cocoxceoccxdxdo
|
||||
ceoxx eecxxde xdxc
|
||||
ecc oedddddcxxoxcoeo xcxe
|
||||
eeexcec xxoeeeexxxedxee o
|
||||
xoxeeccccccce eeeoxocoeoe
|
||||
ee oeo eeccocec
|
||||
eecceeo eceeoeoe
|
||||
cxoccccdddecceoeoc
|
||||
cxxeoeeooccdcc
|
||||
e
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eeddcxcddxoe
|
||||
ecxxxeodddeceoxcoo
|
||||
ocddocxcce ecdoecde
|
||||
odxcoee eddcoexco
|
||||
xxoeoe oxecocxe xeo
|
||||
xeocc excxo oo cocx
|
||||
edxxc oceoxcoe odocx
|
||||
xxxx xdcexco x xxx
|
||||
xcxeoddddddxxxxccdcxd e cxx
|
||||
edooxdcoecceoeo ee deeeoooxe
|
||||
cecocxcccccccc eeeoxoo ooc
|
||||
eeecee eooeooc
|
||||
c eexxco oddooxde
|
||||
ccoxcoxceeddocc dcxc
|
||||
cxoedoceooecoe
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eoeddcdddcoe
|
||||
ecoocdcxxxdxxdecxcce
|
||||
oxcxeccxcee eccdcoxxdxo
|
||||
exoeoccooe ooexoxo
|
||||
oecocexeeeee eoxexo
|
||||
cocce xcecoec eexcx
|
||||
oxccx eoxdxexo ocxcx
|
||||
xc ee oxcxxdc xcoox
|
||||
cccdx dxeeexcoxccccccccoxexxc
|
||||
edcx oxxc oc xdeeeeeooeexco x
|
||||
eee c ceooxc ecccccccccxocxx
|
||||
ceeooo e ocdooc
|
||||
oeeexco odec exc
|
||||
exedeecccdddddodceexxc
|
||||
eccccxxeeeexdocc
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eecdxxdcdoee
|
||||
oddcdoeodddxxeececo
|
||||
oocecccxcc ecececcxce
|
||||
excecxc eocxeocee
|
||||
ex oxc eo exxecexxe
|
||||
oeoxc cccdxco cexxe
|
||||
dxdcx oc occe oexo
|
||||
xeeoe ccddxco xxcx
|
||||
xoxxdoddddddddeocdeeeec o xe
|
||||
cxexec oeeeeeexe ceecxde oo xx
|
||||
eoeecccccccccc eodxxox oe
|
||||
c ecoo eocoxo
|
||||
eeecoxe odcedcc
|
||||
eooocxceddodcxceoocc
|
||||
eccxe deeeexccc
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eeodcddcdcoee
|
||||
occeeeecxdxcdeeocce
|
||||
dceeccece eexcceeco
|
||||
ocxdcc eodcodco
|
||||
oooce oxoee eeeeo
|
||||
ocox occeoo eeeo
|
||||
xcxe e oeooc edec
|
||||
ee ed cxo x x
|
||||
x x ocdddddccc exocxo do x
|
||||
x xe xe eox ececxo ocoo
|
||||
d co eeccc ce cceod oe o
|
||||
cc dde ecc o
|
||||
ce eoe eodcc oe
|
||||
cde ccccdxxdddccc oe
|
||||
cccdceeeeoedcce
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eocdcddcdcoe
|
||||
ecocxoeoxoexxdxcocce
|
||||
odcdxecce ecceccceeco
|
||||
dcxccc ooxxxece
|
||||
exxoc oeoxdxoodcx
|
||||
excoe oxoxdeoe exedx
|
||||
xcceo xcxecoc xxox
|
||||
xxdxe xexxee xexcx
|
||||
xxoco cxddddddcceecxe eo exdc
|
||||
exd ceeeo oocxoox ecdecxoo oed
|
||||
eeeex cccccccce edcceooocoe
|
||||
eceeeo ecocxoc
|
||||
cccd cce eococceo
|
||||
cdccoccxddcddodccccoc
|
||||
cxcxedeeeodeodce
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eocedccccdcee
|
||||
edxcxeeoeddoxexcxce
|
||||
occxcodce cxdcxedxxo
|
||||
odxcdoe eddexxde
|
||||
ooxeoc ooooccocexe
|
||||
oexcoe ecccccoccxxexo
|
||||
exxcx odoo exe c xcc
|
||||
xox x xcxoeeo x cox
|
||||
ece xcxddddddddxecxecee x xxx
|
||||
xeeexcdc oee exeeox eex
|
||||
ocx x eccccccc ceoddxeoeoe
|
||||
oxxexo ooxeeoe
|
||||
e xocoee eocdcoco
|
||||
edecdccexddecccoecce
|
||||
cx cdexeeceecce
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
exedcccddoe
|
||||
oceocxeexddcoecc
|
||||
occdeoccx oedcxcco e
|
||||
ocooooxdoeexoe ecexeec
|
||||
o ooeoo eccoeexeeexoc
|
||||
xoecee cooo oxd oce
|
||||
x xx ooeoocoeexeexe
|
||||
x exx xodoeexxeooexx
|
||||
xo xddddccxxxccecoex x xx
|
||||
e o cxoooddooxoeeccx xcx
|
||||
e cexeccccccce eoocexdooe
|
||||
e eoce x codo
|
||||
eoceexo edceodec
|
||||
oocoeecxxddddxeeoe
|
||||
cdeccdeeeddcc
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
ecdcdcccce
|
||||
o coceedexcxxo
|
||||
oxoooocoxcedexxxe
|
||||
xccx o dx cexoceo
|
||||
oeeeoocedoexc xooeoc
|
||||
eoxxxeccoexd oxoxooxo
|
||||
xoxcx xeeoeeoxeoecxdx
|
||||
xxxoxoc xedeoxeexdxxe
|
||||
ecexcxeeddddcxxeexccxe
|
||||
oocxoxoxexxdcexecdoex
|
||||
excoexecccccccoxexoxe
|
||||
xecxdcdeoocdeooooxo
|
||||
eeexeeecdooeoexxo
|
||||
eodeeecdxcc cxc
|
||||
xoccecoecxc
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
edccccco
|
||||
ocxdoexcdxo
|
||||
occcxdexecceo
|
||||
dccoxxxexxecoe
|
||||
xeoexoxcceodxed
|
||||
e cxodocceeceeo
|
||||
x ccdxxoxxddcc
|
||||
oo exxxeedxxoxx
|
||||
x oecdcxcddoexx
|
||||
oexooxeeoceecx
|
||||
xecoxcceooecexx
|
||||
eexxoe oocxxe
|
||||
c cxe eeoxoo
|
||||
xcceecceccd
|
||||
eodecxeec
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
dcccco
|
||||
xddoxoe
|
||||
dce cxocx
|
||||
xxxexxdxx
|
||||
x exeocd
|
||||
xeoecexxxe
|
||||
d cxxecxx
|
||||
x exxxdcxx
|
||||
xo o xcxxxx
|
||||
cd ocexecxx
|
||||
xo eecccoc
|
||||
xxccxxeox
|
||||
xddcdooxe
|
||||
eeexedoo
|
||||
cec eeo
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
occd
|
||||
xcexe
|
||||
d dxe
|
||||
xoecx
|
||||
x xx
|
||||
x ocx
|
||||
exx ex
|
||||
xoccx
|
||||
oe ex
|
||||
xxodxx
|
||||
x ex
|
||||
xdcdx
|
||||
xdcxx
|
||||
ceeox
|
||||
x ocx
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
ccccco
|
||||
oxco ce
|
||||
eoxx ccx
|
||||
xxxxeeoo
|
||||
e xcx x
|
||||
xoxxx ee
|
||||
xeexxx e
|
||||
xxdxx
|
||||
xxxcx e
|
||||
exdxx e
|
||||
cxxoxe d
|
||||
xoxxx ex
|
||||
xxxxexex
|
||||
xdxcocxc
|
||||
xxc oo
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eoddccddddoe
|
||||
ecooexxcxcddxdeexcce
|
||||
odocdxccce ecx cccoexo
|
||||
ocoexdoce edc xxe
|
||||
cocxoeoxxcee eeexxe
|
||||
oxeeo ooxedee x eex
|
||||
dc x ccexecxo ocoxo
|
||||
ooxox ooxcoex xexdx
|
||||
occx dxccxxcoxdcceeeccexecdx
|
||||
oedeo oocoddx xcxeeo doodeexexe
|
||||
cex x cxxcoc cccccccccoooooo
|
||||
ccx ec e oeceoo
|
||||
deooceo ocdocoxc
|
||||
decoecceddddoddcdeecc
|
||||
ecccedxeeeexdoec
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
edcccco
|
||||
eodxxeccde
|
||||
ccexoeexcoe
|
||||
xxexoxeexe eo
|
||||
dcxxeexoxo x
|
||||
xcxec cxxxxox
|
||||
eoxxxee eoex de
|
||||
cx ccdxoxcxo e
|
||||
cxecexdxeoxo e
|
||||
cxxexeexx co e
|
||||
exxdeecxxxcxx
|
||||
xcoooocexxc x
|
||||
exexxocxxoxo
|
||||
oeocdeoxooc
|
||||
eooxeeedc
|
||||
eeee
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eodccccdo
|
||||
eccdcoeccecco
|
||||
oxeooodeeocxece
|
||||
oxoceecdeoeexexxe
|
||||
exxxxcoceeocexoee
|
||||
dxeexexccedcoooxocx
|
||||
oxx xecxeododcxcxox
|
||||
eeo xxcxe xeccxxeox
|
||||
xeoexcexxxocxxxe x
|
||||
cxxxooxxeeeeexexx c
|
||||
eceocxo occceoxcxe
|
||||
xxxeeeo edc x
|
||||
dxcde o o xceoe
|
||||
dxexoexeoxcoxe
|
||||
ccdxeccoodc
|
||||
eeee
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
occccddxoe
|
||||
dcxccxexxccxxo
|
||||
oecdeocedoecxcecco
|
||||
cooxeoedo o oeexco o
|
||||
ooxoxceccxd ceoxeoeceo
|
||||
eoeeoecxedxxce xco c
|
||||
cxcdoecexxooxodeoeooxce
|
||||
xxxoe cexxcocxdoecexcce
|
||||
exxoe cexceexcccxxxdxcde
|
||||
ccceexceceeeeeexxcxdxoe
|
||||
oecxxo xccccccedooooo
|
||||
eoxeee oexocx
|
||||
cccxxxce eoexo o
|
||||
eoecxcxddceecceo
|
||||
xddeeococecc
|
||||
eee
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eocdcdcdxoe
|
||||
eccxxecdxdxoxcxco
|
||||
eoexcccodce ccoxxcco
|
||||
oeoxoexoe cxxeec
|
||||
eoxoexxoeee xceee
|
||||
ooo eeeeeeo oeoee
|
||||
xxc eocxexe xcxx
|
||||
cxoo occeodo ecxc
|
||||
xxx x oe ocooodddcxxcoexex
|
||||
eoxccodooexxeeeeexxceeexxo
|
||||
edeo xoxo o ccccccc xxooee
|
||||
ececoco oododo
|
||||
ceccocdo ecxoocec
|
||||
exccecxodcecdoecxc
|
||||
cddcoeeeeccdoc
|
||||
eeee
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
eodccccdxoe
|
||||
ecccoedxcxccdccdode
|
||||
eoooxccdxce eeeeoccco
|
||||
ooexceooe cxocee
|
||||
ooxeoox xc o eecee
|
||||
ooexeo eecxece eoexe
|
||||
xcexe ceecxee xdxe
|
||||
exdcd xcexocx o ee
|
||||
ocooc oeooceddccccccxeec xee
|
||||
xxeooooecoocxxxexoeeeooexxexe
|
||||
oeeo xexce ccceeeee oooexc
|
||||
ooeddee odoxoc
|
||||
ecexcedo ecdceooe
|
||||
oeoxcxcodocdcdceccdc
|
||||
cxeddeeeeeddcde
|
||||
eee
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user