From 985913c1fed22136e463d533d65e824c8c23144a Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Thu, 30 Apr 2026 21:15:21 +0700 Subject: [PATCH 01/12] feat: implement golden round-trip (Rust <-> Mojo) and hybrid tool-calling structure --- .github/workflows/ci.yml | 139 + .github/workflows/security.yml | 44 + .gitignore | 8 + CLAUDE.md | 4 +- Cargo.toml | 23 + DESIGN_DECISIONS.md | 64 +- Makefile | 50 + README.md | 8 +- STRUCTURE.tree | 8590 ++++++++++++++++- buf.gen.yaml | 14 + buf.yaml | 9 + build.rs | 19 + examples/generate_golden.rs | 32 + .../python/vtuber/v1/conversation_pb2.py | 49 + .../python/vtuber/v1/conversation_pb2.pyi | 57 + generated/python/vtuber/v1/persona_pb2.py | 39 + generated/python/vtuber/v1/persona_pb2.pyi | 39 + generated/python/vtuber/v1/tool_call_pb2.py | 46 + generated/python/vtuber/v1/tool_call_pb2.pyi | 49 + .../python/vtuber/v1/voice_profile_pb2.py | 42 + .../python/vtuber/v1/voice_profile_pb2.pyi | 57 + .../typescript/google/protobuf/struct.ts | 615 ++ .../typescript/google/protobuf/timestamp.ts | 230 + .../typescript/vtuber/v1/conversation.ts | 610 ++ generated/typescript/vtuber/v1/persona.ts | 272 + generated/typescript/vtuber/v1/tool_call.ts | 511 + .../typescript/vtuber/v1/voice_profile.ts | 355 + golden_directive.bin | 2 + locales/README.ja.md | 8 +- locales/README.th.md | 8 +- locales/README.zh.md | 8 +- mojo/tests/test_golden_roundtrip.mojo | 46 + mojo/tests/test_roundtrip.mojo | 45 + mojo/vtuber_contracts.mojo | 127 + package.json | 18 + pixi.lock | 1011 ++ pixi.toml | 33 + proto/vtuber/v1/conversation.proto | 71 + proto/vtuber/v1/persona.proto | 32 + proto/vtuber/v1/tool_call.proto | 46 + proto/vtuber/v1/voice_profile.proto | 46 + samples/personas/aurora.yaml | 15 + samples/personas/valora.yaml | 23 + src/lib.rs | 14 + tests/persona_yaml_roundtrip.rs | 85 + tests/roundtrip.rs | 80 + tsconfig.json | 21 + 47 files changed, 13663 insertions(+), 51 deletions(-) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 Makefile create mode 100644 buf.gen.yaml create mode 100644 buf.yaml create mode 100644 build.rs create mode 100644 examples/generate_golden.rs create mode 100644 generated/python/vtuber/v1/conversation_pb2.py create mode 100644 generated/python/vtuber/v1/conversation_pb2.pyi create mode 100644 generated/python/vtuber/v1/persona_pb2.py create mode 100644 generated/python/vtuber/v1/persona_pb2.pyi create mode 100644 generated/python/vtuber/v1/tool_call_pb2.py create mode 100644 generated/python/vtuber/v1/tool_call_pb2.pyi create mode 100644 generated/python/vtuber/v1/voice_profile_pb2.py create mode 100644 generated/python/vtuber/v1/voice_profile_pb2.pyi create mode 100644 generated/typescript/google/protobuf/struct.ts create mode 100644 generated/typescript/google/protobuf/timestamp.ts create mode 100644 generated/typescript/vtuber/v1/conversation.ts create mode 100644 generated/typescript/vtuber/v1/persona.ts create mode 100644 generated/typescript/vtuber/v1/tool_call.ts create mode 100644 generated/typescript/vtuber/v1/voice_profile.ts create mode 100644 golden_directive.bin create mode 100644 mojo/tests/test_golden_roundtrip.mojo create mode 100644 mojo/tests/test_roundtrip.mojo create mode 100644 mojo/vtuber_contracts.mojo create mode 100644 package.json create mode 100644 pixi.lock create mode 100644 pixi.toml create mode 100644 proto/vtuber/v1/conversation.proto create mode 100644 proto/vtuber/v1/persona.proto create mode 100644 proto/vtuber/v1/tool_call.proto create mode 100644 proto/vtuber/v1/voice_profile.proto create mode 100644 samples/personas/aurora.yaml create mode 100644 samples/personas/valora.yaml create mode 100644 src/lib.rs create mode 100644 tests/persona_yaml_roundtrip.rs create mode 100644 tests/roundtrip.rs create mode 100644 tsconfig.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f627f0..f88305d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,3 +82,142 @@ jobs: if: steps.guard.outputs.skip != 'true' run: cargo test + + mojo-build: + name: Mojo Build & Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Skip if no pixi.toml + id: guard + run: | + if [ ! -f pixi.toml ]; then + echo "::notice::No pixi.toml yet; skipping Mojo build/test." + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + - name: Setup Pixi + if: steps.guard.outputs.skip != 'true' + uses: prefix-dev/setup-pixi@v0.8.1 + with: + pixi-version: latest + cache: true + - name: Install dependencies (pixi install) + if: steps.guard.outputs.skip != 'true' + run: pixi install + - name: Mojo check (pixi run check) + if: steps.guard.outputs.skip != 'true' + run: | + # The `check` task is expected to exist in every Mojo repo's pixi.toml + # and to run `mojo format --check` + any static analysis. If the task + # is missing the repo's build is incomplete — fail loudly, don't skip. + pixi run check + - name: Mojo test (pixi run test) + if: steps.guard.outputs.skip != 'true' + run: pixi run test + + + buf-lint: + name: buf Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Skip if no buf.yaml + id: guard + run: | + if [ ! -f buf.yaml ] && [ ! -f buf.yml ]; then + echo "::notice::No buf.yaml yet; skipping buf lint." + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + - name: Setup buf + if: steps.guard.outputs.skip != 'true' + uses: bufbuild/buf-setup-action@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - name: Lint + if: steps.guard.outputs.skip != 'true' + run: buf lint + + buf-breaking: + name: buf Breaking-Change Gate + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Skip if no buf.yaml + id: guard + run: | + if [ ! -f buf.yaml ] && [ ! -f buf.yml ]; then + echo "::notice::No buf.yaml yet; skipping buf breaking." + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + - name: Setup buf + if: steps.guard.outputs.skip != 'true' + uses: bufbuild/buf-setup-action@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - name: Resolve baseline ref + if: steps.guard.outputs.skip != 'true' + id: baseline + run: | + # Pull requests: compare against the merge base with the PR target branch. + # Pushes to main/master: compare against the previous commit (HEAD~1) when + # one exists; on the very first commit, there is nothing to compare so + # skip the job rather than fail the initial bootstrap push. + if [ -n "${{ github.base_ref }}" ]; then + git fetch origin "${{ github.base_ref }}" --depth=50 + ref="origin/${{ github.base_ref }}" + else + if git rev-parse HEAD~1 >/dev/null 2>&1; then + ref="HEAD~1" + else + echo "::notice::No prior commit; skipping breaking-change check for initial commit." + echo "skip=true" >> $GITHUB_OUTPUT + exit 0 + fi + fi + echo "ref=$ref" >> $GITHUB_OUTPUT + echo "skip=false" >> $GITHUB_OUTPUT + - name: Breaking-change check + if: steps.guard.outputs.skip != 'true' && steps.baseline.outputs.skip != 'true' + run: buf breaking --against ".git#ref=${{ steps.baseline.outputs.ref }}" + + buf-generate: + name: buf Generate (dry-run verify) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Skip if no buf.gen.yaml + id: guard + run: | + if [ ! -f buf.gen.yaml ]; then + echo "::notice::No buf.gen.yaml yet; skipping buf generate." + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + - name: Setup buf + if: steps.guard.outputs.skip != 'true' + uses: bufbuild/buf-setup-action@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - name: Generate and verify no drift + if: steps.guard.outputs.skip != 'true' + run: | + # Regenerate into a scratch dir and diff against committed generated/. + # If generated artifacts are committed (they should be for lockstep + # SDK consumers), any drift between proto changes and regeneration + # must fail CI — a reviewer should not have to run buf generate by hand. + buf generate --template buf.gen.yaml + if [ -d generated ] && ! git diff --quiet --exit-code -- generated/; then + echo "::error::generated/ is out of sync with proto/. Run 'buf generate' locally and commit the result." + git diff --stat -- generated/ + exit 1 + fi + diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index a203cd0..0979e85 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -80,3 +80,47 @@ jobs: with: sarif_file: results.sarif + + mojo-security: + name: Mojo Security Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Mojo static analysis (skipped until mojoproject.toml exists) + env: + MODULAR_AUTH: ${{ secrets.MODULAR_AUTH_TOKEN }} + run: | + if [ ! -f mojoproject.toml ]; then + echo "::notice::No mojoproject.toml yet; skipping Mojo static analysis." + exit 0 + fi + curl -fsSL https://get.modular.com -o install-modular.sh + sh install-modular.sh + export PATH="$HOME/.modular/bin:$PATH" + modular install mojo + mojo check . + + + buf-schema-baseline: + name: buf Schema Security Baseline + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Skip if no buf.yaml + id: guard + run: | + if [ ! -f buf.yaml ] && [ ! -f buf.yml ]; then + echo "::notice::No buf.yaml yet; skipping schema security baseline." + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + - name: Setup buf + if: steps.guard.outputs.skip != 'true' + uses: bufbuild/buf-setup-action@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - name: Lint schema (security pass) + if: steps.guard.outputs.skip != 'true' + run: buf lint + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..29dd0e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +target/ +Cargo.lock +node_modules/ +dist/ +*.egg-info/ +__pycache__/ +*.pyc +.venv/ diff --git a/CLAUDE.md b/CLAUDE.md index d5959b3..78d72e4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,8 +4,8 @@ This file is the operational core for Claude. Gemini CLI and Claude MUST follow ## 🎯 Architectural Intent - **Core Mission:** Become the canonical typed boundary for the vtuber program — every cross-service value crosses through here, internal and external developers consume the same generated SDKs. -- **Primary Stack:** Rust, Protobuf (proto3), buf, tonic, ts-proto, mypy-protobuf -- **System Nature:** vtuber-contracts is the build-time source of truth for all inter-service typed boundaries in the vtuber-* program. It defines proto3 schemas for messages such as ConversationDirective, VoiceProfile, and Persona, then runs codegen to publish a Rust crate, Python typed stubs (.pyi), and TypeScript declaration files consumed by every other vtuber-* repo and by the public SDK shipped through vtuber-api. +- **Primary Stack:** Rust, Mojo (via Pixi), Protobuf (proto3), buf, tonic, ts-proto +- **System Nature:** vtuber-contracts is the build-time source of truth for all inter-service typed boundaries in the vtuber-* program. It defines proto3 schemas for messages such as ConversationDirective, VoiceProfile, and Persona, then runs codegen to publish three consumer surfaces: a Rust crate (via tonic-build), a Mojo binding package (via Pixi + Python interop — see ADR-004), and TypeScript declarations (via ts-proto) consumed by every other vtuber-* repo and by the public SDK shipped through vtuber-api. ## 🧬 Automated Lifecycle Management 1. **Research Sync:** When `./scripts/update_notebookLM.sh` is executed: diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9f0687c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "vtuber-contracts" +version = "0.1.0" +edition = "2021" +rust-version = "1.75" +description = "Typed interface contracts (proto3) for the vtuber-* program — generates a Rust crate, Python typed stubs, and TypeScript declarations consumed by every other vtuber-* repo." +license = "MIT" +repository = "https://github.com/echo-layer/vtuber-contracts" +readme = "README.md" +keywords = ["vtuber", "grpc", "protobuf", "contracts"] +categories = ["api-bindings"] + +[dependencies] +prost = "0.13" +prost-types = "0.13" +tonic = { version = "0.12", default-features = false, features = ["codegen", "prost"] } + +[build-dependencies] +tonic-build = { version = "0.12", default-features = false, features = ["prost"] } + +[dev-dependencies] +serde_yaml = "0.9" +serde = { version = "1", features = ["derive"] } diff --git a/DESIGN_DECISIONS.md b/DESIGN_DECISIONS.md index 5be2c38..f8ad93f 100644 --- a/DESIGN_DECISIONS.md +++ b/DESIGN_DECISIONS.md @@ -1,15 +1,67 @@ # Design Decisions (ADR) ## 💡 Philosophy -This project uses Architectural Decision Records (ADR) to track significant design choices. + +vtuber-contracts is the single build-time source of truth for every typed boundary between sibling `vtuber-*` services. Decisions here are load-bearing across 16 downstream consumers, so each ADR is recorded with its full constraint and trade-off context. Rolling log keeps the latest 10 entries per `CLAUDE.md`. ## 📝 Decision Log -### ADR-001: Initial Scaffolding -- **Status:** Accepted -- **Context:** Bootstrapped using MLOps Meta-Repo. -- **Decision:** Use Rust, Protobuf (proto3), buf, tonic, ts-proto, mypy-protobuf for the core implementation to balance performance and safety. -- **Consequences:** Provides a solid foundation for vtuber-contracts is the build-time source of truth for all inter-service typed boundaries in the vtuber-* program. It defines proto3 schemas for messages such as ConversationDirective, VoiceProfile, and Persona, then runs codegen to publish a Rust crate, Python typed stubs (.pyi), and TypeScript declaration files consumed by every other vtuber-* repo and by the public SDK shipped through vtuber-api.. +### ADR-004: Mojo bindings go through Python interop, not native proto codegen + +- **Status:** Accepted — 2026-04-22 +- **Context:** The three target consumer surfaces for `vtuber-contracts` are Rust, Mojo, and TypeScript. Rust has tonic-build; TypeScript has ts-proto. Mojo, verified against `https://docs.modular.com/mojo/manual/get-started/` as of 2026-04, has **no** native proto3 codegen, no `buf.build/modular/*` plugin, and no community protobuf library. Its documented path for consuming external schemas is Python interop via `Python.import_module()`. +- **Decision:** + 1. `buf generate` continues to produce Python `_pb2.py` + `.pyi` files under `generated/python/vtuber/v1/`. They are a **build-intermediate** for the Mojo consumer surface — not a publicly advertised Python package. There is no `pyproject.toml`; external Python consumers are out of scope for v0.1. + 2. The Mojo binding ships as a Pixi project (`pixi.toml` at repo root). Pixi pulls `mojo`, `python>=3.11`, and `protobuf` into a single environment so `Python.import_module("vtuber.v1.persona_pb2")` resolves at runtime. + 3. Mojo source lives in `mojo/`. Every proto message gets a thin Mojo struct facade that holds a `PythonObject` — see `mojo/vtuber_contracts.mojo`. The facade is opinionated but minimal: just enough so Mojo consumers do not type `Python.import_module` by hand. + 4. CI runs `pixi run check` and `pixi run test`. The Mojo round-trip test consumes the Python stubs under `PYTHONPATH=generated/python`, proving the interop end-to-end. +- **Consequences:** + - Pixi is a transitive dependency of every Mojo-consuming repo (`vtuber-brain`, `vtuber-voice`). Rust and TypeScript consumers are unaffected. + - When Modular ships a native Mojo proto plugin, migration path is: add the plugin to `buf.gen.yaml`, keep the Mojo struct facades (same API surface), drop the Python interop guts. Consumers unchanged. + - Python `_pb2.py` files are committed under `generated/python/` to keep the `buf generate` drift-check from ADR-003 working. They are regenerated — never hand-edited. + - The older `get.modular.com` + `mojoproject.toml` install flow is deprecated; `patterns/lang/mojo/ci.yml` was rewritten to use Pixi as part of this ADR. + +### ADR-003: `buf breaking` is a non-skippable hard CI gate + +- **Status:** Accepted — 2026-04-22 +- **Context:** The archived `failures/pandora-code/` repo defined four `.proto` files (`brain.proto`, `voice.proto`, `memory.proto`, `streaming.proto`) but wired no `buf breaking` check into CI. Field renames and removals surfaced at consumer runtime instead of at build time, which was one of the stall paths called out in `failures/codex.md`. Once `vtuber-contracts` publishes a v0.1 tag, 16 sibling repos consume it; a silent breaking change is a 16-repo cascade. +- **Decision:** + 1. `patterns/tools/buf/ci.yml` runs `buf breaking --against ` on every pull request and every push to a release branch. The job is generated into every repo that has `buf` in its `tech_stack`, not just this one, so downstream consumers also catch drift locally before merging. + 2. The check is **not** optional and **not** a warning. A CI failure here blocks merge. + 3. On the very first commit (no `HEAD~1`) the job self-skips with a `::notice::` — this is the only way out, and it only ever fires once per repo. + 4. Baseline selection: pull requests use the merge base with the PR target branch; direct pushes use `HEAD~1`. +- **Consequences:** + - Every proto change requires a semver bump captured in a PR. Field-number reuse or tag-incompatible field-type changes fail the build, which is exactly the desired forcing function. + - Back-compatible additions (new optional fields, new enum variants at the end) pass freely, preserving the fast path for additive evolution. + - The cost is paid once at setup; from that point on, semver discipline is automatic. + +### ADR-002: Director / Performer split as the governing protocol boundary + +- **Status:** Accepted — 2026-04-22 +- **Context:** pandora-code collapsed the reasoning loop and the speech loop into one service tree (`brain/` + `voice/` in the same repo, tightly coupled via implicit Python calls). The rewrite separates the two into `vtuber-brain` and `vtuber-voice` and defines their only contact surface as a typed proto message. +- **Decision:** + 1. `vtuber-brain` is the **Director**: it owns reasoning, memory, persona selection, tool routing. It emits one and only one outbound message type on each turn: `ConversationDirective`. + 2. `vtuber-voice` is the **Performer**: it owns speech synthesis (PersonaPlex-7B primary, Whisper + Typhoon + XTTS cascade fallback for Thai). It consumes `ConversationDirective` and streams audio chunks back — but the audio-stream shape is explicitly **out of scope** for v0.1 and will be added in the brain↔voice vertical slice. + 3. v0.1 ships exactly three messages that define the Director output: `Persona`, `VoiceProfile`, `ConversationDirective`. A minimal `Director` service with a unary `EmitDirective` rpc is included so tonic / buf service codegen paths are validated end-to-end, but full audio streaming is deferred. +- **Consequences:** + - New Director outputs (tool calls, stream-control signals, persona-switch commands) attach to `ConversationDirective` or get their own top-level message — never a loose JSON blob crossing the boundary. + - Brain and voice each evolve their internal stacks (LLM swap, TTS swap) without coordinating, as long as the directive shape holds. + - If this boundary fails — e.g. the Performer needs context the Director does not know — it is a proto-level change, reviewed under ADR-003's breaking-change gate, not a hidden runtime coupling. + +### ADR-001: Package naming and layout (`vtuber.v1` under `proto/vtuber/v1/`) + +- **Status:** Accepted — 2026-04-22 (supersedes auto-generated ADR-001) +- **Context:** pandora's protos used bare package names (`package voice;`, `package brain;`) with no version suffix and no namespace. That made it impossible to evolve to a v2 package in parallel without a full rename; it also polluted the global proto namespace across multiple services. +- **Decision:** + 1. Every `.proto` file sits under `proto/vtuber/v1/` and declares `package vtuber.v1;`. + 2. When a message needs a breaking change, a new `proto/vtuber/v2/` directory is added alongside, containing only the messages that broke. Consumers migrate one message at a time. The old v1 schemas stay supported until every consumer has migrated. + 3. All timestamps use `google.protobuf.Timestamp`. No bare int64 milliseconds, no ISO8601 strings. Pandora had two incompatible conventions in the same repo. + 4. All closed-set string fields become proto3 enums with the `_UNSPECIFIED = 0` convention. v0.1 introduces `PersonaId`, `Emotion`, and `AudioFormat` — one per 3-message surface. Further enums (`Platform`, `StreamEventType`) are added per vertical slice, not up front. +- **Consequences:** + - Side-by-side v1/v2 evolution is mechanical: add v2 directory, add v2 messages, bump consumer at their own pace. + - Anyone reading a proto knows exactly which version they are on from the package path. + - Enum fields catch category errors at codegen time instead of at runtime string comparison. --- + *Add new decisions above this line using the standard ADR format.* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8ca0265 --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +# vtuber-contracts bootstrap Makefile. +# +# The `bootstrap` target is the single source of truth for "does this repo +# build end-to-end on a fresh dev machine?" — per failures/codex.md rule #2, +# it must stay green before any feature work. Run it after every proto change. + +.PHONY: bootstrap lint breaking generate rust-build rust-test mojo-check ts-check clean deps-check + +bootstrap: deps-check lint generate rust-build rust-test mojo-check + @echo "" + @echo "============================================" + @echo " vtuber-contracts bootstrap: OK" + @echo "============================================" + +deps-check: + @command -v buf >/dev/null 2>&1 || { echo "ERROR: buf not installed. See CONTRIBUTING.md"; exit 1; } + @command -v cargo >/dev/null 2>&1 || { echo "ERROR: cargo not installed. See CONTRIBUTING.md"; exit 1; } + @command -v pixi >/dev/null 2>&1 || { echo "ERROR: pixi not installed. See CONTRIBUTING.md"; exit 1; } + +lint: + buf lint + +breaking: + @if git rev-parse HEAD~1 >/dev/null 2>&1; then \ + buf breaking --against ".git#ref=HEAD~1"; \ + else \ + echo "No prior commit; skipping breaking-change check."; \ + fi + +generate: + buf generate + @test -d generated/python || { echo "ERROR: generated/python missing"; exit 1; } + @test -d generated/typescript || { echo "ERROR: generated/typescript missing"; exit 1; } + +rust-build: + cargo build --all-targets + +rust-test: + cargo test + +mojo-check: + @command -v pixi >/dev/null 2>&1 && pixi install --quiet && pixi run check && pixi run test \ + || echo "WARN: pixi not installed — skipping Mojo check + test (CI still gates on this)" + +ts-check: + @command -v pnpm >/dev/null 2>&1 && pnpm install --silent && pnpm typecheck \ + || echo "WARN: pnpm not installed — skipping ts typecheck" + +clean: + rm -rf generated target node_modules .pixi diff --git a/README.md b/README.md index b1fe982..649f9e1 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ # vtuber-contracts -**Build-time typed interface contracts (proto3) for the vtuber-* program — generates a Rust crate, Python typed stubs, and TypeScript declarations consumed by every other vtuber-* repo to prevent contract drift across 17 services.** +**Build-time typed interface contracts (proto3) for the vtuber-* program — generates a Rust crate, Mojo bindings (via Pixi + Python interop), and TypeScript declarations consumed by every other vtuber-* repo to prevent contract drift across 17 services.** [![CI](https://github.com/echo-layer/vtuber-contracts/actions/workflows/ci.yml/badge.svg)](https://github.com/echo-layer/vtuber-contracts/actions/workflows/ci.yml) [![Security](https://github.com/echo-layer/vtuber-contracts/actions/workflows/security.yml/badge.svg)](https://github.com/echo-layer/vtuber-contracts/actions/workflows/security.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Status](https://img.shields.io/badge/status-active-success)](./) -![Rust LOD](https://img.shields.io/badge/Rust_LOD-0-dea584.svg) ![Total LOD](https://img.shields.io/badge/Total_LOD-0-brightgreen.svg) +![Rust LOD](https://img.shields.io/badge/Rust_LOD-0-dea584.svg) ![Mojo LOD](https://img.shields.io/badge/Mojo_LOD-0-CC0000.svg) ![Total LOD](https://img.shields.io/badge/Total_LOD-0-brightgreen.svg) -[![Rust](https://img.shields.io/badge/Rust-dea584?logo=rust&logoColor=white)](./) +[![Rust](https://img.shields.io/badge/Rust-dea584?logo=rust&logoColor=white)](./) [![Mojo](https://img.shields.io/badge/Mojo-CC0000?logo=mojo&logoColor=white)](./) [![buf](https://img.shields.io/badge/buf-151C3B)](./) [![Pixi](https://img.shields.io/badge/Pixi-F4A02D)](./) @@ -19,7 +19,7 @@ [ English | [ภาษาไทย](./locales/README.th.md) | [日本語](./locales/README.ja.md) | [简体中文](./locales/README.zh.md) ] -vtuber-contracts is the build-time source of truth for all inter-service typed boundaries in the vtuber-* program. It defines proto3 schemas for messages such as ConversationDirective, VoiceProfile, and Persona, then runs codegen to publish a Rust crate, Python typed stubs (.pyi), and TypeScript declaration files consumed by every other vtuber-* repo and by the public SDK shipped through vtuber-api. +vtuber-contracts is the build-time source of truth for all inter-service typed boundaries in the vtuber-* program. It defines proto3 schemas for messages such as ConversationDirective, VoiceProfile, and Persona, then runs codegen to publish three consumer surfaces — a Rust crate (via tonic-build), a Mojo binding package (via Pixi + Python interop, see ADR-004), and TypeScript declarations (via ts-proto) — consumed by every other vtuber-* repo and by the public SDK shipped through vtuber-api. ## ✨ Features diff --git a/STRUCTURE.tree b/STRUCTURE.tree index 0078b08..fb0c992 100644 --- a/STRUCTURE.tree +++ b/STRUCTURE.tree @@ -1,35 +1,8571 @@ -/ -├── GEMINI.md -├── CLAUDE.md -├── README.md -├── STRUCTURE.tree +. ├── ARCHITECTURE.md -├── ROADMAP.md -├── CONTRIBUTING.md +├── buf.gen.yaml +├── buf.yaml +├── build.rs +├── Cargo.lock +├── Cargo.toml +├── CLAUDE.md ├── CODE_OF_CONDUCT.md -├── SECURITY.md -├── LICENSE.md +├── CONTRIBUTING.md ├── DEPLOYMENT_GUIDE.md ├── DESIGN_DECISIONS.md +├── examples +│   └── generate_golden.rs ├── FAQ.md +├── GEMINI.md +├── generated +│   ├── python +│   │   └── vtuber +│   │   └── v1 +│   │   ├── conversation_pb2.py +│   │   ├── conversation_pb2.pyi +│   │   ├── persona_pb2.py +│   │   ├── persona_pb2.pyi +│   │   ├── __pycache__ +│   │   │   ├── conversation_pb2.cpython-312.pyc +│   │   │   ├── persona_pb2.cpython-312.pyc +│   │   │   └── voice_profile_pb2.cpython-312.pyc +│   │   ├── tool_call_pb2.py +│   │   ├── tool_call_pb2.pyi +│   │   ├── voice_profile_pb2.py +│   │   └── voice_profile_pb2.pyi +│   └── typescript +│   ├── google +│   │   └── protobuf +│   │   ├── struct.ts +│   │   └── timestamp.ts +│   └── vtuber +│   └── v1 +│   ├── conversation.ts +│   ├── persona.ts +│   ├── tool_call.ts +│   └── voice_profile.ts +├── .github +│   ├── ISSUE_TEMPLATE +│   │   ├── bug_report.yml +│   │   └── feature_request.yml +│   ├── PULL_REQUEST_TEMPLATE.md +│   └── workflows +│   ├── badges.yml +│   ├── ci.yml +│   ├── pr_automation.yml +│   └── security.yml +├── .gitignore +├── golden_directive.bin ├── GOVERNANCE.md -├── SUPPORT.md -├── TROUBLESHOOTING.md -├── PHILOSOPHY.md +├── LICENSE.md +├── locales +│   ├── README.ja.md +│   ├── README.th.md +│   └── README.zh.md +├── Makefile ├── MANIFESTO.md -├── VISION.md -├── STRATEGY.md +├── mojo +│   ├── tests +│   │   ├── test_golden_roundtrip.mojo +│   │   └── test_roundtrip.mojo +│   └── vtuber_contracts.mojo +├── package.json +├── PHILOSOPHY.md +├── .pixi +│   ├── .condapackageignore +│   ├── envs +│   │   └── default +│   │   ├── bin +│   │   │   ├── 2to3 -> 2to3-3.12 +│   │   │   ├── 2to3-3.12 +│   │   │   ├── bunzip2 +│   │   │   ├── bzcat +│   │   │   ├── bzcmp -> bzdiff +│   │   │   ├── bzdiff +│   │   │   ├── bzegrep -> bzgrep +│   │   │   ├── bzfgrep -> bzgrep +│   │   │   ├── bzgrep +│   │   │   ├── bzip2 +│   │   │   ├── bzip2recover +│   │   │   ├── bzless -> bzmore +│   │   │   ├── bzmore +│   │   │   ├── captoinfo -> tic +│   │   │   ├── clear +│   │   │   ├── compile_et +│   │   │   ├── c_rehash +│   │   │   ├── curve_keygen +│   │   │   ├── derb +│   │   │   ├── genbrk +│   │   │   ├── gencfu +│   │   │   ├── gencnval +│   │   │   ├── gendict +│   │   │   ├── genrb +│   │   │   ├── gpu-query +│   │   │   ├── gss-client +│   │   │   ├── icu-config +│   │   │   ├── icuexportdata +│   │   │   ├── icuinfo +│   │   │   ├── idle3 -> idle3.12 +│   │   │   ├── idle3.12 +│   │   │   ├── infocmp +│   │   │   ├── infotocap -> tic +│   │   │   ├── jupyter +│   │   │   ├── jupyter-kernel +│   │   │   ├── jupyter-kernelspec +│   │   │   ├── jupyter-migrate +│   │   │   ├── jupyter-run +│   │   │   ├── jupyter-troubleshoot +│   │   │   ├── k5srvutil +│   │   │   ├── kadmin +│   │   │   ├── kdestroy +│   │   │   ├── keyctl +│   │   │   ├── kinit +│   │   │   ├── klist +│   │   │   ├── kpasswd +│   │   │   ├── krb5-config +│   │   │   ├── ksu +│   │   │   ├── kswitch +│   │   │   ├── ktutil +│   │   │   ├── kvno +│   │   │   ├── lld +│   │   │   ├── lldb-argdumper +│   │   │   ├── lldb-server +│   │   │   ├── llvm-symbolizer +│   │   │   ├── makeconv +│   │   │   ├── mblack +│   │   │   ├── modular-crashpad-handler +│   │   │   ├── mojo +│   │   │   ├── mojo-lldb +│   │   │   ├── _mojo-lldb-dap +│   │   │   ├── mojo-lldb-dap +│   │   │   ├── mojo-lsp-server +│   │   │   ├── ncurses6-config +│   │   │   ├── ncursesw6-config +│   │   │   ├── openssl +│   │   │   ├── pkgdata +│   │   │   ├── protoc-gen-mypy +│   │   │   ├── protoc-gen-mypy_grpc +│   │   │   ├── pydoc -> pydoc3.12 +│   │   │   ├── pydoc3 -> pydoc3.12 +│   │   │   ├── pydoc3.12 +│   │   │   ├── python -> python3.12 +│   │   │   ├── python3 -> python3.12 +│   │   │   ├── python3.1 -> python3.12 +│   │   │   ├── python3.12 +│   │   │   ├── python3.12-config +│   │   │   ├── python3-config -> python3.12-config +│   │   │   ├── reset -> tset +│   │   │   ├── sclient +│   │   │   ├── sim_client +│   │   │   ├── sqlite3_analyzer +│   │   │   ├── tabs +│   │   │   ├── tclsh -> tclsh8.6 +│   │   │   ├── tclsh8.6 +│   │   │   ├── tic +│   │   │   ├── toe +│   │   │   ├── tput +│   │   │   ├── tset +│   │   │   ├── unzstd -> zstd +│   │   │   ├── uuclient +│   │   │   ├── wish -> wish8.6 +│   │   │   ├── wish8.6 +│   │   │   ├── x86_64-conda-linux-gnu-ld +│   │   │   ├── zstd +│   │   │   ├── zstdcat -> zstd +│   │   │   ├── zstdgrep +│   │   │   ├── zstdless +│   │   │   └── zstdmt -> zstd +│   │   ├── CACHEDIR.TAG +│   │   ├── compiler_compat +│   │   │   ├── ld -> ../bin/x86_64-conda-linux-gnu-ld +│   │   │   └── README +│   │   ├── conda-meta +│   │   │   ├── bzip2-1.0.8-hda65f42_9.json +│   │   │   ├── ca-certificates-2026.4.22-hbd8a1cb_0.json +│   │   │   ├── click-8.3.3-pyhc90fa1f_0.json +│   │   │   ├── cpython-3.12.13-py312hd8ed1ab_0.json +│   │   │   ├── history +│   │   │   ├── icu-78.3-h33c6efd_0.json +│   │   │   ├── importlib-metadata-8.8.0-pyhcf101f3_0.json +│   │   │   ├── jupyter_client-8.6.3-pyhd8ed1ab_1.json +│   │   │   ├── jupyter_core-5.9.1-pyhc90fa1f_0.json +│   │   │   ├── keyutils-1.6.3-hb9d3cd8_0.json +│   │   │   ├── krb5-1.22.2-ha1258a1_0.json +│   │   │   ├── ld_impl_linux-64-2.45.1-default_hbd61a6d_102.json +│   │   │   ├── libedit-3.1.20250104-pl5321h7949ede_0.json +│   │   │   ├── libexpat-2.7.5-hecca717_0.json +│   │   │   ├── libffi-3.5.2-h3435931_0.json +│   │   │   ├── libgcc-15.2.0-he0feb66_18.json +│   │   │   ├── libgcc-ng-15.2.0-h69a702a_18.json +│   │   │   ├── libgomp-15.2.0-he0feb66_18.json +│   │   │   ├── liblzma-5.8.3-hb03c661_0.json +│   │   │   ├── libnsl-2.0.1-hb9d3cd8_1.json +│   │   │   ├── libsodium-1.0.21-h280c20c_3.json +│   │   │   ├── libsqlite-3.53.0-hf4e2dac_0.json +│   │   │   ├── libstdcxx-15.2.0-h934c35e_18.json +│   │   │   ├── libuuid-2.42-h5347b49_0.json +│   │   │   ├── libxcrypt-4.4.36-hd590300_1.json +│   │   │   ├── libzlib-1.3.2-h25fd6f3_2.json +│   │   │   ├── mblack-26.3.0.dev2026042817-release.json +│   │   │   ├── mojo-1.0.0b1.dev2026042817-release.json +│   │   │   ├── mojo-compiler-1.0.0b1.dev2026042817-release.json +│   │   │   ├── mojo-python-1.0.0b1.dev2026042817-release.json +│   │   │   ├── mypy_extensions-1.1.0-pyha770c72_0.json +│   │   │   ├── ncurses-6.6-hdb14827_0.json +│   │   │   ├── _openmp_mutex-4.5-20_gnu.json +│   │   │   ├── openssl-3.6.2-h35e630c_0.json +│   │   │   ├── packaging-26.2-pyhc364b38_0.json +│   │   │   ├── pathspec-1.1.1-pyhd8ed1ab_0.json +│   │   │   ├── pixi +│   │   │   ├── pixi_env_prefix +│   │   │   ├── platformdirs-4.9.6-pyhcf101f3_0.json +│   │   │   ├── python-3.12.13-hd63d673_0_cpython.json +│   │   │   ├── python_abi-3.12-8_cp312.json +│   │   │   ├── _python_abi3_support-1.0-hd8ed1ab_2.json +│   │   │   ├── python-dateutil-2.9.0.post0-pyhe01879c_2.json +│   │   │   ├── python-gil-3.12.13-hd8ed1ab_0.json +│   │   │   ├── pyzmq-27.1.0-py312hda471dd_2.json +│   │   │   ├── readline-8.3-h853b02a_0.json +│   │   │   ├── six-1.17.0-pyhe01879c_1.json +│   │   │   ├── tk-8.6.13-noxft_h366c992_103.json +│   │   │   ├── tomli-2.4.1-pyhcf101f3_0.json +│   │   │   ├── tornado-6.5.5-py312h4c3975b_0.json +│   │   │   ├── traitlets-5.14.3-pyhd8ed1ab_1.json +│   │   │   ├── tzdata-2025c-hc9c84f9_1.json +│   │   │   ├── zeromq-4.3.5-h41580af_10.json +│   │   │   ├── zipp-3.23.1-pyhcf101f3_0.json +│   │   │   └── zstd-1.5.7-hb78ec9c_6.json +│   │   ├── etc +│   │   │   ├── conda +│   │   │   │   ├── activate.d +│   │   │   │   │   └── 10-activate-max.sh +│   │   │   │   └── test-files +│   │   │   │   ├── jupyter_core +│   │   │   │   │   └── 1 +│   │   │   │   │   ├── pyproject.toml +│   │   │   │   │   ├── run_test.py +│   │   │   │   │   └── tests +│   │   │   │   │   ├── dotipython +│   │   │   │   │   │   ├── nbextensions +│   │   │   │   │   │   │   └── myext.js +│   │   │   │   │   │   └── profile_default +│   │   │   │   │   │   ├── ipython_config.py +│   │   │   │   │   │   ├── ipython_console_config.py +│   │   │   │   │   │   ├── ipython_kernel_config.py +│   │   │   │   │   │   ├── ipython_nbconvert_config.py +│   │   │   │   │   │   ├── ipython_notebook_config.py +│   │   │   │   │   │   └── static +│   │   │   │   │   │   └── custom +│   │   │   │   │   │   ├── custom.css +│   │   │   │   │   │   └── custom.js +│   │   │   │   │   ├── dotipython_empty +│   │   │   │   │   │   └── profile_default +│   │   │   │   │   │   ├── ipython_config.py +│   │   │   │   │   │   ├── ipython_console_config.py +│   │   │   │   │   │   ├── ipython_kernel_config.py +│   │   │   │   │   │   ├── ipython_nbconvert_config.py +│   │   │   │   │   │   ├── ipython_notebook_config.py +│   │   │   │   │   │   └── static +│   │   │   │   │   │   └── custom +│   │   │   │   │   │   ├── custom.css +│   │   │   │   │   │   └── custom.js +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── mocking.py +│   │   │   │   │   ├── test_application.py +│   │   │   │   │   ├── test_command.py +│   │   │   │   │   ├── test_migrate.py +│   │   │   │   │   ├── test_paths.py +│   │   │   │   │   ├── test_troubleshoot.py +│   │   │   │   │   └── test_utils.py +│   │   │   │   ├── libsodium +│   │   │   │   │   └── 0 +│   │   │   │   │   └── test +│   │   │   │   │   ├── CMakeLists.txt +│   │   │   │   │   └── test_version.c +│   │   │   │   ├── pyzmq +│   │   │   │   │   ├── 1 +│   │   │   │   │   │   └── tests +│   │   │   │   │   │   └── test_pyzmq.py +│   │   │   │   │   ├── 3 +│   │   │   │   │   │   └── tests +│   │   │   │   │   │   └── test_pyzmq.py +│   │   │   │   │   └── 4 +│   │   │   │   │   └── tests +│   │   │   │   │   └── test_pyzmq.py +│   │   │   │   ├── zeromq +│   │   │   │   │   └── 0 +│   │   │   │   │   └── tests +│   │   │   │   │   ├── CMakeLists.txt +│   │   │   │   │   └── test_has.c +│   │   │   │   ├── zipp +│   │   │   │   │   └── 1 +│   │   │   │   │   └── tests +│   │   │   │   │   ├── compat +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── py310.py +│   │   │   │   │   │   ├── py313.py +│   │   │   │   │   │   ├── py38.py +│   │   │   │   │   │   └── py39.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── _support.py +│   │   │   │   │   ├── test_complexity.py +│   │   │   │   │   ├── _test_params.py +│   │   │   │   │   ├── test_path.py +│   │   │   │   │   └── write-alpharep.py +│   │   │   │   └── zstd +│   │   │   │   └── 1 +│   │   │   │   └── cf_test +│   │   │   │   └── CMakeLists.txt +│   │   │   └── request-key.conf +│   │   ├── include +│   │   │   ├── bzlib.h +│   │   │   ├── com_err.h +│   │   │   ├── crypt.h +│   │   │   ├── cursesapp.h +│   │   │   ├── cursesf.h +│   │   │   ├── curses.h +│   │   │   ├── cursesm.h +│   │   │   ├── cursesp.h +│   │   │   ├── cursesw.h +│   │   │   ├── cursslk.h +│   │   │   ├── default.h +│   │   │   ├── editline +│   │   │   │   └── readline.h +│   │   │   ├── eti.h +│   │   │   ├── etip.h +│   │   │   ├── fakemysql.h +│   │   │   ├── fakepq.h +│   │   │   ├── fakesql.h +│   │   │   ├── ffi.h +│   │   │   ├── ffitarget.h +│   │   │   ├── form.h +│   │   │   ├── gssapi +│   │   │   │   ├── gssapi_alloc.h +│   │   │   │   ├── gssapi_ext.h +│   │   │   │   ├── gssapi_generic.h +│   │   │   │   ├── gssapi.h +│   │   │   │   ├── gssapi_krb5.h +│   │   │   │   └── mechglue.h +│   │   │   ├── gssapi.h +│   │   │   ├── gssrpc +│   │   │   │   ├── auth_gssapi.h +│   │   │   │   ├── auth_gss.h +│   │   │   │   ├── auth.h +│   │   │   │   ├── auth_unix.h +│   │   │   │   ├── clnt.h +│   │   │   │   ├── netdb.h +│   │   │   │   ├── pmap_clnt.h +│   │   │   │   ├── pmap_prot.h +│   │   │   │   ├── pmap_rmt.h +│   │   │   │   ├── rename.h +│   │   │   │   ├── rpc.h +│   │   │   │   ├── rpc_msg.h +│   │   │   │   ├── svc_auth.h +│   │   │   │   ├── svc.h +│   │   │   │   ├── types.h +│   │   │   │   └── xdr.h +│   │   │   ├── histedit.h +│   │   │   ├── itcl2TclOO.h +│   │   │   ├── itclDecls.h +│   │   │   ├── itcl.h +│   │   │   ├── itclIntDecls.h +│   │   │   ├── itclInt.h +│   │   │   ├── itclMigrate2TclCore.h +│   │   │   ├── itclTclIntStubsFcn.h +│   │   │   ├── kadm5 +│   │   │   │   ├── admin.h +│   │   │   │   ├── chpass_util_strings.h +│   │   │   │   └── kadm_err.h +│   │   │   ├── kdb.h +│   │   │   ├── keyutils.h +│   │   │   ├── krad.h +│   │   │   ├── krb5 +│   │   │   │   ├── ccselect_plugin.h +│   │   │   │   ├── certauth_plugin.h +│   │   │   │   ├── clpreauth_plugin.h +│   │   │   │   ├── hostrealm_plugin.h +│   │   │   │   ├── kadm5_auth_plugin.h +│   │   │   │   ├── kadm5_hook_plugin.h +│   │   │   │   ├── kdcpolicy_plugin.h +│   │   │   │   ├── kdcpreauth_plugin.h +│   │   │   │   ├── krb5.h +│   │   │   │   ├── localauth_plugin.h +│   │   │   │   ├── locate_plugin.h +│   │   │   │   ├── plugin.h +│   │   │   │   ├── preauth_plugin.h +│   │   │   │   └── pwqual_plugin.h +│   │   │   ├── krb5.h +│   │   │   ├── ks_names.h +│   │   │   ├── menu.h +│   │   │   ├── mysqlStubs.h +│   │   │   ├── ncurses +│   │   │   │   ├── cursesapp.h -> ../cursesapp.h +│   │   │   │   ├── cursesf.h -> ../cursesf.h +│   │   │   │   ├── curses.h -> ../curses.h +│   │   │   │   ├── cursesm.h -> ../cursesm.h +│   │   │   │   ├── cursesp.h -> ../cursesp.h +│   │   │   │   ├── cursesw.h -> ../cursesw.h +│   │   │   │   ├── cursslk.h -> ../cursslk.h +│   │   │   │   ├── eti.h -> ../eti.h +│   │   │   │   ├── etip.h -> ../etip.h +│   │   │   │   ├── form.h -> ../form.h +│   │   │   │   ├── menu.h -> ../menu.h +│   │   │   │   ├── ncurses_dll.h -> ../ncurses_dll.h +│   │   │   │   ├── ncurses.h -> ../curses.h +│   │   │   │   ├── panel.h -> ../panel.h +│   │   │   │   ├── termcap.h -> ../termcap.h +│   │   │   │   ├── term_entry.h -> ../term_entry.h +│   │   │   │   ├── term.h -> ../term.h +│   │   │   │   └── unctrl.h -> ../unctrl.h +│   │   │   ├── ncurses_dll.h +│   │   │   ├── ncurses.h -> curses.h +│   │   │   ├── ncursesw +│   │   │   │   ├── cursesapp.h -> ../cursesapp.h +│   │   │   │   ├── cursesf.h -> ../cursesf.h +│   │   │   │   ├── curses.h -> ../curses.h +│   │   │   │   ├── cursesm.h -> ../cursesm.h +│   │   │   │   ├── cursesp.h -> ../cursesp.h +│   │   │   │   ├── cursesw.h -> ../cursesw.h +│   │   │   │   ├── cursslk.h -> ../cursslk.h +│   │   │   │   ├── eti.h -> ../eti.h +│   │   │   │   ├── etip.h -> ../etip.h +│   │   │   │   ├── form.h -> ../form.h +│   │   │   │   ├── menu.h -> ../menu.h +│   │   │   │   ├── ncurses_dll.h -> ../ncurses_dll.h +│   │   │   │   ├── ncurses.h -> ../curses.h +│   │   │   │   ├── panel.h -> ../panel.h +│   │   │   │   ├── termcap.h -> ../termcap.h +│   │   │   │   ├── term_entry.h -> ../term_entry.h +│   │   │   │   ├── term.h -> ../term.h +│   │   │   │   └── unctrl.h -> ../unctrl.h +│   │   │   ├── odbcStubs.h +│   │   │   ├── openssl +│   │   │   │   ├── aes.h +│   │   │   │   ├── asn1err.h +│   │   │   │   ├── asn1.h +│   │   │   │   ├── asn1t.h +│   │   │   │   ├── asyncerr.h +│   │   │   │   ├── async.h +│   │   │   │   ├── bioerr.h +│   │   │   │   ├── bio.h +│   │   │   │   ├── blowfish.h +│   │   │   │   ├── bnerr.h +│   │   │   │   ├── bn.h +│   │   │   │   ├── buffererr.h +│   │   │   │   ├── buffer.h +│   │   │   │   ├── byteorder.h +│   │   │   │   ├── camellia.h +│   │   │   │   ├── cast.h +│   │   │   │   ├── cmac.h +│   │   │   │   ├── cmperr.h +│   │   │   │   ├── cmp.h +│   │   │   │   ├── cmp_util.h +│   │   │   │   ├── cmserr.h +│   │   │   │   ├── cms.h +│   │   │   │   ├── comperr.h +│   │   │   │   ├── comp.h +│   │   │   │   ├── conf_api.h +│   │   │   │   ├── conferr.h +│   │   │   │   ├── conf.h +│   │   │   │   ├── configuration.h +│   │   │   │   ├── conftypes.h +│   │   │   │   ├── core_dispatch.h +│   │   │   │   ├── core.h +│   │   │   │   ├── core_names.h +│   │   │   │   ├── core_object.h +│   │   │   │   ├── crmferr.h +│   │   │   │   ├── crmf.h +│   │   │   │   ├── cryptoerr.h +│   │   │   │   ├── cryptoerr_legacy.h +│   │   │   │   ├── crypto.h +│   │   │   │   ├── cterr.h +│   │   │   │   ├── ct.h +│   │   │   │   ├── decodererr.h +│   │   │   │   ├── decoder.h +│   │   │   │   ├── des.h +│   │   │   │   ├── dherr.h +│   │   │   │   ├── dh.h +│   │   │   │   ├── dsaerr.h +│   │   │   │   ├── dsa.h +│   │   │   │   ├── dtls1.h +│   │   │   │   ├── ebcdic.h +│   │   │   │   ├── ecdh.h +│   │   │   │   ├── ecdsa.h +│   │   │   │   ├── ecerr.h +│   │   │   │   ├── ec.h +│   │   │   │   ├── encodererr.h +│   │   │   │   ├── encoder.h +│   │   │   │   ├── engineerr.h +│   │   │   │   ├── engine.h +│   │   │   │   ├── e_os2.h +│   │   │   │   ├── e_ostime.h +│   │   │   │   ├── err.h +│   │   │   │   ├── esserr.h +│   │   │   │   ├── ess.h +│   │   │   │   ├── evperr.h +│   │   │   │   ├── evp.h +│   │   │   │   ├── fipskey.h +│   │   │   │   ├── fips_names.h +│   │   │   │   ├── hmac.h +│   │   │   │   ├── hpke.h +│   │   │   │   ├── httperr.h +│   │   │   │   ├── http.h +│   │   │   │   ├── idea.h +│   │   │   │   ├── indicator.h +│   │   │   │   ├── kdferr.h +│   │   │   │   ├── kdf.h +│   │   │   │   ├── lhash.h +│   │   │   │   ├── macros.h +│   │   │   │   ├── md2.h +│   │   │   │   ├── md4.h +│   │   │   │   ├── md5.h +│   │   │   │   ├── mdc2.h +│   │   │   │   ├── ml_kem.h +│   │   │   │   ├── modes.h +│   │   │   │   ├── objectserr.h +│   │   │   │   ├── objects.h +│   │   │   │   ├── obj_mac.h +│   │   │   │   ├── ocsperr.h +│   │   │   │   ├── ocsp.h +│   │   │   │   ├── opensslconf.h +│   │   │   │   ├── opensslv.h +│   │   │   │   ├── ossl_typ.h +│   │   │   │   ├── param_build.h +│   │   │   │   ├── params.h +│   │   │   │   ├── pem2.h +│   │   │   │   ├── pemerr.h +│   │   │   │   ├── pem.h +│   │   │   │   ├── pkcs12err.h +│   │   │   │   ├── pkcs12.h +│   │   │   │   ├── pkcs7err.h +│   │   │   │   ├── pkcs7.h +│   │   │   │   ├── proverr.h +│   │   │   │   ├── provider.h +│   │   │   │   ├── prov_ssl.h +│   │   │   │   ├── quic.h +│   │   │   │   ├── randerr.h +│   │   │   │   ├── rand.h +│   │   │   │   ├── rc2.h +│   │   │   │   ├── rc4.h +│   │   │   │   ├── rc5.h +│   │   │   │   ├── ripemd.h +│   │   │   │   ├── rsaerr.h +│   │   │   │   ├── rsa.h +│   │   │   │   ├── safestack.h +│   │   │   │   ├── seed.h +│   │   │   │   ├── self_test.h +│   │   │   │   ├── sha.h +│   │   │   │   ├── srp.h +│   │   │   │   ├── srtp.h +│   │   │   │   ├── ssl2.h +│   │   │   │   ├── ssl3.h +│   │   │   │   ├── sslerr.h +│   │   │   │   ├── sslerr_legacy.h +│   │   │   │   ├── ssl.h +│   │   │   │   ├── stack.h +│   │   │   │   ├── storeerr.h +│   │   │   │   ├── store.h +│   │   │   │   ├── symhacks.h +│   │   │   │   ├── thread.h +│   │   │   │   ├── tls1.h +│   │   │   │   ├── trace.h +│   │   │   │   ├── tserr.h +│   │   │   │   ├── ts.h +│   │   │   │   ├── txt_db.h +│   │   │   │   ├── types.h +│   │   │   │   ├── uierr.h +│   │   │   │   ├── ui.h +│   │   │   │   ├── whrlpool.h +│   │   │   │   ├── x509_acert.h +│   │   │   │   ├── x509err.h +│   │   │   │   ├── x509.h +│   │   │   │   ├── x509v3err.h +│   │   │   │   ├── x509v3.h +│   │   │   │   └── x509_vfy.h +│   │   │   ├── panel.h +│   │   │   ├── pqStubs.h +│   │   │   ├── profile.h +│   │   │   ├── python3.12 +│   │   │   │   ├── abstract.h +│   │   │   │   ├── bltinmodule.h +│   │   │   │   ├── boolobject.h +│   │   │   │   ├── bytearrayobject.h +│   │   │   │   ├── bytesobject.h +│   │   │   │   ├── ceval.h +│   │   │   │   ├── codecs.h +│   │   │   │   ├── compile.h +│   │   │   │   ├── complexobject.h +│   │   │   │   ├── cpython +│   │   │   │   │   ├── abstract.h +│   │   │   │   │   ├── bytearrayobject.h +│   │   │   │   │   ├── bytesobject.h +│   │   │   │   │   ├── cellobject.h +│   │   │   │   │   ├── ceval.h +│   │   │   │   │   ├── classobject.h +│   │   │   │   │   ├── code.h +│   │   │   │   │   ├── compile.h +│   │   │   │   │   ├── complexobject.h +│   │   │   │   │   ├── context.h +│   │   │   │   │   ├── descrobject.h +│   │   │   │   │   ├── dictobject.h +│   │   │   │   │   ├── fileobject.h +│   │   │   │   │   ├── fileutils.h +│   │   │   │   │   ├── floatobject.h +│   │   │   │   │   ├── frameobject.h +│   │   │   │   │   ├── funcobject.h +│   │   │   │   │   ├── genobject.h +│   │   │   │   │   ├── import.h +│   │   │   │   │   ├── initconfig.h +│   │   │   │   │   ├── interpreteridobject.h +│   │   │   │   │   ├── listobject.h +│   │   │   │   │   ├── longintrepr.h +│   │   │   │   │   ├── longobject.h +│   │   │   │   │   ├── memoryobject.h +│   │   │   │   │   ├── methodobject.h +│   │   │   │   │   ├── modsupport.h +│   │   │   │   │   ├── object.h +│   │   │   │   │   ├── objimpl.h +│   │   │   │   │   ├── odictobject.h +│   │   │   │   │   ├── picklebufobject.h +│   │   │   │   │   ├── pthread_stubs.h +│   │   │   │   │   ├── pyctype.h +│   │   │   │   │   ├── pydebug.h +│   │   │   │   │   ├── pyerrors.h +│   │   │   │   │   ├── pyfpe.h +│   │   │   │   │   ├── pyframe.h +│   │   │   │   │   ├── pylifecycle.h +│   │   │   │   │   ├── pymem.h +│   │   │   │   │   ├── pystate.h +│   │   │   │   │   ├── pythonrun.h +│   │   │   │   │   ├── pythread.h +│   │   │   │   │   ├── pytime.h +│   │   │   │   │   ├── setobject.h +│   │   │   │   │   ├── sysmodule.h +│   │   │   │   │   ├── traceback.h +│   │   │   │   │   ├── tupleobject.h +│   │   │   │   │   ├── unicodeobject.h +│   │   │   │   │   ├── warnings.h +│   │   │   │   │   └── weakrefobject.h +│   │   │   │   ├── datetime.h +│   │   │   │   ├── descrobject.h +│   │   │   │   ├── dictobject.h +│   │   │   │   ├── dynamic_annotations.h +│   │   │   │   ├── enumobject.h +│   │   │   │   ├── errcode.h +│   │   │   │   ├── exports.h +│   │   │   │   ├── fileobject.h +│   │   │   │   ├── fileutils.h +│   │   │   │   ├── floatobject.h +│   │   │   │   ├── frameobject.h +│   │   │   │   ├── genericaliasobject.h +│   │   │   │   ├── import.h +│   │   │   │   ├── internal +│   │   │   │   │   ├── pycore_abstract.h +│   │   │   │   │   ├── pycore_asdl.h +│   │   │   │   │   ├── pycore_ast.h +│   │   │   │   │   ├── pycore_ast_state.h +│   │   │   │   │   ├── pycore_atexit.h +│   │   │   │   │   ├── pycore_atomic_funcs.h +│   │   │   │   │   ├── pycore_atomic.h +│   │   │   │   │   ├── pycore_bitutils.h +│   │   │   │   │   ├── pycore_blocks_output_buffer.h +│   │   │   │   │   ├── pycore_bytes_methods.h +│   │   │   │   │   ├── pycore_bytesobject.h +│   │   │   │   │   ├── pycore_call.h +│   │   │   │   │   ├── pycore_ceval.h +│   │   │   │   │   ├── pycore_ceval_state.h +│   │   │   │   │   ├── pycore_code.h +│   │   │   │   │   ├── pycore_compile.h +│   │   │   │   │   ├── pycore_condvar.h +│   │   │   │   │   ├── pycore_context.h +│   │   │   │   │   ├── pycore_descrobject.h +│   │   │   │   │   ├── pycore_dict.h +│   │   │   │   │   ├── pycore_dict_state.h +│   │   │   │   │   ├── pycore_dtoa.h +│   │   │   │   │   ├── pycore_emscripten_signal.h +│   │   │   │   │   ├── pycore_exceptions.h +│   │   │   │   │   ├── pycore_faulthandler.h +│   │   │   │   │   ├── pycore_fileutils.h +│   │   │   │   │   ├── pycore_fileutils_windows.h +│   │   │   │   │   ├── pycore_floatobject.h +│   │   │   │   │   ├── pycore_flowgraph.h +│   │   │   │   │   ├── pycore_format.h +│   │   │   │   │   ├── pycore_frame.h +│   │   │   │   │   ├── pycore_function.h +│   │   │   │   │   ├── pycore_gc.h +│   │   │   │   │   ├── pycore_genobject.h +│   │   │   │   │   ├── pycore_getopt.h +│   │   │   │   │   ├── pycore_gil.h +│   │   │   │   │   ├── pycore_global_objects_fini_generated.h +│   │   │   │   │   ├── pycore_global_objects.h +│   │   │   │   │   ├── pycore_global_strings.h +│   │   │   │   │   ├── pycore_hamt.h +│   │   │   │   │   ├── pycore_hashtable.h +│   │   │   │   │   ├── pycore_import.h +│   │   │   │   │   ├── pycore_initconfig.h +│   │   │   │   │   ├── pycore_instruments.h +│   │   │   │   │   ├── pycore_interp.h +│   │   │   │   │   ├── pycore_intrinsics.h +│   │   │   │   │   ├── pycore_list.h +│   │   │   │   │   ├── pycore_long.h +│   │   │   │   │   ├── pycore_memoryobject.h +│   │   │   │   │   ├── pycore_moduleobject.h +│   │   │   │   │   ├── pycore_namespace.h +│   │   │   │   │   ├── pycore_object.h +│   │   │   │   │   ├── pycore_object_state.h +│   │   │   │   │   ├── pycore_obmalloc.h +│   │   │   │   │   ├── pycore_obmalloc_init.h +│   │   │   │   │   ├── pycore_opcode.h +│   │   │   │   │   ├── pycore_opcode_utils.h +│   │   │   │   │   ├── pycore_parser.h +│   │   │   │   │   ├── pycore_pathconfig.h +│   │   │   │   │   ├── pycore_pyarena.h +│   │   │   │   │   ├── pycore_pyerrors.h +│   │   │   │   │   ├── pycore_pyhash.h +│   │   │   │   │   ├── pycore_pylifecycle.h +│   │   │   │   │   ├── pycore_pymath.h +│   │   │   │   │   ├── pycore_pymem.h +│   │   │   │   │   ├── pycore_pymem_init.h +│   │   │   │   │   ├── pycore_pystate.h +│   │   │   │   │   ├── pycore_pythread.h +│   │   │   │   │   ├── pycore_range.h +│   │   │   │   │   ├── pycore_runtime.h +│   │   │   │   │   ├── pycore_runtime_init_generated.h +│   │   │   │   │   ├── pycore_runtime_init.h +│   │   │   │   │   ├── pycore_signal.h +│   │   │   │   │   ├── pycore_sliceobject.h +│   │   │   │   │   ├── pycore_strhex.h +│   │   │   │   │   ├── pycore_structseq.h +│   │   │   │   │   ├── pycore_symtable.h +│   │   │   │   │   ├── pycore_sysmodule.h +│   │   │   │   │   ├── pycore_time.h +│   │   │   │   │   ├── pycore_token.h +│   │   │   │   │   ├── pycore_traceback.h +│   │   │   │   │   ├── pycore_tracemalloc.h +│   │   │   │   │   ├── pycore_tuple.h +│   │   │   │   │   ├── pycore_typeobject.h +│   │   │   │   │   ├── pycore_typevarobject.h +│   │   │   │   │   ├── pycore_ucnhash.h +│   │   │   │   │   ├── pycore_unicodeobject_generated.h +│   │   │   │   │   ├── pycore_unicodeobject.h +│   │   │   │   │   ├── pycore_unionobject.h +│   │   │   │   │   └── pycore_warnings.h +│   │   │   │   ├── interpreteridobject.h +│   │   │   │   ├── intrcheck.h +│   │   │   │   ├── iterobject.h +│   │   │   │   ├── listobject.h +│   │   │   │   ├── longobject.h +│   │   │   │   ├── marshal.h +│   │   │   │   ├── memoryobject.h +│   │   │   │   ├── methodobject.h +│   │   │   │   ├── modsupport.h +│   │   │   │   ├── moduleobject.h +│   │   │   │   ├── object.h +│   │   │   │   ├── objimpl.h +│   │   │   │   ├── opcode.h +│   │   │   │   ├── osdefs.h +│   │   │   │   ├── osmodule.h +│   │   │   │   ├── patchlevel.h +│   │   │   │   ├── pybuffer.h +│   │   │   │   ├── pycapsule.h +│   │   │   │   ├── pyconfig.h +│   │   │   │   ├── py_curses.h +│   │   │   │   ├── pydtrace.h +│   │   │   │   ├── pyerrors.h +│   │   │   │   ├── pyexpat.h +│   │   │   │   ├── pyframe.h +│   │   │   │   ├── pyhash.h +│   │   │   │   ├── pylifecycle.h +│   │   │   │   ├── pymacconfig.h +│   │   │   │   ├── pymacro.h +│   │   │   │   ├── pymath.h +│   │   │   │   ├── pymem.h +│   │   │   │   ├── pyport.h +│   │   │   │   ├── pystate.h +│   │   │   │   ├── pystats.h +│   │   │   │   ├── pystrcmp.h +│   │   │   │   ├── pystrtod.h +│   │   │   │   ├── Python.h +│   │   │   │   ├── pythonrun.h +│   │   │   │   ├── pythread.h +│   │   │   │   ├── pytypedefs.h +│   │   │   │   ├── rangeobject.h +│   │   │   │   ├── setobject.h +│   │   │   │   ├── sliceobject.h +│   │   │   │   ├── structmember.h +│   │   │   │   ├── structseq.h +│   │   │   │   ├── sysmodule.h +│   │   │   │   ├── traceback.h +│   │   │   │   ├── tracemalloc.h +│   │   │   │   ├── tupleobject.h +│   │   │   │   ├── typeslots.h +│   │   │   │   ├── unicodeobject.h +│   │   │   │   ├── warnings.h +│   │   │   │   └── weakrefobject.h +│   │   │   ├── readline +│   │   │   │   ├── chardefs.h +│   │   │   │   ├── history.h +│   │   │   │   ├── keymaps.h +│   │   │   │   ├── readline.h +│   │   │   │   ├── rlconf.h +│   │   │   │   ├── rlstdc.h +│   │   │   │   ├── rltypedefs.h +│   │   │   │   └── tilde.h +│   │   │   ├── rpcsvc +│   │   │   │   ├── ypclnt.h +│   │   │   │   ├── yp.h +│   │   │   │   ├── yppasswd.h +│   │   │   │   ├── yppasswd.x +│   │   │   │   ├── yp_prot.h +│   │   │   │   ├── ypupd.h +│   │   │   │   └── yp.x +│   │   │   ├── sodium +│   │   │   │   ├── core.h +│   │   │   │   ├── crypto_aead_aegis128l.h +│   │   │   │   ├── crypto_aead_aegis256.h +│   │   │   │   ├── crypto_aead_aes256gcm.h +│   │   │   │   ├── crypto_aead_chacha20poly1305.h +│   │   │   │   ├── crypto_aead_xchacha20poly1305.h +│   │   │   │   ├── crypto_auth.h +│   │   │   │   ├── crypto_auth_hmacsha256.h +│   │   │   │   ├── crypto_auth_hmacsha512256.h +│   │   │   │   ├── crypto_auth_hmacsha512.h +│   │   │   │   ├── crypto_box_curve25519xchacha20poly1305.h +│   │   │   │   ├── crypto_box_curve25519xsalsa20poly1305.h +│   │   │   │   ├── crypto_box.h +│   │   │   │   ├── crypto_core_ed25519.h +│   │   │   │   ├── crypto_core_hchacha20.h +│   │   │   │   ├── crypto_core_hsalsa20.h +│   │   │   │   ├── crypto_core_keccak1600.h +│   │   │   │   ├── crypto_core_ristretto255.h +│   │   │   │   ├── crypto_core_salsa2012.h +│   │   │   │   ├── crypto_core_salsa208.h +│   │   │   │   ├── crypto_core_salsa20.h +│   │   │   │   ├── crypto_generichash_blake2b.h +│   │   │   │   ├── crypto_generichash.h +│   │   │   │   ├── crypto_hash.h +│   │   │   │   ├── crypto_hash_sha256.h +│   │   │   │   ├── crypto_hash_sha512.h +│   │   │   │   ├── crypto_ipcrypt.h +│   │   │   │   ├── crypto_kdf_blake2b.h +│   │   │   │   ├── crypto_kdf.h +│   │   │   │   ├── crypto_kdf_hkdf_sha256.h +│   │   │   │   ├── crypto_kdf_hkdf_sha512.h +│   │   │   │   ├── crypto_kx.h +│   │   │   │   ├── crypto_onetimeauth.h +│   │   │   │   ├── crypto_onetimeauth_poly1305.h +│   │   │   │   ├── crypto_pwhash_argon2id.h +│   │   │   │   ├── crypto_pwhash_argon2i.h +│   │   │   │   ├── crypto_pwhash.h +│   │   │   │   ├── crypto_pwhash_scryptsalsa208sha256.h +│   │   │   │   ├── crypto_scalarmult_curve25519.h +│   │   │   │   ├── crypto_scalarmult_ed25519.h +│   │   │   │   ├── crypto_scalarmult.h +│   │   │   │   ├── crypto_scalarmult_ristretto255.h +│   │   │   │   ├── crypto_secretbox.h +│   │   │   │   ├── crypto_secretbox_xchacha20poly1305.h +│   │   │   │   ├── crypto_secretbox_xsalsa20poly1305.h +│   │   │   │   ├── crypto_secretstream_xchacha20poly1305.h +│   │   │   │   ├── crypto_shorthash.h +│   │   │   │   ├── crypto_shorthash_siphash24.h +│   │   │   │   ├── crypto_sign_ed25519.h +│   │   │   │   ├── crypto_sign_edwards25519sha512batch.h +│   │   │   │   ├── crypto_sign.h +│   │   │   │   ├── crypto_stream_chacha20.h +│   │   │   │   ├── crypto_stream.h +│   │   │   │   ├── crypto_stream_salsa2012.h +│   │   │   │   ├── crypto_stream_salsa208.h +│   │   │   │   ├── crypto_stream_salsa20.h +│   │   │   │   ├── crypto_stream_xchacha20.h +│   │   │   │   ├── crypto_stream_xsalsa20.h +│   │   │   │   ├── crypto_verify_16.h +│   │   │   │   ├── crypto_verify_32.h +│   │   │   │   ├── crypto_verify_64.h +│   │   │   │   ├── crypto_xof_shake128.h +│   │   │   │   ├── crypto_xof_shake256.h +│   │   │   │   ├── crypto_xof_turboshake128.h +│   │   │   │   ├── crypto_xof_turboshake256.h +│   │   │   │   ├── export.h +│   │   │   │   ├── randombytes.h +│   │   │   │   ├── randombytes_internal_random.h +│   │   │   │   ├── randombytes_sysrandom.h +│   │   │   │   ├── runtime.h +│   │   │   │   ├── utils.h +│   │   │   │   └── version.h +│   │   │   ├── sodium.h +│   │   │   ├── sqlite3ext.h +│   │   │   ├── sqlite3.h +│   │   │   ├── tclDecls.h +│   │   │   ├── tcl.h +│   │   │   ├── tclIntDecls.h +│   │   │   ├── tclInt.h +│   │   │   ├── tclIntPlatDecls.h +│   │   │   ├── tclOODecls.h +│   │   │   ├── tclOO.h +│   │   │   ├── tclOOIntDecls.h +│   │   │   ├── tclOOInt.h +│   │   │   ├── tclPlatDecls.h +│   │   │   ├── tclPort.h +│   │   │   ├── tclThread.h +│   │   │   ├── tclTomMathDecls.h +│   │   │   ├── tclTomMath.h +│   │   │   ├── tclUnixPort.h +│   │   │   ├── tdbcDecls.h +│   │   │   ├── tdbc.h +│   │   │   ├── tdbcInt.h +│   │   │   ├── termcap.h +│   │   │   ├── term_entry.h +│   │   │   ├── term.h +│   │   │   ├── tk3d.h +│   │   │   ├── tkArray.h +│   │   │   ├── tkBusy.h +│   │   │   ├── tkButton.h +│   │   │   ├── tkCanvas.h +│   │   │   ├── tkColor.h +│   │   │   ├── tkDecls.h +│   │   │   ├── tkDList.h +│   │   │   ├── tkEntry.h +│   │   │   ├── tkFileFilter.h +│   │   │   ├── tkFont.h +│   │   │   ├── tk.h +│   │   │   ├── tkImgPhoto.h +│   │   │   ├── tkIntDecls.h +│   │   │   ├── tkInt.h +│   │   │   ├── tkIntPlatDecls.h +│   │   │   ├── tkIntXlibDecls.h +│   │   │   ├── tkMacOSXColor.h +│   │   │   ├── tkMacOSXConstants.h +│   │   │   ├── tkMacOSXCursors.h +│   │   │   ├── tkMacOSXDebug.h +│   │   │   ├── tkMacOSXDefault.h +│   │   │   ├── tkMacOSXEvent.h +│   │   │   ├── tkMacOSXFileTypes.h +│   │   │   ├── tkMacOSXFont.h +│   │   │   ├── tkMacOSX.h +│   │   │   ├── tkMacOSXInt.h +│   │   │   ├── tkMacOSXKeysyms.h +│   │   │   ├── tkMacOSXPort.h +│   │   │   ├── tkMacOSXPrivate.h +│   │   │   ├── tkMacOSXWm.h +│   │   │   ├── tkMacOSXXCursors.h +│   │   │   ├── tkMenubutton.h +│   │   │   ├── tkMenu.h +│   │   │   ├── tkPlatDecls.h +│   │   │   ├── tkPort.h +│   │   │   ├── tkScale.h +│   │   │   ├── tkScrollbar.h +│   │   │   ├── tkSelect.h +│   │   │   ├── tkText.h +│   │   │   ├── tkUndo.h +│   │   │   ├── tkUnixDefault.h +│   │   │   ├── tkUnixInt.h +│   │   │   ├── tkUnixPort.h +│   │   │   ├── tkUuid.h +│   │   │   ├── unctrl.h +│   │   │   ├── unicode +│   │   │   │   ├── alphaindex.h +│   │   │   │   ├── appendable.h +│   │   │   │   ├── basictz.h +│   │   │   │   ├── brkiter.h +│   │   │   │   ├── bytestream.h +│   │   │   │   ├── bytestriebuilder.h +│   │   │   │   ├── bytestrie.h +│   │   │   │   ├── calendar.h +│   │   │   │   ├── caniter.h +│   │   │   │   ├── casemap.h +│   │   │   │   ├── char16ptr.h +│   │   │   │   ├── chariter.h +│   │   │   │   ├── choicfmt.h +│   │   │   │   ├── coleitr.h +│   │   │   │   ├── coll.h +│   │   │   │   ├── compactdecimalformat.h +│   │   │   │   ├── curramt.h +│   │   │   │   ├── currpinf.h +│   │   │   │   ├── currunit.h +│   │   │   │   ├── datefmt.h +│   │   │   │   ├── dbbi.h +│   │   │   │   ├── dcfmtsym.h +│   │   │   │   ├── decimfmt.h +│   │   │   │   ├── displayoptions.h +│   │   │   │   ├── docmain.h +│   │   │   │   ├── dtfmtsym.h +│   │   │   │   ├── dtintrv.h +│   │   │   │   ├── dtitvfmt.h +│   │   │   │   ├── dtitvinf.h +│   │   │   │   ├── dtptngen.h +│   │   │   │   ├── dtrule.h +│   │   │   │   ├── edits.h +│   │   │   │   ├── enumset.h +│   │   │   │   ├── errorcode.h +│   │   │   │   ├── fieldpos.h +│   │   │   │   ├── filteredbrk.h +│   │   │   │   ├── fmtable.h +│   │   │   │   ├── format.h +│   │   │   │   ├── formattednumber.h +│   │   │   │   ├── formattedvalue.h +│   │   │   │   ├── fpositer.h +│   │   │   │   ├── gender.h +│   │   │   │   ├── gregocal.h +│   │   │   │   ├── icudataver.h +│   │   │   │   ├── icuplug.h +│   │   │   │   ├── idna.h +│   │   │   │   ├── listformatter.h +│   │   │   │   ├── localebuilder.h +│   │   │   │   ├── localematcher.h +│   │   │   │   ├── localpointer.h +│   │   │   │   ├── locdspnm.h +│   │   │   │   ├── locid.h +│   │   │   │   ├── measfmt.h +│   │   │   │   ├── measunit.h +│   │   │   │   ├── measure.h +│   │   │   │   ├── messageformat2_arguments.h +│   │   │   │   ├── messageformat2_data_model.h +│   │   │   │   ├── messageformat2_data_model_names.h +│   │   │   │   ├── messageformat2_formattable.h +│   │   │   │   ├── messageformat2_function_registry.h +│   │   │   │   ├── messageformat2.h +│   │   │   │   ├── messagepattern.h +│   │   │   │   ├── msgfmt.h +│   │   │   │   ├── normalizer2.h +│   │   │   │   ├── normlzr.h +│   │   │   │   ├── nounit.h +│   │   │   │   ├── numberformatter.h +│   │   │   │   ├── numberrangeformatter.h +│   │   │   │   ├── numfmt.h +│   │   │   │   ├── numsys.h +│   │   │   │   ├── parseerr.h +│   │   │   │   ├── parsepos.h +│   │   │   │   ├── platform.h +│   │   │   │   ├── plurfmt.h +│   │   │   │   ├── plurrule.h +│   │   │   │   ├── ptypes.h +│   │   │   │   ├── putil.h +│   │   │   │   ├── rbbi.h +│   │   │   │   ├── rbnf.h +│   │   │   │   ├── rbtz.h +│   │   │   │   ├── regex.h +│   │   │   │   ├── region.h +│   │   │   │   ├── reldatefmt.h +│   │   │   │   ├── rep.h +│   │   │   │   ├── resbund.h +│   │   │   │   ├── schriter.h +│   │   │   │   ├── scientificnumberformatter.h +│   │   │   │   ├── search.h +│   │   │   │   ├── selfmt.h +│   │   │   │   ├── simpleformatter.h +│   │   │   │   ├── simplenumberformatter.h +│   │   │   │   ├── simpletz.h +│   │   │   │   ├── smpdtfmt.h +│   │   │   │   ├── sortkey.h +│   │   │   │   ├── std_string.h +│   │   │   │   ├── strenum.h +│   │   │   │   ├── stringoptions.h +│   │   │   │   ├── stringpiece.h +│   │   │   │   ├── stringtriebuilder.h +│   │   │   │   ├── stsearch.h +│   │   │   │   ├── symtable.h +│   │   │   │   ├── tblcoll.h +│   │   │   │   ├── timezone.h +│   │   │   │   ├── tmunit.h +│   │   │   │   ├── tmutamt.h +│   │   │   │   ├── tmutfmt.h +│   │   │   │   ├── translit.h +│   │   │   │   ├── tzfmt.h +│   │   │   │   ├── tznames.h +│   │   │   │   ├── tzrule.h +│   │   │   │   ├── tztrans.h +│   │   │   │   ├── ubidi.h +│   │   │   │   ├── ubiditransform.h +│   │   │   │   ├── ubrk.h +│   │   │   │   ├── ucal.h +│   │   │   │   ├── ucasemap.h +│   │   │   │   ├── ucat.h +│   │   │   │   ├── uchar.h +│   │   │   │   ├── ucharstriebuilder.h +│   │   │   │   ├── ucharstrie.h +│   │   │   │   ├── uchriter.h +│   │   │   │   ├── uclean.h +│   │   │   │   ├── ucnv_cb.h +│   │   │   │   ├── ucnv_err.h +│   │   │   │   ├── ucnv.h +│   │   │   │   ├── ucnvsel.h +│   │   │   │   ├── ucoleitr.h +│   │   │   │   ├── ucol.h +│   │   │   │   ├── uconfig.h +│   │   │   │   ├── ucpmap.h +│   │   │   │   ├── ucptrie.h +│   │   │   │   ├── ucsdet.h +│   │   │   │   ├── ucurr.h +│   │   │   │   ├── udata.h +│   │   │   │   ├── udateintervalformat.h +│   │   │   │   ├── udat.h +│   │   │   │   ├── udatpg.h +│   │   │   │   ├── udisplaycontext.h +│   │   │   │   ├── udisplayoptions.h +│   │   │   │   ├── uenum.h +│   │   │   │   ├── ufieldpositer.h +│   │   │   │   ├── uformattable.h +│   │   │   │   ├── uformattednumber.h +│   │   │   │   ├── uformattedvalue.h +│   │   │   │   ├── ugender.h +│   │   │   │   ├── uidna.h +│   │   │   │   ├── uiter.h +│   │   │   │   ├── uldnames.h +│   │   │   │   ├── ulistformatter.h +│   │   │   │   ├── ulocale.h +│   │   │   │   ├── ulocbuilder.h +│   │   │   │   ├── ulocdata.h +│   │   │   │   ├── uloc.h +│   │   │   │   ├── umachine.h +│   │   │   │   ├── umisc.h +│   │   │   │   ├── umsg.h +│   │   │   │   ├── umutablecptrie.h +│   │   │   │   ├── unifilt.h +│   │   │   │   ├── unifunct.h +│   │   │   │   ├── unimatch.h +│   │   │   │   ├── unirepl.h +│   │   │   │   ├── uniset.h +│   │   │   │   ├── unistr.h +│   │   │   │   ├── unorm2.h +│   │   │   │   ├── unorm.h +│   │   │   │   ├── unumberformatter.h +│   │   │   │   ├── unumberoptions.h +│   │   │   │   ├── unumberrangeformatter.h +│   │   │   │   ├── unum.h +│   │   │   │   ├── unumsys.h +│   │   │   │   ├── uobject.h +│   │   │   │   ├── upluralrules.h +│   │   │   │   ├── uregex.h +│   │   │   │   ├── uregion.h +│   │   │   │   ├── ureldatefmt.h +│   │   │   │   ├── urename.h +│   │   │   │   ├── urep.h +│   │   │   │   ├── ures.h +│   │   │   │   ├── uscript.h +│   │   │   │   ├── usearch.h +│   │   │   │   ├── uset.h +│   │   │   │   ├── usetiter.h +│   │   │   │   ├── ushape.h +│   │   │   │   ├── usimplenumberformatter.h +│   │   │   │   ├── uspoof.h +│   │   │   │   ├── usprep.h +│   │   │   │   ├── ustdio.h +│   │   │   │   ├── ustream.h +│   │   │   │   ├── ustring.h +│   │   │   │   ├── ustringtrie.h +│   │   │   │   ├── utext.h +│   │   │   │   ├── utf16.h +│   │   │   │   ├── utf32.h +│   │   │   │   ├── utf8.h +│   │   │   │   ├── utf.h +│   │   │   │   ├── utfiterator.h +│   │   │   │   ├── utf_old.h +│   │   │   │   ├── utfstring.h +│   │   │   │   ├── utmscale.h +│   │   │   │   ├── utrace.h +│   │   │   │   ├── utrans.h +│   │   │   │   ├── utypes.h +│   │   │   │   ├── uvernum.h +│   │   │   │   ├── uversion.h +│   │   │   │   └── vtzone.h +│   │   │   ├── uuid +│   │   │   │   └── uuid.h +│   │   │   ├── verto.h +│   │   │   ├── verto-module.h +│   │   │   ├── zdict.h +│   │   │   ├── zmq.h +│   │   │   ├── zmq_utils.h +│   │   │   ├── zstd_errors.h +│   │   │   └── zstd.h +│   │   ├── lib +│   │   │   ├── cmake +│   │   │   │   ├── OpenSSL +│   │   │   │   │   ├── OpenSSLConfig.cmake +│   │   │   │   │   └── OpenSSLConfigVersion.cmake +│   │   │   │   ├── ZeroMQ +│   │   │   │   │   ├── ZeroMQConfig.cmake +│   │   │   │   │   └── ZeroMQConfigVersion.cmake +│   │   │   │   └── zstd +│   │   │   │   ├── zstdConfig.cmake +│   │   │   │   ├── zstdConfigVersion.cmake +│   │   │   │   ├── zstdTargets.cmake +│   │   │   │   └── zstdTargets-release.cmake +│   │   │   ├── icu +│   │   │   │   ├── 78.3 +│   │   │   │   │   ├── Makefile.inc +│   │   │   │   │   └── pkgdata.inc +│   │   │   │   ├── current -> 78.3 +│   │   │   │   ├── Makefile.inc -> 78.3/Makefile.inc +│   │   │   │   └── pkgdata.inc -> 78.3/pkgdata.inc +│   │   │   ├── itcl4.2.3 +│   │   │   │   ├── itclConfig.sh +│   │   │   │   ├── itclHullCmds.tcl +│   │   │   │   ├── itcl.tcl +│   │   │   │   ├── itclWidget.tcl +│   │   │   │   ├── libitcl4.2.3.so +│   │   │   │   ├── libitclstub4.2.3.a +│   │   │   │   └── pkgIndex.tcl +│   │   │   ├── krb5 +│   │   │   │   └── plugins +│   │   │   │   ├── kdb +│   │   │   │   │   └── db2.so +│   │   │   │   ├── preauth +│   │   │   │   │   ├── otp.so +│   │   │   │   │   ├── pkinit.so +│   │   │   │   │   ├── spake.so +│   │   │   │   │   └── test.so +│   │   │   │   └── tls +│   │   │   │   └── k5tls.so +│   │   │   ├── libAsyncRTMojoBindings.so +│   │   │   ├── libAsyncRTRuntimeGlobals.so +│   │   │   ├── libatomic.so -> libatomic.so.1.2.0 +│   │   │   ├── libatomic.so.1 -> libatomic.so.1.2.0 +│   │   │   ├── libatomic.so.1.2.0 +│   │   │   ├── libbz2.a +│   │   │   ├── libbz2.so -> libbz2.so.1.0.8 +│   │   │   ├── libbz2.so.1.0 -> libbz2.so.1.0.8 +│   │   │   ├── libbz2.so.1.0.8 +│   │   │   ├── libcom_err.so -> libcom_err.so.3.0 +│   │   │   ├── libcom_err.so.3 -> libcom_err.so.3.0 +│   │   │   ├── libcom_err.so.3.0 +│   │   │   ├── libcrypto.so -> libcrypto.so.3 +│   │   │   ├── libcrypto.so.3 +│   │   │   ├── libcrypt.so -> libcrypt.so.2.0.0 +│   │   │   ├── libcrypt.so.2 -> libcrypt.so.2.0.0 +│   │   │   ├── libcrypt.so.2.0.0 +│   │   │   ├── libedit.so -> libedit.so.0.0.75 +│   │   │   ├── libedit.so.0 -> libedit.so.0.0.75 +│   │   │   ├── libedit.so.0.0.75 +│   │   │   ├── libexpat.so.1 -> libexpat.so.1.11.3 +│   │   │   ├── libexpat.so.1.11.3 +│   │   │   ├── libffi.a +│   │   │   ├── libffi.so -> libffi.so.8.2.0 +│   │   │   ├── libffi.so.8 -> libffi.so.8.2.0 +│   │   │   ├── libffi.so.8.2.0 +│   │   │   ├── libform.so -> libform.so.6.6 +│   │   │   ├── libform.so.6 -> libform.so.6.6 +│   │   │   ├── libform.so.6.6 +│   │   │   ├── libformw.so -> libformw.so.6.6 +│   │   │   ├── libformw.so.6 -> libformw.so.6.6 +│   │   │   ├── libformw.so.6.6 +│   │   │   ├── libgcc_s.so +│   │   │   ├── libgcc_s.so.1 +│   │   │   ├── libgomp.so -> libgomp.so.1.0.0 +│   │   │   ├── libgomp.so.1 -> libgomp.so.1.0.0 +│   │   │   ├── libgomp.so.1.0.0 +│   │   │   ├── libgssapi_krb5.so -> libgssapi_krb5.so.2.2 +│   │   │   ├── libgssapi_krb5.so.2 -> libgssapi_krb5.so.2.2 +│   │   │   ├── libgssapi_krb5.so.2.2 +│   │   │   ├── libgssrpc.so -> libgssrpc.so.4.2 +│   │   │   ├── libgssrpc.so.4 -> libgssrpc.so.4.2 +│   │   │   ├── libgssrpc.so.4.2 +│   │   │   ├── libhistory.so -> libhistory.so.8.3 +│   │   │   ├── libhistory.so.8 -> libhistory.so.8.3 +│   │   │   ├── libhistory.so.8.3 +│   │   │   ├── libicudata.so -> libicudata.so.78.3 +│   │   │   ├── libicudata.so.78 -> libicudata.so.78.3 +│   │   │   ├── libicudata.so.78.3 +│   │   │   ├── libicui18n.so -> libicui18n.so.78.3 +│   │   │   ├── libicui18n.so.78 -> libicui18n.so.78.3 +│   │   │   ├── libicui18n.so.78.3 +│   │   │   ├── libicuio.so -> libicuio.so.78.3 +│   │   │   ├── libicuio.so.78 -> libicuio.so.78.3 +│   │   │   ├── libicuio.so.78.3 +│   │   │   ├── libicutest.so -> libicutest.so.78.3 +│   │   │   ├── libicutest.so.78 -> libicutest.so.78.3 +│   │   │   ├── libicutest.so.78.3 +│   │   │   ├── libicutu.so -> libicutu.so.78.3 +│   │   │   ├── libicutu.so.78 -> libicutu.so.78.3 +│   │   │   ├── libicutu.so.78.3 +│   │   │   ├── libicuuc.so -> libicuuc.so.78.3 +│   │   │   ├── libicuuc.so.78 -> libicuuc.so.78.3 +│   │   │   ├── libicuuc.so.78.3 +│   │   │   ├── libitm.so -> libitm.so.1.0.0 +│   │   │   ├── libitm.so.1 -> libitm.so.1.0.0 +│   │   │   ├── libitm.so.1.0.0 +│   │   │   ├── libk5crypto.so -> libk5crypto.so.3.1 +│   │   │   ├── libk5crypto.so.3 -> libk5crypto.so.3.1 +│   │   │   ├── libk5crypto.so.3.1 +│   │   │   ├── libkadm5clnt_mit.so -> libkadm5clnt_mit.so.12.0 +│   │   │   ├── libkadm5clnt_mit.so.12 -> libkadm5clnt_mit.so.12.0 +│   │   │   ├── libkadm5clnt_mit.so.12.0 +│   │   │   ├── libkadm5clnt.so -> libkadm5clnt_mit.so.12.0 +│   │   │   ├── libkadm5srv_mit.so -> libkadm5srv_mit.so.12.0 +│   │   │   ├── libkadm5srv_mit.so.12 -> libkadm5srv_mit.so.12.0 +│   │   │   ├── libkadm5srv_mit.so.12.0 +│   │   │   ├── libkadm5srv.so -> libkadm5srv_mit.so.12.0 +│   │   │   ├── libkdb5.so -> libkdb5.so.10.0 +│   │   │   ├── libkdb5.so.10 -> libkdb5.so.10.0 +│   │   │   ├── libkdb5.so.10.0 +│   │   │   ├── libkeyutils.a +│   │   │   ├── libkeyutils.so -> libkeyutils.so.1.10 +│   │   │   ├── libkeyutils.so.1 -> libkeyutils.so.1.10 +│   │   │   ├── libkeyutils.so.1.10 +│   │   │   ├── libKGENCompilerRTShared.so +│   │   │   ├── libkrad.so -> libkrad.so.0.0 +│   │   │   ├── libkrad.so.0 -> libkrad.so.0.0 +│   │   │   ├── libkrad.so.0.0 +│   │   │   ├── libkrb5.so -> libkrb5.so.3.3 +│   │   │   ├── libkrb5.so.3 -> libkrb5.so.3.3 +│   │   │   ├── libkrb5.so.3.3 +│   │   │   ├── libkrb5support.so -> libkrb5support.so.0.1 +│   │   │   ├── libkrb5support.so.0 -> libkrb5support.so.0.1 +│   │   │   ├── libkrb5support.so.0.1 +│   │   │   ├── liblldb23.0.0git.so +│   │   │   ├── liblzma.so.5 +│   │   │   ├── liblzma.so.5.8.3 +│   │   │   ├── libmenu.so -> libmenu.so.6.6 +│   │   │   ├── libmenu.so.6 -> libmenu.so.6.6 +│   │   │   ├── libmenu.so.6.6 +│   │   │   ├── libmenuw.so -> libmenuw.so.6.6 +│   │   │   ├── libmenuw.so.6 -> libmenuw.so.6.6 +│   │   │   ├── libmenuw.so.6.6 +│   │   │   ├── libMojoJupyter.so +│   │   │   ├── libMojoLLDB.so +│   │   │   ├── libMSupportGlobals.so +│   │   │   ├── libncurses++.a +│   │   │   ├── libncurses.so +│   │   │   ├── libncurses.so.6 -> libncurses.so.6.6 +│   │   │   ├── libncurses.so.6.6 +│   │   │   ├── libncurses++w.a +│   │   │   ├── libncursesw.so +│   │   │   ├── libncursesw.so.6 -> libncursesw.so.6.6 +│   │   │   ├── libncursesw.so.6.6 +│   │   │   ├── libnsl.so -> libnsl.so.3.0.0 +│   │   │   ├── libnsl.so.3 -> libnsl.so.3.0.0 +│   │   │   ├── libnsl.so.3.0.0 +│   │   │   ├── libNVPTX.so +│   │   │   ├── libpanel.so -> libpanel.so.6.6 +│   │   │   ├── libpanel.so.6 -> libpanel.so.6.6 +│   │   │   ├── libpanel.so.6.6 +│   │   │   ├── libpanelw.so -> libpanelw.so.6.6 +│   │   │   ├── libpanelw.so.6 -> libpanelw.so.6.6 +│   │   │   ├── libpanelw.so.6.6 +│   │   │   ├── libpython3.12.so -> libpython3.12.so.1.0 +│   │   │   ├── libpython3.12.so.1.0 +│   │   │   ├── libpython3.so +│   │   │   ├── libquadmath.so -> libquadmath.so.0.0.0 +│   │   │   ├── libquadmath.so.0 -> libquadmath.so.0.0.0 +│   │   │   ├── libquadmath.so.0.0.0 +│   │   │   ├── libreadline.so -> libreadline.so.8.3 +│   │   │   ├── libreadline.so.8 -> libreadline.so.8.3 +│   │   │   ├── libreadline.so.8.3 +│   │   │   ├── libsodium.so -> libsodium.so.26.3.0 +│   │   │   ├── libsodium.so.26 -> libsodium.so.26.3.0 +│   │   │   ├── libsodium.so.26.3.0 +│   │   │   ├── libsqlite3.so -> libsqlite3.so.3.53.0 +│   │   │   ├── libsqlite3.so.0 -> libsqlite3.so.3.53.0 +│   │   │   ├── libsqlite3.so.3.53.0 +│   │   │   ├── libssl.so -> libssl.so.3 +│   │   │   ├── libssl.so.3 +│   │   │   ├── libstdc++.so -> libstdc++.so.6.0.34 +│   │   │   ├── libstdc++.so.6 -> libstdc++.so.6.0.34 +│   │   │   ├── libstdc++.so.6.0.34 +│   │   │   ├── libtcl8.6.so +│   │   │   ├── libtclstub8.6.a +│   │   │   ├── libtinfo.so -> libtinfo.so.6.6 +│   │   │   ├── libtinfo.so.6 -> libtinfo.so.6.6 +│   │   │   ├── libtinfo.so.6.6 +│   │   │   ├── libtinfow.so -> libtinfow.so.6.6 +│   │   │   ├── libtinfow.so.6 -> libtinfow.so.6.6 +│   │   │   ├── libtinfow.so.6.6 +│   │   │   ├── libtk8.6.so +│   │   │   ├── libtkstub8.6.a +│   │   │   ├── libuuid.a +│   │   │   ├── libuuid.so -> libuuid.so.1.3.0 +│   │   │   ├── libuuid.so.1 -> libuuid.so.1.3.0 +│   │   │   ├── libuuid.so.1.3.0 +│   │   │   ├── libverto.so -> libverto.so.0.0 +│   │   │   ├── libverto.so.0 -> libverto.so.0.0 +│   │   │   ├── libverto.so.0.0 +│   │   │   ├── libzmq.so -> libzmq.so.5.2.5 +│   │   │   ├── libzmq.so.5 -> libzmq.so.5.2.5 +│   │   │   ├── libzmq.so.5.2.5 +│   │   │   ├── libz.so.1 -> libz.so.1.3.2 +│   │   │   ├── libz.so.1.3.2 +│   │   │   ├── libzstd.so -> libzstd.so.1 +│   │   │   ├── libzstd.so.1 -> libzstd.so.1.5.7 +│   │   │   ├── libzstd.so.1.5.7 +│   │   │   ├── lldb-visualizers +│   │   │   │   ├── lldbDataFormatters.py +│   │   │   │   └── mlirDataFormatters.py +│   │   │   ├── mojo +│   │   │   │   ├── layout.mojopkg +│   │   │   │   └── std.mojopkg +│   │   │   ├── mojo-repl-entry-point +│   │   │   ├── pkgconfig +│   │   │   │   ├── form.pc +│   │   │   │   ├── formw.pc +│   │   │   │   ├── gssrpc.pc +│   │   │   │   ├── history.pc +│   │   │   │   ├── icu-i18n.pc +│   │   │   │   ├── icu-io.pc +│   │   │   │   ├── icu-uc.pc +│   │   │   │   ├── kadm-client.pc +│   │   │   │   ├── kadm-server.pc +│   │   │   │   ├── kdb.pc +│   │   │   │   ├── krb5-gssapi.pc +│   │   │   │   ├── krb5.pc +│   │   │   │   ├── libcrypto.pc +│   │   │   │   ├── libcrypt.pc -> libxcrypt.pc +│   │   │   │   ├── libedit.pc +│   │   │   │   ├── libffi.pc +│   │   │   │   ├── libkeyutils.pc +│   │   │   │   ├── libnsl.pc +│   │   │   │   ├── libsodium.pc +│   │   │   │   ├── libssl.pc +│   │   │   │   ├── libxcrypt.pc +│   │   │   │   ├── libzmq.pc +│   │   │   │   ├── libzstd.pc +│   │   │   │   ├── menu.pc +│   │   │   │   ├── menuw.pc +│   │   │   │   ├── mit-krb5-gssapi.pc +│   │   │   │   ├── mit-krb5.pc +│   │   │   │   ├── ncurses++.pc +│   │   │   │   ├── ncurses.pc +│   │   │   │   ├── ncurses++w.pc +│   │   │   │   ├── ncursesw.pc +│   │   │   │   ├── openssl.pc +│   │   │   │   ├── panel.pc +│   │   │   │   ├── panelw.pc +│   │   │   │   ├── python-3.12-embed.pc +│   │   │   │   ├── python-3.12.pc +│   │   │   │   ├── python3-embed.pc -> python-3.12-embed.pc +│   │   │   │   ├── python3.pc -> python-3.12.pc +│   │   │   │   ├── readline.pc +│   │   │   │   ├── sqlite3.pc +│   │   │   │   ├── tcl.pc +│   │   │   │   ├── tinfo.pc +│   │   │   │   ├── tinfow.pc +│   │   │   │   ├── tk.pc +│   │   │   │   └── uuid.pc +│   │   │   ├── python3.1 -> python3.12 +│   │   │   ├── python3.12 +│   │   │   │   ├── abc.py +│   │   │   │   ├── aifc.py +│   │   │   │   ├── _aix_support.py +│   │   │   │   ├── antigravity.py +│   │   │   │   ├── argparse.py +│   │   │   │   ├── ast.py +│   │   │   │   ├── asyncio +│   │   │   │   │   ├── base_events.py +│   │   │   │   │   ├── base_futures.py +│   │   │   │   │   ├── base_subprocess.py +│   │   │   │   │   ├── base_tasks.py +│   │   │   │   │   ├── constants.py +│   │   │   │   │   ├── coroutines.py +│   │   │   │   │   ├── events.py +│   │   │   │   │   ├── exceptions.py +│   │   │   │   │   ├── format_helpers.py +│   │   │   │   │   ├── futures.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── locks.py +│   │   │   │   │   ├── log.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── mixins.py +│   │   │   │   │   ├── proactor_events.py +│   │   │   │   │   ├── protocols.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── base_events.cpython-312.pyc +│   │   │   │   │   │   ├── base_futures.cpython-312.pyc +│   │   │   │   │   │   ├── base_subprocess.cpython-312.pyc +│   │   │   │   │   │   ├── base_tasks.cpython-312.pyc +│   │   │   │   │   │   ├── constants.cpython-312.pyc +│   │   │   │   │   │   ├── coroutines.cpython-312.pyc +│   │   │   │   │   │   ├── events.cpython-312.pyc +│   │   │   │   │   │   ├── exceptions.cpython-312.pyc +│   │   │   │   │   │   ├── format_helpers.cpython-312.pyc +│   │   │   │   │   │   ├── futures.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── locks.cpython-312.pyc +│   │   │   │   │   │   ├── log.cpython-312.pyc +│   │   │   │   │   │   ├── __main__.cpython-312.pyc +│   │   │   │   │   │   ├── mixins.cpython-312.pyc +│   │   │   │   │   │   ├── proactor_events.cpython-312.pyc +│   │   │   │   │   │   ├── protocols.cpython-312.pyc +│   │   │   │   │   │   ├── queues.cpython-312.pyc +│   │   │   │   │   │   ├── runners.cpython-312.pyc +│   │   │   │   │   │   ├── selector_events.cpython-312.pyc +│   │   │   │   │   │   ├── sslproto.cpython-312.pyc +│   │   │   │   │   │   ├── staggered.cpython-312.pyc +│   │   │   │   │   │   ├── streams.cpython-312.pyc +│   │   │   │   │   │   ├── subprocess.cpython-312.pyc +│   │   │   │   │   │   ├── taskgroups.cpython-312.pyc +│   │   │   │   │   │   ├── tasks.cpython-312.pyc +│   │   │   │   │   │   ├── threads.cpython-312.pyc +│   │   │   │   │   │   ├── timeouts.cpython-312.pyc +│   │   │   │   │   │   ├── transports.cpython-312.pyc +│   │   │   │   │   │   ├── trsock.cpython-312.pyc +│   │   │   │   │   │   ├── unix_events.cpython-312.pyc +│   │   │   │   │   │   ├── windows_events.cpython-312.pyc +│   │   │   │   │   │   └── windows_utils.cpython-312.pyc +│   │   │   │   │   ├── queues.py +│   │   │   │   │   ├── runners.py +│   │   │   │   │   ├── selector_events.py +│   │   │   │   │   ├── sslproto.py +│   │   │   │   │   ├── staggered.py +│   │   │   │   │   ├── streams.py +│   │   │   │   │   ├── subprocess.py +│   │   │   │   │   ├── taskgroups.py +│   │   │   │   │   ├── tasks.py +│   │   │   │   │   ├── threads.py +│   │   │   │   │   ├── timeouts.py +│   │   │   │   │   ├── transports.py +│   │   │   │   │   ├── trsock.py +│   │   │   │   │   ├── unix_events.py +│   │   │   │   │   ├── windows_events.py +│   │   │   │   │   └── windows_utils.py +│   │   │   │   ├── base64.py +│   │   │   │   ├── bdb.py +│   │   │   │   ├── bisect.py +│   │   │   │   ├── bz2.py +│   │   │   │   ├── calendar.py +│   │   │   │   ├── cgi.py +│   │   │   │   ├── cgitb.py +│   │   │   │   ├── chunk.py +│   │   │   │   ├── cmd.py +│   │   │   │   ├── codecs.py +│   │   │   │   ├── codeop.py +│   │   │   │   ├── code.py +│   │   │   │   ├── collections +│   │   │   │   │   ├── abc.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   └── __pycache__ +│   │   │   │   │   ├── abc.cpython-312.pyc +│   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   ├── _collections_abc.py +│   │   │   │   ├── colorsys.py +│   │   │   │   ├── _compat_pickle.py +│   │   │   │   ├── compileall.py +│   │   │   │   ├── _compression.py +│   │   │   │   ├── concurrent +│   │   │   │   │   ├── futures +│   │   │   │   │   │   ├── _base.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── process.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── _base.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── process.cpython-312.pyc +│   │   │   │   │   │   │   └── thread.cpython-312.pyc +│   │   │   │   │   │   └── thread.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   └── __pycache__ +│   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   ├── config-3.12-x86_64-linux-gnu +│   │   │   │   │   ├── config.c +│   │   │   │   │   ├── config.c.in +│   │   │   │   │   ├── install-sh +│   │   │   │   │   ├── Makefile +│   │   │   │   │   ├── makesetup +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   └── python-config.cpython-312.pyc +│   │   │   │   │   ├── python-config.py +│   │   │   │   │   ├── python.o +│   │   │   │   │   ├── Setup +│   │   │   │   │   ├── Setup.bootstrap +│   │   │   │   │   ├── Setup.local +│   │   │   │   │   └── Setup.stdlib +│   │   │   │   ├── configparser.py +│   │   │   │   ├── contextlib.py +│   │   │   │   ├── contextvars.py +│   │   │   │   ├── copy.py +│   │   │   │   ├── copyreg.py +│   │   │   │   ├── cProfile.py +│   │   │   │   ├── crypt.py +│   │   │   │   ├── csv.py +│   │   │   │   ├── ctypes +│   │   │   │   │   ├── _aix.py +│   │   │   │   │   ├── _endian.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── macholib +│   │   │   │   │   │   ├── dyld.py +│   │   │   │   │   │   ├── dylib.py +│   │   │   │   │   │   ├── fetch_macholib +│   │   │   │   │   │   ├── fetch_macholib.bat +│   │   │   │   │   │   ├── framework.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── dyld.cpython-312.pyc +│   │   │   │   │   │   │   ├── dylib.cpython-312.pyc +│   │   │   │   │   │   │   ├── framework.cpython-312.pyc +│   │   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   │   └── README.ctypes +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── _aix.cpython-312.pyc +│   │   │   │   │   │   ├── _endian.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── util.cpython-312.pyc +│   │   │   │   │   │   └── wintypes.cpython-312.pyc +│   │   │   │   │   ├── util.py +│   │   │   │   │   └── wintypes.py +│   │   │   │   ├── curses +│   │   │   │   │   ├── ascii.py +│   │   │   │   │   ├── has_key.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── panel.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── ascii.cpython-312.pyc +│   │   │   │   │   │   ├── has_key.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── panel.cpython-312.pyc +│   │   │   │   │   │   └── textpad.cpython-312.pyc +│   │   │   │   │   └── textpad.py +│   │   │   │   ├── dataclasses.py +│   │   │   │   ├── datetime.py +│   │   │   │   ├── dbm +│   │   │   │   │   ├── dumb.py +│   │   │   │   │   ├── gnu.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── ndbm.py +│   │   │   │   │   └── __pycache__ +│   │   │   │   │   ├── dumb.cpython-312.pyc +│   │   │   │   │   ├── gnu.cpython-312.pyc +│   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   └── ndbm.cpython-312.pyc +│   │   │   │   ├── decimal.py +│   │   │   │   ├── difflib.py +│   │   │   │   ├── dis.py +│   │   │   │   ├── doctest.py +│   │   │   │   ├── email +│   │   │   │   │   ├── architecture.rst +│   │   │   │   │   ├── base64mime.py +│   │   │   │   │   ├── charset.py +│   │   │   │   │   ├── contentmanager.py +│   │   │   │   │   ├── _encoded_words.py +│   │   │   │   │   ├── encoders.py +│   │   │   │   │   ├── errors.py +│   │   │   │   │   ├── feedparser.py +│   │   │   │   │   ├── generator.py +│   │   │   │   │   ├── header.py +│   │   │   │   │   ├── headerregistry.py +│   │   │   │   │   ├── _header_value_parser.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── iterators.py +│   │   │   │   │   ├── message.py +│   │   │   │   │   ├── mime +│   │   │   │   │   │   ├── application.py +│   │   │   │   │   │   ├── audio.py +│   │   │   │   │   │   ├── base.py +│   │   │   │   │   │   ├── image.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── message.py +│   │   │   │   │   │   ├── multipart.py +│   │   │   │   │   │   ├── nonmultipart.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── application.cpython-312.pyc +│   │   │   │   │   │   │   ├── audio.cpython-312.pyc +│   │   │   │   │   │   │   ├── base.cpython-312.pyc +│   │   │   │   │   │   │   ├── image.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── message.cpython-312.pyc +│   │   │   │   │   │   │   ├── multipart.cpython-312.pyc +│   │   │   │   │   │   │   ├── nonmultipart.cpython-312.pyc +│   │   │   │   │   │   │   └── text.cpython-312.pyc +│   │   │   │   │   │   └── text.py +│   │   │   │   │   ├── _parseaddr.py +│   │   │   │   │   ├── parser.py +│   │   │   │   │   ├── _policybase.py +│   │   │   │   │   ├── policy.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── base64mime.cpython-312.pyc +│   │   │   │   │   │   ├── charset.cpython-312.pyc +│   │   │   │   │   │   ├── contentmanager.cpython-312.pyc +│   │   │   │   │   │   ├── _encoded_words.cpython-312.pyc +│   │   │   │   │   │   ├── encoders.cpython-312.pyc +│   │   │   │   │   │   ├── errors.cpython-312.pyc +│   │   │   │   │   │   ├── feedparser.cpython-312.pyc +│   │   │   │   │   │   ├── generator.cpython-312.pyc +│   │   │   │   │   │   ├── header.cpython-312.pyc +│   │   │   │   │   │   ├── headerregistry.cpython-312.pyc +│   │   │   │   │   │   ├── _header_value_parser.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── iterators.cpython-312.pyc +│   │   │   │   │   │   ├── message.cpython-312.pyc +│   │   │   │   │   │   ├── _parseaddr.cpython-312.pyc +│   │   │   │   │   │   ├── parser.cpython-312.pyc +│   │   │   │   │   │   ├── _policybase.cpython-312.pyc +│   │   │   │   │   │   ├── policy.cpython-312.pyc +│   │   │   │   │   │   ├── quoprimime.cpython-312.pyc +│   │   │   │   │   │   └── utils.cpython-312.pyc +│   │   │   │   │   ├── quoprimime.py +│   │   │   │   │   └── utils.py +│   │   │   │   ├── encodings +│   │   │   │   │   ├── aliases.py +│   │   │   │   │   ├── ascii.py +│   │   │   │   │   ├── base64_codec.py +│   │   │   │   │   ├── big5hkscs.py +│   │   │   │   │   ├── big5.py +│   │   │   │   │   ├── bz2_codec.py +│   │   │   │   │   ├── charmap.py +│   │   │   │   │   ├── cp037.py +│   │   │   │   │   ├── cp1006.py +│   │   │   │   │   ├── cp1026.py +│   │   │   │   │   ├── cp1125.py +│   │   │   │   │   ├── cp1140.py +│   │   │   │   │   ├── cp1250.py +│   │   │   │   │   ├── cp1251.py +│   │   │   │   │   ├── cp1252.py +│   │   │   │   │   ├── cp1253.py +│   │   │   │   │   ├── cp1254.py +│   │   │   │   │   ├── cp1255.py +│   │   │   │   │   ├── cp1256.py +│   │   │   │   │   ├── cp1257.py +│   │   │   │   │   ├── cp1258.py +│   │   │   │   │   ├── cp273.py +│   │   │   │   │   ├── cp424.py +│   │   │   │   │   ├── cp437.py +│   │   │   │   │   ├── cp500.py +│   │   │   │   │   ├── cp720.py +│   │   │   │   │   ├── cp737.py +│   │   │   │   │   ├── cp775.py +│   │   │   │   │   ├── cp850.py +│   │   │   │   │   ├── cp852.py +│   │   │   │   │   ├── cp855.py +│   │   │   │   │   ├── cp856.py +│   │   │   │   │   ├── cp857.py +│   │   │   │   │   ├── cp858.py +│   │   │   │   │   ├── cp860.py +│   │   │   │   │   ├── cp861.py +│   │   │   │   │   ├── cp862.py +│   │   │   │   │   ├── cp863.py +│   │   │   │   │   ├── cp864.py +│   │   │   │   │   ├── cp865.py +│   │   │   │   │   ├── cp866.py +│   │   │   │   │   ├── cp869.py +│   │   │   │   │   ├── cp874.py +│   │   │   │   │   ├── cp875.py +│   │   │   │   │   ├── cp932.py +│   │   │   │   │   ├── cp949.py +│   │   │   │   │   ├── cp950.py +│   │   │   │   │   ├── euc_jis_2004.py +│   │   │   │   │   ├── euc_jisx0213.py +│   │   │   │   │   ├── euc_jp.py +│   │   │   │   │   ├── euc_kr.py +│   │   │   │   │   ├── gb18030.py +│   │   │   │   │   ├── gb2312.py +│   │   │   │   │   ├── gbk.py +│   │   │   │   │   ├── hex_codec.py +│   │   │   │   │   ├── hp_roman8.py +│   │   │   │   │   ├── hz.py +│   │   │   │   │   ├── idna.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── iso2022_jp_1.py +│   │   │   │   │   ├── iso2022_jp_2004.py +│   │   │   │   │   ├── iso2022_jp_2.py +│   │   │   │   │   ├── iso2022_jp_3.py +│   │   │   │   │   ├── iso2022_jp_ext.py +│   │   │   │   │   ├── iso2022_jp.py +│   │   │   │   │   ├── iso2022_kr.py +│   │   │   │   │   ├── iso8859_10.py +│   │   │   │   │   ├── iso8859_11.py +│   │   │   │   │   ├── iso8859_13.py +│   │   │   │   │   ├── iso8859_14.py +│   │   │   │   │   ├── iso8859_15.py +│   │   │   │   │   ├── iso8859_16.py +│   │   │   │   │   ├── iso8859_1.py +│   │   │   │   │   ├── iso8859_2.py +│   │   │   │   │   ├── iso8859_3.py +│   │   │   │   │   ├── iso8859_4.py +│   │   │   │   │   ├── iso8859_5.py +│   │   │   │   │   ├── iso8859_6.py +│   │   │   │   │   ├── iso8859_7.py +│   │   │   │   │   ├── iso8859_8.py +│   │   │   │   │   ├── iso8859_9.py +│   │   │   │   │   ├── johab.py +│   │   │   │   │   ├── koi8_r.py +│   │   │   │   │   ├── koi8_t.py +│   │   │   │   │   ├── koi8_u.py +│   │   │   │   │   ├── kz1048.py +│   │   │   │   │   ├── latin_1.py +│   │   │   │   │   ├── mac_arabic.py +│   │   │   │   │   ├── mac_croatian.py +│   │   │   │   │   ├── mac_cyrillic.py +│   │   │   │   │   ├── mac_farsi.py +│   │   │   │   │   ├── mac_greek.py +│   │   │   │   │   ├── mac_iceland.py +│   │   │   │   │   ├── mac_latin2.py +│   │   │   │   │   ├── mac_romanian.py +│   │   │   │   │   ├── mac_roman.py +│   │   │   │   │   ├── mac_turkish.py +│   │   │   │   │   ├── mbcs.py +│   │   │   │   │   ├── oem.py +│   │   │   │   │   ├── palmos.py +│   │   │   │   │   ├── ptcp154.py +│   │   │   │   │   ├── punycode.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── aliases.cpython-312.pyc +│   │   │   │   │   │   ├── ascii.cpython-312.pyc +│   │   │   │   │   │   ├── base64_codec.cpython-312.pyc +│   │   │   │   │   │   ├── big5.cpython-312.pyc +│   │   │   │   │   │   ├── big5hkscs.cpython-312.pyc +│   │   │   │   │   │   ├── bz2_codec.cpython-312.pyc +│   │   │   │   │   │   ├── charmap.cpython-312.pyc +│   │   │   │   │   │   ├── cp037.cpython-312.pyc +│   │   │   │   │   │   ├── cp1006.cpython-312.pyc +│   │   │   │   │   │   ├── cp1026.cpython-312.pyc +│   │   │   │   │   │   ├── cp1125.cpython-312.pyc +│   │   │   │   │   │   ├── cp1140.cpython-312.pyc +│   │   │   │   │   │   ├── cp1250.cpython-312.pyc +│   │   │   │   │   │   ├── cp1251.cpython-312.pyc +│   │   │   │   │   │   ├── cp1252.cpython-312.pyc +│   │   │   │   │   │   ├── cp1253.cpython-312.pyc +│   │   │   │   │   │   ├── cp1254.cpython-312.pyc +│   │   │   │   │   │   ├── cp1255.cpython-312.pyc +│   │   │   │   │   │   ├── cp1256.cpython-312.pyc +│   │   │   │   │   │   ├── cp1257.cpython-312.pyc +│   │   │   │   │   │   ├── cp1258.cpython-312.pyc +│   │   │   │   │   │   ├── cp273.cpython-312.pyc +│   │   │   │   │   │   ├── cp424.cpython-312.pyc +│   │   │   │   │   │   ├── cp437.cpython-312.pyc +│   │   │   │   │   │   ├── cp500.cpython-312.pyc +│   │   │   │   │   │   ├── cp720.cpython-312.pyc +│   │   │   │   │   │   ├── cp737.cpython-312.pyc +│   │   │   │   │   │   ├── cp775.cpython-312.pyc +│   │   │   │   │   │   ├── cp850.cpython-312.pyc +│   │   │   │   │   │   ├── cp852.cpython-312.pyc +│   │   │   │   │   │   ├── cp855.cpython-312.pyc +│   │   │   │   │   │   ├── cp856.cpython-312.pyc +│   │   │   │   │   │   ├── cp857.cpython-312.pyc +│   │   │   │   │   │   ├── cp858.cpython-312.pyc +│   │   │   │   │   │   ├── cp860.cpython-312.pyc +│   │   │   │   │   │   ├── cp861.cpython-312.pyc +│   │   │   │   │   │   ├── cp862.cpython-312.pyc +│   │   │   │   │   │   ├── cp863.cpython-312.pyc +│   │   │   │   │   │   ├── cp864.cpython-312.pyc +│   │   │   │   │   │   ├── cp865.cpython-312.pyc +│   │   │   │   │   │   ├── cp866.cpython-312.pyc +│   │   │   │   │   │   ├── cp869.cpython-312.pyc +│   │   │   │   │   │   ├── cp874.cpython-312.pyc +│   │   │   │   │   │   ├── cp875.cpython-312.pyc +│   │   │   │   │   │   ├── cp932.cpython-312.pyc +│   │   │   │   │   │   ├── cp949.cpython-312.pyc +│   │   │   │   │   │   ├── cp950.cpython-312.pyc +│   │   │   │   │   │   ├── euc_jis_2004.cpython-312.pyc +│   │   │   │   │   │   ├── euc_jisx0213.cpython-312.pyc +│   │   │   │   │   │   ├── euc_jp.cpython-312.pyc +│   │   │   │   │   │   ├── euc_kr.cpython-312.pyc +│   │   │   │   │   │   ├── gb18030.cpython-312.pyc +│   │   │   │   │   │   ├── gb2312.cpython-312.pyc +│   │   │   │   │   │   ├── gbk.cpython-312.pyc +│   │   │   │   │   │   ├── hex_codec.cpython-312.pyc +│   │   │   │   │   │   ├── hp_roman8.cpython-312.pyc +│   │   │   │   │   │   ├── hz.cpython-312.pyc +│   │   │   │   │   │   ├── idna.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── iso2022_jp_1.cpython-312.pyc +│   │   │   │   │   │   ├── iso2022_jp_2004.cpython-312.pyc +│   │   │   │   │   │   ├── iso2022_jp_2.cpython-312.pyc +│   │   │   │   │   │   ├── iso2022_jp_3.cpython-312.pyc +│   │   │   │   │   │   ├── iso2022_jp.cpython-312.pyc +│   │   │   │   │   │   ├── iso2022_jp_ext.cpython-312.pyc +│   │   │   │   │   │   ├── iso2022_kr.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_10.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_11.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_13.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_14.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_15.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_16.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_1.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_2.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_3.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_4.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_5.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_6.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_7.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_8.cpython-312.pyc +│   │   │   │   │   │   ├── iso8859_9.cpython-312.pyc +│   │   │   │   │   │   ├── johab.cpython-312.pyc +│   │   │   │   │   │   ├── koi8_r.cpython-312.pyc +│   │   │   │   │   │   ├── koi8_t.cpython-312.pyc +│   │   │   │   │   │   ├── koi8_u.cpython-312.pyc +│   │   │   │   │   │   ├── kz1048.cpython-312.pyc +│   │   │   │   │   │   ├── latin_1.cpython-312.pyc +│   │   │   │   │   │   ├── mac_arabic.cpython-312.pyc +│   │   │   │   │   │   ├── mac_croatian.cpython-312.pyc +│   │   │   │   │   │   ├── mac_cyrillic.cpython-312.pyc +│   │   │   │   │   │   ├── mac_farsi.cpython-312.pyc +│   │   │   │   │   │   ├── mac_greek.cpython-312.pyc +│   │   │   │   │   │   ├── mac_iceland.cpython-312.pyc +│   │   │   │   │   │   ├── mac_latin2.cpython-312.pyc +│   │   │   │   │   │   ├── mac_roman.cpython-312.pyc +│   │   │   │   │   │   ├── mac_romanian.cpython-312.pyc +│   │   │   │   │   │   ├── mac_turkish.cpython-312.pyc +│   │   │   │   │   │   ├── mbcs.cpython-312.pyc +│   │   │   │   │   │   ├── oem.cpython-312.pyc +│   │   │   │   │   │   ├── palmos.cpython-312.pyc +│   │   │   │   │   │   ├── ptcp154.cpython-312.pyc +│   │   │   │   │   │   ├── punycode.cpython-312.pyc +│   │   │   │   │   │   ├── quopri_codec.cpython-312.pyc +│   │   │   │   │   │   ├── raw_unicode_escape.cpython-312.pyc +│   │   │   │   │   │   ├── rot_13.cpython-312.pyc +│   │   │   │   │   │   ├── shift_jis_2004.cpython-312.pyc +│   │   │   │   │   │   ├── shift_jis.cpython-312.pyc +│   │   │   │   │   │   ├── shift_jisx0213.cpython-312.pyc +│   │   │   │   │   │   ├── tis_620.cpython-312.pyc +│   │   │   │   │   │   ├── undefined.cpython-312.pyc +│   │   │   │   │   │   ├── unicode_escape.cpython-312.pyc +│   │   │   │   │   │   ├── utf_16_be.cpython-312.pyc +│   │   │   │   │   │   ├── utf_16.cpython-312.pyc +│   │   │   │   │   │   ├── utf_16_le.cpython-312.pyc +│   │   │   │   │   │   ├── utf_32_be.cpython-312.pyc +│   │   │   │   │   │   ├── utf_32.cpython-312.pyc +│   │   │   │   │   │   ├── utf_32_le.cpython-312.pyc +│   │   │   │   │   │   ├── utf_7.cpython-312.pyc +│   │   │   │   │   │   ├── utf_8.cpython-312.pyc +│   │   │   │   │   │   ├── utf_8_sig.cpython-312.pyc +│   │   │   │   │   │   ├── uu_codec.cpython-312.pyc +│   │   │   │   │   │   └── zlib_codec.cpython-312.pyc +│   │   │   │   │   ├── quopri_codec.py +│   │   │   │   │   ├── raw_unicode_escape.py +│   │   │   │   │   ├── rot_13.py +│   │   │   │   │   ├── shift_jis_2004.py +│   │   │   │   │   ├── shift_jis.py +│   │   │   │   │   ├── shift_jisx0213.py +│   │   │   │   │   ├── tis_620.py +│   │   │   │   │   ├── undefined.py +│   │   │   │   │   ├── unicode_escape.py +│   │   │   │   │   ├── utf_16_be.py +│   │   │   │   │   ├── utf_16_le.py +│   │   │   │   │   ├── utf_16.py +│   │   │   │   │   ├── utf_32_be.py +│   │   │   │   │   ├── utf_32_le.py +│   │   │   │   │   ├── utf_32.py +│   │   │   │   │   ├── utf_7.py +│   │   │   │   │   ├── utf_8.py +│   │   │   │   │   ├── utf_8_sig.py +│   │   │   │   │   ├── uu_codec.py +│   │   │   │   │   └── zlib_codec.py +│   │   │   │   ├── ensurepip +│   │   │   │   │   ├── _bundled +│   │   │   │   │   │   └── pip-25.0.1-py3-none-any.whl +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── __main__.cpython-312.pyc +│   │   │   │   │   │   └── _uninstall.cpython-312.pyc +│   │   │   │   │   └── _uninstall.py +│   │   │   │   ├── enum.py +│   │   │   │   ├── filecmp.py +│   │   │   │   ├── fileinput.py +│   │   │   │   ├── fnmatch.py +│   │   │   │   ├── fractions.py +│   │   │   │   ├── ftplib.py +│   │   │   │   ├── functools.py +│   │   │   │   ├── __future__.py +│   │   │   │   ├── genericpath.py +│   │   │   │   ├── getopt.py +│   │   │   │   ├── getpass.py +│   │   │   │   ├── gettext.py +│   │   │   │   ├── glob.py +│   │   │   │   ├── graphlib.py +│   │   │   │   ├── gzip.py +│   │   │   │   ├── hashlib.py +│   │   │   │   ├── heapq.py +│   │   │   │   ├── __hello__.py +│   │   │   │   ├── hmac.py +│   │   │   │   ├── html +│   │   │   │   │   ├── entities.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── parser.py +│   │   │   │   │   └── __pycache__ +│   │   │   │   │   ├── entities.cpython-312.pyc +│   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   └── parser.cpython-312.pyc +│   │   │   │   ├── http +│   │   │   │   │   ├── client.py +│   │   │   │   │   ├── cookiejar.py +│   │   │   │   │   ├── cookies.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── client.cpython-312.pyc +│   │   │   │   │   │   ├── cookiejar.cpython-312.pyc +│   │   │   │   │   │   ├── cookies.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   └── server.cpython-312.pyc +│   │   │   │   │   └── server.py +│   │   │   │   ├── idlelib +│   │   │   │   │   ├── autocomplete.py +│   │   │   │   │   ├── autocomplete_w.py +│   │   │   │   │   ├── autoexpand.py +│   │   │   │   │   ├── browser.py +│   │   │   │   │   ├── calltip.py +│   │   │   │   │   ├── calltip_w.py +│   │   │   │   │   ├── ChangeLog +│   │   │   │   │   ├── codecontext.py +│   │   │   │   │   ├── colorizer.py +│   │   │   │   │   ├── configdialog.py +│   │   │   │   │   ├── config-extensions.def +│   │   │   │   │   ├── config-highlight.def +│   │   │   │   │   ├── config_key.py +│   │   │   │   │   ├── config-keys.def +│   │   │   │   │   ├── config-main.def +│   │   │   │   │   ├── config.py +│   │   │   │   │   ├── CREDITS.txt +│   │   │   │   │   ├── debugger.py +│   │   │   │   │   ├── debugger_r.py +│   │   │   │   │   ├── debugobj.py +│   │   │   │   │   ├── debugobj_r.py +│   │   │   │   │   ├── delegator.py +│   │   │   │   │   ├── dynoption.py +│   │   │   │   │   ├── editor.py +│   │   │   │   │   ├── extend.txt +│   │   │   │   │   ├── filelist.py +│   │   │   │   │   ├── format.py +│   │   │   │   │   ├── grep.py +│   │   │   │   │   ├── help_about.py +│   │   │   │   │   ├── help.html +│   │   │   │   │   ├── help.py +│   │   │   │   │   ├── history.py +│   │   │   │   │   ├── HISTORY.txt +│   │   │   │   │   ├── hyperparser.py +│   │   │   │   │   ├── Icons +│   │   │   │   │   │   ├── folder.gif +│   │   │   │   │   │   ├── idle_16.gif +│   │   │   │   │   │   ├── idle_16.png +│   │   │   │   │   │   ├── idle_256.png +│   │   │   │   │   │   ├── idle_32.gif +│   │   │   │   │   │   ├── idle_32.png +│   │   │   │   │   │   ├── idle_48.gif +│   │   │   │   │   │   ├── idle_48.png +│   │   │   │   │   │   ├── idle.ico +│   │   │   │   │   │   ├── minusnode.gif +│   │   │   │   │   │   ├── openfolder.gif +│   │   │   │   │   │   ├── plusnode.gif +│   │   │   │   │   │   ├── python.gif +│   │   │   │   │   │   ├── README.txt +│   │   │   │   │   │   └── tk.gif +│   │   │   │   │   ├── idle.bat +│   │   │   │   │   ├── idle.py +│   │   │   │   │   ├── idle.pyw +│   │   │   │   │   ├── idle_test +│   │   │   │   │   │   ├── example_noext +│   │   │   │   │   │   ├── example_stub.pyi +│   │   │   │   │   │   ├── htest.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── mock_idle.py +│   │   │   │   │   │   ├── mock_tk.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── htest.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── mock_idle.cpython-312.pyc +│   │   │   │   │   │   │   ├── mock_tk.cpython-312.pyc +│   │   │   │   │   │   │   ├── template.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_autocomplete.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_autocomplete_w.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_autoexpand.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_browser.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_calltip.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_calltip_w.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_codecontext.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_colorizer.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_config.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_configdialog.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_config_key.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_debugger.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_debugger_r.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_debugobj.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_debugobj_r.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_delegator.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_editmenu.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_editor.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_filelist.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_format.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_grep.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_help_about.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_help.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_history.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_hyperparser.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_iomenu.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_macosx.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_mainmenu.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_multicall.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_outwin.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_parenmatch.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_pathbrowser.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_percolator.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_pyparse.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_pyshell.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_query.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_redirector.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_replace.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_rpc.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_run.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_runscript.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_scrolledlist.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_searchbase.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_search.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_searchengine.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_sidebar.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_squeezer.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_stackviewer.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_statusbar.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_text.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_textview.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_tooltip.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_tree.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_undo.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_util.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_warning.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_window.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_zoomheight.cpython-312.pyc +│   │   │   │   │   │   │   ├── test_zzdummy.cpython-312.pyc +│   │   │   │   │   │   │   └── tkinter_testing_utils.cpython-312.pyc +│   │   │   │   │   │   ├── README.txt +│   │   │   │   │   │   ├── template.py +│   │   │   │   │   │   ├── test_autocomplete.py +│   │   │   │   │   │   ├── test_autocomplete_w.py +│   │   │   │   │   │   ├── test_autoexpand.py +│   │   │   │   │   │   ├── test_browser.py +│   │   │   │   │   │   ├── test_calltip.py +│   │   │   │   │   │   ├── test_calltip_w.py +│   │   │   │   │   │   ├── test_codecontext.py +│   │   │   │   │   │   ├── test_colorizer.py +│   │   │   │   │   │   ├── test_configdialog.py +│   │   │   │   │   │   ├── test_config_key.py +│   │   │   │   │   │   ├── test_config.py +│   │   │   │   │   │   ├── test_debugger.py +│   │   │   │   │   │   ├── test_debugger_r.py +│   │   │   │   │   │   ├── test_debugobj.py +│   │   │   │   │   │   ├── test_debugobj_r.py +│   │   │   │   │   │   ├── test_delegator.py +│   │   │   │   │   │   ├── test_editmenu.py +│   │   │   │   │   │   ├── test_editor.py +│   │   │   │   │   │   ├── test_filelist.py +│   │   │   │   │   │   ├── test_format.py +│   │   │   │   │   │   ├── test_grep.py +│   │   │   │   │   │   ├── test_help_about.py +│   │   │   │   │   │   ├── test_help.py +│   │   │   │   │   │   ├── test_history.py +│   │   │   │   │   │   ├── test_hyperparser.py +│   │   │   │   │   │   ├── test_iomenu.py +│   │   │   │   │   │   ├── test_macosx.py +│   │   │   │   │   │   ├── test_mainmenu.py +│   │   │   │   │   │   ├── test_multicall.py +│   │   │   │   │   │   ├── test_outwin.py +│   │   │   │   │   │   ├── test_parenmatch.py +│   │   │   │   │   │   ├── test_pathbrowser.py +│   │   │   │   │   │   ├── test_percolator.py +│   │   │   │   │   │   ├── test_pyparse.py +│   │   │   │   │   │   ├── test_pyshell.py +│   │   │   │   │   │   ├── test_query.py +│   │   │   │   │   │   ├── test_redirector.py +│   │   │   │   │   │   ├── test_replace.py +│   │   │   │   │   │   ├── test_rpc.py +│   │   │   │   │   │   ├── test_run.py +│   │   │   │   │   │   ├── test_runscript.py +│   │   │   │   │   │   ├── test_scrolledlist.py +│   │   │   │   │   │   ├── test_searchbase.py +│   │   │   │   │   │   ├── test_searchengine.py +│   │   │   │   │   │   ├── test_search.py +│   │   │   │   │   │   ├── test_sidebar.py +│   │   │   │   │   │   ├── test_squeezer.py +│   │   │   │   │   │   ├── test_stackviewer.py +│   │   │   │   │   │   ├── test_statusbar.py +│   │   │   │   │   │   ├── test_text.py +│   │   │   │   │   │   ├── test_textview.py +│   │   │   │   │   │   ├── test_tooltip.py +│   │   │   │   │   │   ├── test_tree.py +│   │   │   │   │   │   ├── test_undo.py +│   │   │   │   │   │   ├── test_util.py +│   │   │   │   │   │   ├── test_warning.py +│   │   │   │   │   │   ├── test_window.py +│   │   │   │   │   │   ├── test_zoomheight.py +│   │   │   │   │   │   ├── test_zzdummy.py +│   │   │   │   │   │   └── tkinter_testing_utils.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── iomenu.py +│   │   │   │   │   ├── macosx.py +│   │   │   │   │   ├── mainmenu.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── multicall.py +│   │   │   │   │   ├── NEWS2x.txt +│   │   │   │   │   ├── News3.txt +│   │   │   │   │   ├── outwin.py +│   │   │   │   │   ├── parenmatch.py +│   │   │   │   │   ├── pathbrowser.py +│   │   │   │   │   ├── percolator.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── autocomplete.cpython-312.pyc +│   │   │   │   │   │   ├── autocomplete_w.cpython-312.pyc +│   │   │   │   │   │   ├── autoexpand.cpython-312.pyc +│   │   │   │   │   │   ├── browser.cpython-312.pyc +│   │   │   │   │   │   ├── calltip.cpython-312.pyc +│   │   │   │   │   │   ├── calltip_w.cpython-312.pyc +│   │   │   │   │   │   ├── codecontext.cpython-312.pyc +│   │   │   │   │   │   ├── colorizer.cpython-312.pyc +│   │   │   │   │   │   ├── config.cpython-312.pyc +│   │   │   │   │   │   ├── configdialog.cpython-312.pyc +│   │   │   │   │   │   ├── config_key.cpython-312.pyc +│   │   │   │   │   │   ├── debugger.cpython-312.pyc +│   │   │   │   │   │   ├── debugger_r.cpython-312.pyc +│   │   │   │   │   │   ├── debugobj.cpython-312.pyc +│   │   │   │   │   │   ├── debugobj_r.cpython-312.pyc +│   │   │   │   │   │   ├── delegator.cpython-312.pyc +│   │   │   │   │   │   ├── dynoption.cpython-312.pyc +│   │   │   │   │   │   ├── editor.cpython-312.pyc +│   │   │   │   │   │   ├── filelist.cpython-312.pyc +│   │   │   │   │   │   ├── format.cpython-312.pyc +│   │   │   │   │   │   ├── grep.cpython-312.pyc +│   │   │   │   │   │   ├── help_about.cpython-312.pyc +│   │   │   │   │   │   ├── help.cpython-312.pyc +│   │   │   │   │   │   ├── history.cpython-312.pyc +│   │   │   │   │   │   ├── hyperparser.cpython-312.pyc +│   │   │   │   │   │   ├── idle.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── iomenu.cpython-312.pyc +│   │   │   │   │   │   ├── macosx.cpython-312.pyc +│   │   │   │   │   │   ├── __main__.cpython-312.pyc +│   │   │   │   │   │   ├── mainmenu.cpython-312.pyc +│   │   │   │   │   │   ├── multicall.cpython-312.pyc +│   │   │   │   │   │   ├── outwin.cpython-312.pyc +│   │   │   │   │   │   ├── parenmatch.cpython-312.pyc +│   │   │   │   │   │   ├── pathbrowser.cpython-312.pyc +│   │   │   │   │   │   ├── percolator.cpython-312.pyc +│   │   │   │   │   │   ├── pyparse.cpython-312.pyc +│   │   │   │   │   │   ├── pyshell.cpython-312.pyc +│   │   │   │   │   │   ├── query.cpython-312.pyc +│   │   │   │   │   │   ├── redirector.cpython-312.pyc +│   │   │   │   │   │   ├── replace.cpython-312.pyc +│   │   │   │   │   │   ├── rpc.cpython-312.pyc +│   │   │   │   │   │   ├── run.cpython-312.pyc +│   │   │   │   │   │   ├── runscript.cpython-312.pyc +│   │   │   │   │   │   ├── scrolledlist.cpython-312.pyc +│   │   │   │   │   │   ├── searchbase.cpython-312.pyc +│   │   │   │   │   │   ├── search.cpython-312.pyc +│   │   │   │   │   │   ├── searchengine.cpython-312.pyc +│   │   │   │   │   │   ├── sidebar.cpython-312.pyc +│   │   │   │   │   │   ├── squeezer.cpython-312.pyc +│   │   │   │   │   │   ├── stackviewer.cpython-312.pyc +│   │   │   │   │   │   ├── statusbar.cpython-312.pyc +│   │   │   │   │   │   ├── textview.cpython-312.pyc +│   │   │   │   │   │   ├── tooltip.cpython-312.pyc +│   │   │   │   │   │   ├── tree.cpython-312.pyc +│   │   │   │   │   │   ├── undo.cpython-312.pyc +│   │   │   │   │   │   ├── util.cpython-312.pyc +│   │   │   │   │   │   ├── window.cpython-312.pyc +│   │   │   │   │   │   ├── zoomheight.cpython-312.pyc +│   │   │   │   │   │   └── zzdummy.cpython-312.pyc +│   │   │   │   │   ├── pyparse.py +│   │   │   │   │   ├── pyshell.py +│   │   │   │   │   ├── query.py +│   │   │   │   │   ├── README.txt +│   │   │   │   │   ├── redirector.py +│   │   │   │   │   ├── replace.py +│   │   │   │   │   ├── rpc.py +│   │   │   │   │   ├── run.py +│   │   │   │   │   ├── runscript.py +│   │   │   │   │   ├── scrolledlist.py +│   │   │   │   │   ├── searchbase.py +│   │   │   │   │   ├── searchengine.py +│   │   │   │   │   ├── search.py +│   │   │   │   │   ├── sidebar.py +│   │   │   │   │   ├── squeezer.py +│   │   │   │   │   ├── stackviewer.py +│   │   │   │   │   ├── statusbar.py +│   │   │   │   │   ├── textview.py +│   │   │   │   │   ├── TODO.txt +│   │   │   │   │   ├── tooltip.py +│   │   │   │   │   ├── tree.py +│   │   │   │   │   ├── undo.py +│   │   │   │   │   ├── util.py +│   │   │   │   │   ├── window.py +│   │   │   │   │   ├── zoomheight.py +│   │   │   │   │   └── zzdummy.py +│   │   │   │   ├── imaplib.py +│   │   │   │   ├── imghdr.py +│   │   │   │   ├── importlib +│   │   │   │   │   ├── _abc.py +│   │   │   │   │   ├── abc.py +│   │   │   │   │   ├── _bootstrap_external.py +│   │   │   │   │   ├── _bootstrap.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── machinery.py +│   │   │   │   │   ├── metadata +│   │   │   │   │   │   ├── _adapters.py +│   │   │   │   │   │   ├── _collections.py +│   │   │   │   │   │   ├── _functools.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── _itertools.py +│   │   │   │   │   │   ├── _meta.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── _adapters.cpython-312.pyc +│   │   │   │   │   │   │   ├── _collections.cpython-312.pyc +│   │   │   │   │   │   │   ├── _functools.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── _itertools.cpython-312.pyc +│   │   │   │   │   │   │   ├── _meta.cpython-312.pyc +│   │   │   │   │   │   │   └── _text.cpython-312.pyc +│   │   │   │   │   │   └── _text.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── _abc.cpython-312.pyc +│   │   │   │   │   │   ├── abc.cpython-312.pyc +│   │   │   │   │   │   ├── _bootstrap.cpython-312.pyc +│   │   │   │   │   │   ├── _bootstrap_external.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── machinery.cpython-312.pyc +│   │   │   │   │   │   ├── readers.cpython-312.pyc +│   │   │   │   │   │   ├── simple.cpython-312.pyc +│   │   │   │   │   │   └── util.cpython-312.pyc +│   │   │   │   │   ├── readers.py +│   │   │   │   │   ├── resources +│   │   │   │   │   │   ├── abc.py +│   │   │   │   │   │   ├── _adapters.py +│   │   │   │   │   │   ├── _common.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── _itertools.py +│   │   │   │   │   │   ├── _legacy.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── abc.cpython-312.pyc +│   │   │   │   │   │   │   ├── _adapters.cpython-312.pyc +│   │   │   │   │   │   │   ├── _common.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── _itertools.cpython-312.pyc +│   │   │   │   │   │   │   ├── _legacy.cpython-312.pyc +│   │   │   │   │   │   │   ├── readers.cpython-312.pyc +│   │   │   │   │   │   │   └── simple.cpython-312.pyc +│   │   │   │   │   │   ├── readers.py +│   │   │   │   │   │   └── simple.py +│   │   │   │   │   ├── simple.py +│   │   │   │   │   └── util.py +│   │   │   │   ├── inspect.py +│   │   │   │   ├── io.py +│   │   │   │   ├── ipaddress.py +│   │   │   │   ├── json +│   │   │   │   │   ├── decoder.py +│   │   │   │   │   ├── encoder.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── decoder.cpython-312.pyc +│   │   │   │   │   │   ├── encoder.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── scanner.cpython-312.pyc +│   │   │   │   │   │   └── tool.cpython-312.pyc +│   │   │   │   │   ├── scanner.py +│   │   │   │   │   └── tool.py +│   │   │   │   ├── keyword.py +│   │   │   │   ├── lib2to3 +│   │   │   │   │   ├── btm_matcher.py +│   │   │   │   │   ├── btm_utils.py +│   │   │   │   │   ├── fixer_base.py +│   │   │   │   │   ├── fixer_util.py +│   │   │   │   │   ├── fixes +│   │   │   │   │   │   ├── fix_apply.py +│   │   │   │   │   │   ├── fix_asserts.py +│   │   │   │   │   │   ├── fix_basestring.py +│   │   │   │   │   │   ├── fix_buffer.py +│   │   │   │   │   │   ├── fix_dict.py +│   │   │   │   │   │   ├── fix_except.py +│   │   │   │   │   │   ├── fix_execfile.py +│   │   │   │   │   │   ├── fix_exec.py +│   │   │   │   │   │   ├── fix_exitfunc.py +│   │   │   │   │   │   ├── fix_filter.py +│   │   │   │   │   │   ├── fix_funcattrs.py +│   │   │   │   │   │   ├── fix_future.py +│   │   │   │   │   │   ├── fix_getcwdu.py +│   │   │   │   │   │   ├── fix_has_key.py +│   │   │   │   │   │   ├── fix_idioms.py +│   │   │   │   │   │   ├── fix_import.py +│   │   │   │   │   │   ├── fix_imports2.py +│   │   │   │   │   │   ├── fix_imports.py +│   │   │   │   │   │   ├── fix_input.py +│   │   │   │   │   │   ├── fix_intern.py +│   │   │   │   │   │   ├── fix_isinstance.py +│   │   │   │   │   │   ├── fix_itertools_imports.py +│   │   │   │   │   │   ├── fix_itertools.py +│   │   │   │   │   │   ├── fix_long.py +│   │   │   │   │   │   ├── fix_map.py +│   │   │   │   │   │   ├── fix_metaclass.py +│   │   │   │   │   │   ├── fix_methodattrs.py +│   │   │   │   │   │   ├── fix_ne.py +│   │   │   │   │   │   ├── fix_next.py +│   │   │   │   │   │   ├── fix_nonzero.py +│   │   │   │   │   │   ├── fix_numliterals.py +│   │   │   │   │   │   ├── fix_operator.py +│   │   │   │   │   │   ├── fix_paren.py +│   │   │   │   │   │   ├── fix_print.py +│   │   │   │   │   │   ├── fix_raise.py +│   │   │   │   │   │   ├── fix_raw_input.py +│   │   │   │   │   │   ├── fix_reduce.py +│   │   │   │   │   │   ├── fix_reload.py +│   │   │   │   │   │   ├── fix_renames.py +│   │   │   │   │   │   ├── fix_repr.py +│   │   │   │   │   │   ├── fix_set_literal.py +│   │   │   │   │   │   ├── fix_standarderror.py +│   │   │   │   │   │   ├── fix_sys_exc.py +│   │   │   │   │   │   ├── fix_throw.py +│   │   │   │   │   │   ├── fix_tuple_params.py +│   │   │   │   │   │   ├── fix_types.py +│   │   │   │   │   │   ├── fix_unicode.py +│   │   │   │   │   │   ├── fix_urllib.py +│   │   │   │   │   │   ├── fix_ws_comma.py +│   │   │   │   │   │   ├── fix_xrange.py +│   │   │   │   │   │   ├── fix_xreadlines.py +│   │   │   │   │   │   ├── fix_zip.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   ├── fix_apply.cpython-312.pyc +│   │   │   │   │   │   ├── fix_asserts.cpython-312.pyc +│   │   │   │   │   │   ├── fix_basestring.cpython-312.pyc +│   │   │   │   │   │   ├── fix_buffer.cpython-312.pyc +│   │   │   │   │   │   ├── fix_dict.cpython-312.pyc +│   │   │   │   │   │   ├── fix_except.cpython-312.pyc +│   │   │   │   │   │   ├── fix_exec.cpython-312.pyc +│   │   │   │   │   │   ├── fix_execfile.cpython-312.pyc +│   │   │   │   │   │   ├── fix_exitfunc.cpython-312.pyc +│   │   │   │   │   │   ├── fix_filter.cpython-312.pyc +│   │   │   │   │   │   ├── fix_funcattrs.cpython-312.pyc +│   │   │   │   │   │   ├── fix_future.cpython-312.pyc +│   │   │   │   │   │   ├── fix_getcwdu.cpython-312.pyc +│   │   │   │   │   │   ├── fix_has_key.cpython-312.pyc +│   │   │   │   │   │   ├── fix_idioms.cpython-312.pyc +│   │   │   │   │   │   ├── fix_import.cpython-312.pyc +│   │   │   │   │   │   ├── fix_imports2.cpython-312.pyc +│   │   │   │   │   │   ├── fix_imports.cpython-312.pyc +│   │   │   │   │   │   ├── fix_input.cpython-312.pyc +│   │   │   │   │   │   ├── fix_intern.cpython-312.pyc +│   │   │   │   │   │   ├── fix_isinstance.cpython-312.pyc +│   │   │   │   │   │   ├── fix_itertools.cpython-312.pyc +│   │   │   │   │   │   ├── fix_itertools_imports.cpython-312.pyc +│   │   │   │   │   │   ├── fix_long.cpython-312.pyc +│   │   │   │   │   │   ├── fix_map.cpython-312.pyc +│   │   │   │   │   │   ├── fix_metaclass.cpython-312.pyc +│   │   │   │   │   │   ├── fix_methodattrs.cpython-312.pyc +│   │   │   │   │   │   ├── fix_ne.cpython-312.pyc +│   │   │   │   │   │   ├── fix_next.cpython-312.pyc +│   │   │   │   │   │   ├── fix_nonzero.cpython-312.pyc +│   │   │   │   │   │   ├── fix_numliterals.cpython-312.pyc +│   │   │   │   │   │   ├── fix_operator.cpython-312.pyc +│   │   │   │   │   │   ├── fix_paren.cpython-312.pyc +│   │   │   │   │   │   ├── fix_print.cpython-312.pyc +│   │   │   │   │   │   ├── fix_raise.cpython-312.pyc +│   │   │   │   │   │   ├── fix_raw_input.cpython-312.pyc +│   │   │   │   │   │   ├── fix_reduce.cpython-312.pyc +│   │   │   │   │   │   ├── fix_reload.cpython-312.pyc +│   │   │   │   │   │   ├── fix_renames.cpython-312.pyc +│   │   │   │   │   │   ├── fix_repr.cpython-312.pyc +│   │   │   │   │   │   ├── fix_set_literal.cpython-312.pyc +│   │   │   │   │   │   ├── fix_standarderror.cpython-312.pyc +│   │   │   │   │   │   ├── fix_sys_exc.cpython-312.pyc +│   │   │   │   │   │   ├── fix_throw.cpython-312.pyc +│   │   │   │   │   │   ├── fix_tuple_params.cpython-312.pyc +│   │   │   │   │   │   ├── fix_types.cpython-312.pyc +│   │   │   │   │   │   ├── fix_unicode.cpython-312.pyc +│   │   │   │   │   │   ├── fix_urllib.cpython-312.pyc +│   │   │   │   │   │   ├── fix_ws_comma.cpython-312.pyc +│   │   │   │   │   │   ├── fix_xrange.cpython-312.pyc +│   │   │   │   │   │   ├── fix_xreadlines.cpython-312.pyc +│   │   │   │   │   │   ├── fix_zip.cpython-312.pyc +│   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   ├── Grammar3.12.13.final.0.pickle +│   │   │   │   │   ├── Grammar.txt +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── main.py +│   │   │   │   │   ├── patcomp.py +│   │   │   │   │   ├── PatternGrammar3.12.13.final.0.pickle +│   │   │   │   │   ├── PatternGrammar.txt +│   │   │   │   │   ├── pgen2 +│   │   │   │   │   │   ├── conv.py +│   │   │   │   │   │   ├── driver.py +│   │   │   │   │   │   ├── grammar.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── literals.py +│   │   │   │   │   │   ├── parse.py +│   │   │   │   │   │   ├── pgen.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── conv.cpython-312.pyc +│   │   │   │   │   │   │   ├── driver.cpython-312.pyc +│   │   │   │   │   │   │   ├── grammar.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── literals.cpython-312.pyc +│   │   │   │   │   │   │   ├── parse.cpython-312.pyc +│   │   │   │   │   │   │   ├── pgen.cpython-312.pyc +│   │   │   │   │   │   │   ├── token.cpython-312.pyc +│   │   │   │   │   │   │   └── tokenize.cpython-312.pyc +│   │   │   │   │   │   ├── tokenize.py +│   │   │   │   │   │   └── token.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── btm_matcher.cpython-312.pyc +│   │   │   │   │   │   ├── btm_utils.cpython-312.pyc +│   │   │   │   │   │   ├── fixer_base.cpython-312.pyc +│   │   │   │   │   │   ├── fixer_util.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── __main__.cpython-312.pyc +│   │   │   │   │   │   ├── main.cpython-312.pyc +│   │   │   │   │   │   ├── patcomp.cpython-312.pyc +│   │   │   │   │   │   ├── pygram.cpython-312.pyc +│   │   │   │   │   │   ├── pytree.cpython-312.pyc +│   │   │   │   │   │   └── refactor.cpython-312.pyc +│   │   │   │   │   ├── pygram.py +│   │   │   │   │   ├── pytree.py +│   │   │   │   │   └── refactor.py +│   │   │   │   ├── lib-dynload +│   │   │   │   │   ├── array.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _asyncio.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── audioop.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── binascii.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _bisect.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _blake2.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _bz2.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── cmath.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _codecs_cn.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _codecs_hk.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _codecs_iso2022.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _codecs_jp.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _codecs_kr.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _codecs_tw.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _contextvars.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _crypt.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _csv.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _ctypes.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _ctypes_test.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _curses.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _curses_panel.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _datetime.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _decimal.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _elementtree.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── fcntl.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── grp.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _hashlib.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _heapq.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _json.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _lsprof.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _lzma.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── math.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _md5.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── mmap.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _multibytecodec.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _multiprocessing.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── nis.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _opcode.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── ossaudiodev.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _pickle.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _posixshmem.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _posixsubprocess.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── pyexpat.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _queue.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _random.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── readline.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── resource.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── select.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _sha1.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _sha2.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _sha3.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _socket.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── spwd.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _sqlite3.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _ssl.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _statistics.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _struct.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── syslog.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── termios.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _testbuffer.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _testcapi.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _testclinic.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _testimportmultiple.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _testinternalcapi.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _testmultiphase.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _testsinglephase.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _tkinter.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── unicodedata.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _uuid.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _xxinterpchannels.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── xxlimited_35.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── xxlimited.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _xxsubinterpreters.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── xxsubtype.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── _xxtestfuzz.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   ├── zlib.cpython-312-x86_64-linux-gnu.so +│   │   │   │   │   └── _zoneinfo.cpython-312-x86_64-linux-gnu.so +│   │   │   │   ├── LICENSE.txt +│   │   │   │   ├── linecache.py +│   │   │   │   ├── locale.py +│   │   │   │   ├── logging +│   │   │   │   │   ├── config.py +│   │   │   │   │   ├── handlers.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   └── __pycache__ +│   │   │   │   │   ├── config.cpython-312.pyc +│   │   │   │   │   ├── handlers.cpython-312.pyc +│   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   ├── lzma.py +│   │   │   │   ├── mailbox.py +│   │   │   │   ├── mailcap.py +│   │   │   │   ├── _markupbase.py +│   │   │   │   ├── mimetypes.py +│   │   │   │   ├── modulefinder.py +│   │   │   │   ├── multiprocessing +│   │   │   │   │   ├── connection.py +│   │   │   │   │   ├── context.py +│   │   │   │   │   ├── dummy +│   │   │   │   │   │   ├── connection.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   ├── connection.cpython-312.pyc +│   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   ├── forkserver.py +│   │   │   │   │   ├── heap.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── managers.py +│   │   │   │   │   ├── pool.py +│   │   │   │   │   ├── popen_fork.py +│   │   │   │   │   ├── popen_forkserver.py +│   │   │   │   │   ├── popen_spawn_posix.py +│   │   │   │   │   ├── popen_spawn_win32.py +│   │   │   │   │   ├── process.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── connection.cpython-312.pyc +│   │   │   │   │   │   ├── context.cpython-312.pyc +│   │   │   │   │   │   ├── forkserver.cpython-312.pyc +│   │   │   │   │   │   ├── heap.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── managers.cpython-312.pyc +│   │   │   │   │   │   ├── pool.cpython-312.pyc +│   │   │   │   │   │   ├── popen_fork.cpython-312.pyc +│   │   │   │   │   │   ├── popen_forkserver.cpython-312.pyc +│   │   │   │   │   │   ├── popen_spawn_posix.cpython-312.pyc +│   │   │   │   │   │   ├── popen_spawn_win32.cpython-312.pyc +│   │   │   │   │   │   ├── process.cpython-312.pyc +│   │   │   │   │   │   ├── queues.cpython-312.pyc +│   │   │   │   │   │   ├── reduction.cpython-312.pyc +│   │   │   │   │   │   ├── resource_sharer.cpython-312.pyc +│   │   │   │   │   │   ├── resource_tracker.cpython-312.pyc +│   │   │   │   │   │   ├── sharedctypes.cpython-312.pyc +│   │   │   │   │   │   ├── shared_memory.cpython-312.pyc +│   │   │   │   │   │   ├── spawn.cpython-312.pyc +│   │   │   │   │   │   ├── synchronize.cpython-312.pyc +│   │   │   │   │   │   └── util.cpython-312.pyc +│   │   │   │   │   ├── queues.py +│   │   │   │   │   ├── reduction.py +│   │   │   │   │   ├── resource_sharer.py +│   │   │   │   │   ├── resource_tracker.py +│   │   │   │   │   ├── sharedctypes.py +│   │   │   │   │   ├── shared_memory.py +│   │   │   │   │   ├── spawn.py +│   │   │   │   │   ├── synchronize.py +│   │   │   │   │   └── util.py +│   │   │   │   ├── netrc.py +│   │   │   │   ├── nntplib.py +│   │   │   │   ├── ntpath.py +│   │   │   │   ├── nturl2path.py +│   │   │   │   ├── numbers.py +│   │   │   │   ├── opcode.py +│   │   │   │   ├── operator.py +│   │   │   │   ├── optparse.py +│   │   │   │   ├── os.py +│   │   │   │   ├── _osx_support.py +│   │   │   │   ├── pathlib.py +│   │   │   │   ├── pdb.py +│   │   │   │   ├── __phello__ +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   └── spam.cpython-312.pyc +│   │   │   │   │   └── spam.py +│   │   │   │   ├── pickle.py +│   │   │   │   ├── pickletools.py +│   │   │   │   ├── pipes.py +│   │   │   │   ├── pkgutil.py +│   │   │   │   ├── platform.py +│   │   │   │   ├── plistlib.py +│   │   │   │   ├── poplib.py +│   │   │   │   ├── posixpath.py +│   │   │   │   ├── pprint.py +│   │   │   │   ├── profile.py +│   │   │   │   ├── pstats.py +│   │   │   │   ├── pty.py +│   │   │   │   ├── _py_abc.py +│   │   │   │   ├── __pycache__ +│   │   │   │   │   ├── abc.cpython-312.pyc +│   │   │   │   │   ├── aifc.cpython-312.pyc +│   │   │   │   │   ├── _aix_support.cpython-312.pyc +│   │   │   │   │   ├── antigravity.cpython-312.pyc +│   │   │   │   │   ├── argparse.cpython-312.pyc +│   │   │   │   │   ├── ast.cpython-312.pyc +│   │   │   │   │   ├── base64.cpython-312.pyc +│   │   │   │   │   ├── bdb.cpython-312.pyc +│   │   │   │   │   ├── bisect.cpython-312.pyc +│   │   │   │   │   ├── bz2.cpython-312.pyc +│   │   │   │   │   ├── calendar.cpython-312.pyc +│   │   │   │   │   ├── cgi.cpython-312.pyc +│   │   │   │   │   ├── cgitb.cpython-312.pyc +│   │   │   │   │   ├── chunk.cpython-312.pyc +│   │   │   │   │   ├── cmd.cpython-312.pyc +│   │   │   │   │   ├── code.cpython-312.pyc +│   │   │   │   │   ├── codecs.cpython-312.pyc +│   │   │   │   │   ├── codeop.cpython-312.pyc +│   │   │   │   │   ├── _collections_abc.cpython-312.pyc +│   │   │   │   │   ├── colorsys.cpython-312.pyc +│   │   │   │   │   ├── _compat_pickle.cpython-312.pyc +│   │   │   │   │   ├── compileall.cpython-312.pyc +│   │   │   │   │   ├── _compression.cpython-312.pyc +│   │   │   │   │   ├── configparser.cpython-312.pyc +│   │   │   │   │   ├── contextlib.cpython-312.pyc +│   │   │   │   │   ├── contextvars.cpython-312.pyc +│   │   │   │   │   ├── copy.cpython-312.pyc +│   │   │   │   │   ├── copyreg.cpython-312.pyc +│   │   │   │   │   ├── cProfile.cpython-312.pyc +│   │   │   │   │   ├── crypt.cpython-312.pyc +│   │   │   │   │   ├── csv.cpython-312.pyc +│   │   │   │   │   ├── dataclasses.cpython-312.pyc +│   │   │   │   │   ├── datetime.cpython-312.pyc +│   │   │   │   │   ├── decimal.cpython-312.pyc +│   │   │   │   │   ├── difflib.cpython-312.pyc +│   │   │   │   │   ├── dis.cpython-312.pyc +│   │   │   │   │   ├── doctest.cpython-312.pyc +│   │   │   │   │   ├── enum.cpython-312.pyc +│   │   │   │   │   ├── filecmp.cpython-312.pyc +│   │   │   │   │   ├── fileinput.cpython-312.pyc +│   │   │   │   │   ├── fnmatch.cpython-312.pyc +│   │   │   │   │   ├── fractions.cpython-312.pyc +│   │   │   │   │   ├── ftplib.cpython-312.pyc +│   │   │   │   │   ├── functools.cpython-312.pyc +│   │   │   │   │   ├── __future__.cpython-312.pyc +│   │   │   │   │   ├── genericpath.cpython-312.pyc +│   │   │   │   │   ├── getopt.cpython-312.pyc +│   │   │   │   │   ├── getpass.cpython-312.pyc +│   │   │   │   │   ├── gettext.cpython-312.pyc +│   │   │   │   │   ├── glob.cpython-312.pyc +│   │   │   │   │   ├── graphlib.cpython-312.pyc +│   │   │   │   │   ├── gzip.cpython-312.pyc +│   │   │   │   │   ├── hashlib.cpython-312.pyc +│   │   │   │   │   ├── heapq.cpython-312.pyc +│   │   │   │   │   ├── __hello__.cpython-312.pyc +│   │   │   │   │   ├── hmac.cpython-312.pyc +│   │   │   │   │   ├── imaplib.cpython-312.pyc +│   │   │   │   │   ├── imghdr.cpython-312.pyc +│   │   │   │   │   ├── inspect.cpython-312.pyc +│   │   │   │   │   ├── io.cpython-312.pyc +│   │   │   │   │   ├── ipaddress.cpython-312.pyc +│   │   │   │   │   ├── keyword.cpython-312.pyc +│   │   │   │   │   ├── linecache.cpython-312.pyc +│   │   │   │   │   ├── locale.cpython-312.pyc +│   │   │   │   │   ├── lzma.cpython-312.pyc +│   │   │   │   │   ├── mailbox.cpython-312.pyc +│   │   │   │   │   ├── mailcap.cpython-312.pyc +│   │   │   │   │   ├── _markupbase.cpython-312.pyc +│   │   │   │   │   ├── mimetypes.cpython-312.pyc +│   │   │   │   │   ├── modulefinder.cpython-312.pyc +│   │   │   │   │   ├── netrc.cpython-312.pyc +│   │   │   │   │   ├── nntplib.cpython-312.pyc +│   │   │   │   │   ├── ntpath.cpython-312.pyc +│   │   │   │   │   ├── nturl2path.cpython-312.pyc +│   │   │   │   │   ├── numbers.cpython-312.pyc +│   │   │   │   │   ├── opcode.cpython-312.pyc +│   │   │   │   │   ├── operator.cpython-312.pyc +│   │   │   │   │   ├── optparse.cpython-312.pyc +│   │   │   │   │   ├── os.cpython-312.pyc +│   │   │   │   │   ├── _osx_support.cpython-312.pyc +│   │   │   │   │   ├── pathlib.cpython-312.pyc +│   │   │   │   │   ├── pdb.cpython-312.pyc +│   │   │   │   │   ├── pickle.cpython-312.pyc +│   │   │   │   │   ├── pickletools.cpython-312.pyc +│   │   │   │   │   ├── pipes.cpython-312.pyc +│   │   │   │   │   ├── pkgutil.cpython-312.pyc +│   │   │   │   │   ├── platform.cpython-312.pyc +│   │   │   │   │   ├── plistlib.cpython-312.pyc +│   │   │   │   │   ├── poplib.cpython-312.pyc +│   │   │   │   │   ├── posixpath.cpython-312.pyc +│   │   │   │   │   ├── pprint.cpython-312.pyc +│   │   │   │   │   ├── profile.cpython-312.pyc +│   │   │   │   │   ├── pstats.cpython-312.pyc +│   │   │   │   │   ├── pty.cpython-312.pyc +│   │   │   │   │   ├── _py_abc.cpython-312.pyc +│   │   │   │   │   ├── pyclbr.cpython-312.pyc +│   │   │   │   │   ├── py_compile.cpython-312.pyc +│   │   │   │   │   ├── _pydatetime.cpython-312.pyc +│   │   │   │   │   ├── _pydecimal.cpython-312.pyc +│   │   │   │   │   ├── pydoc.cpython-312.pyc +│   │   │   │   │   ├── _pyio.cpython-312.pyc +│   │   │   │   │   ├── _pylong.cpython-312.pyc +│   │   │   │   │   ├── queue.cpython-312.pyc +│   │   │   │   │   ├── quopri.cpython-312.pyc +│   │   │   │   │   ├── random.cpython-312.pyc +│   │   │   │   │   ├── reprlib.cpython-312.pyc +│   │   │   │   │   ├── rlcompleter.cpython-312.pyc +│   │   │   │   │   ├── runpy.cpython-312.pyc +│   │   │   │   │   ├── sched.cpython-312.pyc +│   │   │   │   │   ├── secrets.cpython-312.pyc +│   │   │   │   │   ├── selectors.cpython-312.pyc +│   │   │   │   │   ├── shelve.cpython-312.pyc +│   │   │   │   │   ├── shlex.cpython-312.pyc +│   │   │   │   │   ├── shutil.cpython-312.pyc +│   │   │   │   │   ├── signal.cpython-312.pyc +│   │   │   │   │   ├── _sitebuiltins.cpython-312.pyc +│   │   │   │   │   ├── site.cpython-312.pyc +│   │   │   │   │   ├── smtplib.cpython-312.pyc +│   │   │   │   │   ├── sndhdr.cpython-312.pyc +│   │   │   │   │   ├── socket.cpython-312.pyc +│   │   │   │   │   ├── socketserver.cpython-312.pyc +│   │   │   │   │   ├── sre_compile.cpython-312.pyc +│   │   │   │   │   ├── sre_constants.cpython-312.pyc +│   │   │   │   │   ├── sre_parse.cpython-312.pyc +│   │   │   │   │   ├── ssl.cpython-312.pyc +│   │   │   │   │   ├── stat.cpython-312.pyc +│   │   │   │   │   ├── statistics.cpython-312.pyc +│   │   │   │   │   ├── string.cpython-312.pyc +│   │   │   │   │   ├── stringprep.cpython-312.pyc +│   │   │   │   │   ├── _strptime.cpython-312.pyc +│   │   │   │   │   ├── struct.cpython-312.pyc +│   │   │   │   │   ├── subprocess.cpython-312.pyc +│   │   │   │   │   ├── sunau.cpython-312.pyc +│   │   │   │   │   ├── symtable.cpython-312.pyc +│   │   │   │   │   ├── sysconfig.cpython-312.pyc +│   │   │   │   │   ├── _sysconfigdata__linux_x86_64-linux-gnu.cpython-312.pyc +│   │   │   │   │   ├── _sysconfigdata_x86_64_conda_linux_gnu.cpython-312.pyc +│   │   │   │   │   ├── tabnanny.cpython-312.pyc +│   │   │   │   │   ├── tarfile.cpython-312.pyc +│   │   │   │   │   ├── telnetlib.cpython-312.pyc +│   │   │   │   │   ├── tempfile.cpython-312.pyc +│   │   │   │   │   ├── textwrap.cpython-312.pyc +│   │   │   │   │   ├── this.cpython-312.pyc +│   │   │   │   │   ├── threading.cpython-312.pyc +│   │   │   │   │   ├── _threading_local.cpython-312.pyc +│   │   │   │   │   ├── timeit.cpython-312.pyc +│   │   │   │   │   ├── token.cpython-312.pyc +│   │   │   │   │   ├── tokenize.cpython-312.pyc +│   │   │   │   │   ├── traceback.cpython-312.pyc +│   │   │   │   │   ├── trace.cpython-312.pyc +│   │   │   │   │   ├── tracemalloc.cpython-312.pyc +│   │   │   │   │   ├── tty.cpython-312.pyc +│   │   │   │   │   ├── turtle.cpython-312.pyc +│   │   │   │   │   ├── types.cpython-312.pyc +│   │   │   │   │   ├── typing.cpython-312.pyc +│   │   │   │   │   ├── uu.cpython-312.pyc +│   │   │   │   │   ├── uuid.cpython-312.pyc +│   │   │   │   │   ├── warnings.cpython-312.pyc +│   │   │   │   │   ├── wave.cpython-312.pyc +│   │   │   │   │   ├── weakref.cpython-312.pyc +│   │   │   │   │   ├── _weakrefset.cpython-312.pyc +│   │   │   │   │   ├── webbrowser.cpython-312.pyc +│   │   │   │   │   ├── xdrlib.cpython-312.pyc +│   │   │   │   │   ├── zipapp.cpython-312.pyc +│   │   │   │   │   └── zipimport.cpython-312.pyc +│   │   │   │   ├── pyclbr.py +│   │   │   │   ├── py_compile.py +│   │   │   │   ├── _pydatetime.py +│   │   │   │   ├── _pydecimal.py +│   │   │   │   ├── pydoc_data +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   └── topics.cpython-312.pyc +│   │   │   │   │   ├── _pydoc.css +│   │   │   │   │   └── topics.py +│   │   │   │   ├── pydoc.py +│   │   │   │   ├── _pyio.py +│   │   │   │   ├── _pylong.py +│   │   │   │   ├── queue.py +│   │   │   │   ├── quopri.py +│   │   │   │   ├── random.py +│   │   │   │   ├── re +│   │   │   │   │   ├── _casefix.py +│   │   │   │   │   ├── _compiler.py +│   │   │   │   │   ├── _constants.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── _parser.py +│   │   │   │   │   └── __pycache__ +│   │   │   │   │   ├── _casefix.cpython-312.pyc +│   │   │   │   │   ├── _compiler.cpython-312.pyc +│   │   │   │   │   ├── _constants.cpython-312.pyc +│   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   └── _parser.cpython-312.pyc +│   │   │   │   ├── reprlib.py +│   │   │   │   ├── rlcompleter.py +│   │   │   │   ├── runpy.py +│   │   │   │   ├── sched.py +│   │   │   │   ├── secrets.py +│   │   │   │   ├── selectors.py +│   │   │   │   ├── shelve.py +│   │   │   │   ├── shlex.py +│   │   │   │   ├── shutil.py +│   │   │   │   ├── signal.py +│   │   │   │   ├── _sitebuiltins.py +│   │   │   │   ├── site-packages +│   │   │   │   │   ├── click +│   │   │   │   │   │   ├── _compat.py +│   │   │   │   │   │   ├── core.py +│   │   │   │   │   │   ├── decorators.py +│   │   │   │   │   │   ├── exceptions.py +│   │   │   │   │   │   ├── formatting.py +│   │   │   │   │   │   ├── globals.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── parser.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── _compat.cpython-312.pyc +│   │   │   │   │   │   │   ├── core.cpython-312.pyc +│   │   │   │   │   │   │   ├── decorators.cpython-312.pyc +│   │   │   │   │   │   │   ├── exceptions.cpython-312.pyc +│   │   │   │   │   │   │   ├── formatting.cpython-312.pyc +│   │   │   │   │   │   │   ├── globals.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── parser.cpython-312.pyc +│   │   │   │   │   │   │   ├── termui.cpython-312.pyc +│   │   │   │   │   │   │   ├── types.cpython-312.pyc +│   │   │   │   │   │   │   ├── _utils.cpython-312.pyc +│   │   │   │   │   │   │   └── utils.cpython-312.pyc +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── shell_completion.py +│   │   │   │   │   │   ├── _termui_impl.py +│   │   │   │   │   │   ├── termui.py +│   │   │   │   │   │   ├── testing.py +│   │   │   │   │   │   ├── _textwrap.py +│   │   │   │   │   │   ├── types.py +│   │   │   │   │   │   ├── _utils.py +│   │   │   │   │   │   ├── utils.py +│   │   │   │   │   │   └── _winconsole.py +│   │   │   │   │   ├── click-8.3.3.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE.txt +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── dateutil +│   │   │   │   │   │   ├── _common.py +│   │   │   │   │   │   ├── easter.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── parser +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── isoparser.py +│   │   │   │   │   │   │   └── _parser.py +│   │   │   │   │   │   ├── relativedelta.py +│   │   │   │   │   │   ├── rrule.py +│   │   │   │   │   │   ├── tz +│   │   │   │   │   │   │   ├── _common.py +│   │   │   │   │   │   │   ├── _factories.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── tz.py +│   │   │   │   │   │   │   └── win.py +│   │   │   │   │   │   ├── tzwin.py +│   │   │   │   │   │   ├── utils.py +│   │   │   │   │   │   ├── _version.py +│   │   │   │   │   │   └── zoneinfo +│   │   │   │   │   │   ├── dateutil-zoneinfo.tar.gz +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── rebuild.py +│   │   │   │   │   ├── google +│   │   │   │   │   │   ├── protobuf +│   │   │   │   │   │   │   ├── any_pb2.py +│   │   │   │   │   │   │   ├── any.py +│   │   │   │   │   │   │   ├── api_pb2.py +│   │   │   │   │   │   │   ├── compiler +│   │   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   │   └── plugin_pb2.py +│   │   │   │   │   │   │   ├── descriptor_database.py +│   │   │   │   │   │   │   ├── descriptor_pb2.py +│   │   │   │   │   │   │   ├── descriptor_pool.py +│   │   │   │   │   │   │   ├── descriptor.py +│   │   │   │   │   │   │   ├── duration_pb2.py +│   │   │   │   │   │   │   ├── duration.py +│   │   │   │   │   │   │   ├── empty_pb2.py +│   │   │   │   │   │   │   ├── field_mask_pb2.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── internal +│   │   │   │   │   │   │   │   ├── api_implementation.py +│   │   │   │   │   │   │   │   ├── builder.py +│   │   │   │   │   │   │   │   ├── containers.py +│   │   │   │   │   │   │   │   ├── decoder.py +│   │   │   │   │   │   │   │   ├── encoder.py +│   │   │   │   │   │   │   │   ├── enum_type_wrapper.py +│   │   │   │   │   │   │   │   ├── extension_dict.py +│   │   │   │   │   │   │   │   ├── field_mask.py +│   │   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   │   ├── message_listener.py +│   │   │   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   │   │   ├── api_implementation.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── builder.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── containers.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── decoder.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── encoder.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── enum_type_wrapper.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── extension_dict.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── field_mask.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── message_listener.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── python_edition_defaults.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── python_message.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── type_checkers.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── well_known_types.cpython-312.pyc +│   │   │   │   │   │   │   │   │   └── wire_format.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── python_edition_defaults.py +│   │   │   │   │   │   │   │   ├── python_message.py +│   │   │   │   │   │   │   │   ├── testing_refleaks.py +│   │   │   │   │   │   │   │   ├── type_checkers.py +│   │   │   │   │   │   │   │   ├── well_known_types.py +│   │   │   │   │   │   │   │   └── wire_format.py +│   │   │   │   │   │   │   ├── json_format.py +│   │   │   │   │   │   │   ├── message_factory.py +│   │   │   │   │   │   │   ├── message.py +│   │   │   │   │   │   │   ├── proto_builder.py +│   │   │   │   │   │   │   ├── proto_json.py +│   │   │   │   │   │   │   ├── proto.py +│   │   │   │   │   │   │   ├── proto_text.py +│   │   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   │   ├── descriptor.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── descriptor_database.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── descriptor_pool.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── message.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── message_factory.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── reflection.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── runtime_version.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── symbol_database.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── text_encoding.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── text_format.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── timestamp_pb2.cpython-312.pyc +│   │   │   │   │   │   │   │   └── unknown_fields.cpython-312.pyc +│   │   │   │   │   │   │   ├── pyext +│   │   │   │   │   │   │   │   ├── cpp_message.py +│   │   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   │   │   ├── cpp_message.cpython-312.pyc +│   │   │   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── reflection.py +│   │   │   │   │   │   │   ├── runtime_version.py +│   │   │   │   │   │   │   ├── service_reflection.py +│   │   │   │   │   │   │   ├── source_context_pb2.py +│   │   │   │   │   │   │   ├── struct_pb2.py +│   │   │   │   │   │   │   ├── symbol_database.py +│   │   │   │   │   │   │   ├── testdata +│   │   │   │   │   │   │   │   └── __init__.py +│   │   │   │   │   │   │   ├── text_encoding.py +│   │   │   │   │   │   │   ├── text_format.py +│   │   │   │   │   │   │   ├── timestamp_pb2.py +│   │   │   │   │   │   │   ├── timestamp.py +│   │   │   │   │   │   │   ├── type_pb2.py +│   │   │   │   │   │   │   ├── unknown_fields.py +│   │   │   │   │   │   │   ├── util +│   │   │   │   │   │   │   │   └── __init__.py +│   │   │   │   │   │   │   └── wrappers_pb2.py +│   │   │   │   │   │   └── _upb +│   │   │   │   │   │   └── _message.abi3.so +│   │   │   │   │   ├── google-stubs +│   │   │   │   │   │   ├── METADATA.toml +│   │   │   │   │   │   ├── protobuf +│   │   │   │   │   │   │   ├── any_pb2.pyi +│   │   │   │   │   │   │   ├── any.pyi +│   │   │   │   │   │   │   ├── api_pb2.pyi +│   │   │   │   │   │   │   ├── compiler +│   │   │   │   │   │   │   │   ├── __init__.pyi +│   │   │   │   │   │   │   │   └── plugin_pb2.pyi +│   │   │   │   │   │   │   ├── descriptor_database.pyi +│   │   │   │   │   │   │   ├── descriptor_pb2.pyi +│   │   │   │   │   │   │   ├── descriptor_pool.pyi +│   │   │   │   │   │   │   ├── descriptor.pyi +│   │   │   │   │   │   │   ├── duration_pb2.pyi +│   │   │   │   │   │   │   ├── duration.pyi +│   │   │   │   │   │   │   ├── empty_pb2.pyi +│   │   │   │   │   │   │   ├── field_mask_pb2.pyi +│   │   │   │   │   │   │   ├── __init__.pyi +│   │   │   │   │   │   │   ├── internal +│   │   │   │   │   │   │   │   ├── api_implementation.pyi +│   │   │   │   │   │   │   │   ├── builder.pyi +│   │   │   │   │   │   │   │   ├── containers.pyi +│   │   │   │   │   │   │   │   ├── decoder.pyi +│   │   │   │   │   │   │   │   ├── encoder.pyi +│   │   │   │   │   │   │   │   ├── enum_type_wrapper.pyi +│   │   │   │   │   │   │   │   ├── extension_dict.pyi +│   │   │   │   │   │   │   │   ├── field_mask.pyi +│   │   │   │   │   │   │   │   ├── __init__.pyi +│   │   │   │   │   │   │   │   ├── message_listener.pyi +│   │   │   │   │   │   │   │   ├── python_edition_defaults.pyi +│   │   │   │   │   │   │   │   ├── python_message.pyi +│   │   │   │   │   │   │   │   ├── testing_refleaks.pyi +│   │   │   │   │   │   │   │   ├── type_checkers.pyi +│   │   │   │   │   │   │   │   ├── well_known_types.pyi +│   │   │   │   │   │   │   │   └── wire_format.pyi +│   │   │   │   │   │   │   ├── json_format.pyi +│   │   │   │   │   │   │   ├── message_factory.pyi +│   │   │   │   │   │   │   ├── message.pyi +│   │   │   │   │   │   │   ├── proto_builder.pyi +│   │   │   │   │   │   │   ├── proto_json.pyi +│   │   │   │   │   │   │   ├── proto.pyi +│   │   │   │   │   │   │   ├── proto_text.pyi +│   │   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   │   ├── reflection.pyi +│   │   │   │   │   │   │   ├── runtime_version.pyi +│   │   │   │   │   │   │   ├── service_reflection.pyi +│   │   │   │   │   │   │   ├── source_context_pb2.pyi +│   │   │   │   │   │   │   ├── struct_pb2.pyi +│   │   │   │   │   │   │   ├── symbol_database.pyi +│   │   │   │   │   │   │   ├── text_encoding.pyi +│   │   │   │   │   │   │   ├── text_format.pyi +│   │   │   │   │   │   │   ├── timestamp_pb2.pyi +│   │   │   │   │   │   │   ├── timestamp.pyi +│   │   │   │   │   │   │   ├── type_pb2.pyi +│   │   │   │   │   │   │   ├── unknown_fields.pyi +│   │   │   │   │   │   │   ├── util +│   │   │   │   │   │   │   │   └── __init__.pyi +│   │   │   │   │   │   │   └── wrappers_pb2.pyi +│   │   │   │   │   │   └── _upb +│   │   │   │   │   │   └── _message.pyi +│   │   │   │   │   ├── importlib_metadata +│   │   │   │   │   │   ├── _adapters.py +│   │   │   │   │   │   ├── _collections.py +│   │   │   │   │   │   ├── compat +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   └── py311.py +│   │   │   │   │   │   ├── _compat.py +│   │   │   │   │   │   ├── diagnose.py +│   │   │   │   │   │   ├── _functools.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── _itertools.py +│   │   │   │   │   │   ├── _meta.py +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── _text.py +│   │   │   │   │   │   └── _typing.py +│   │   │   │   │   ├── importlib_metadata-8.8.0.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   ├── top_level.txt +│   │   │   │   │   │   ├── uv_build.json +│   │   │   │   │   │   ├── uv_cache.json +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── jupyter_client +│   │   │   │   │   │   ├── adapter.py +│   │   │   │   │   │   ├── asynchronous +│   │   │   │   │   │   │   ├── client.py +│   │   │   │   │   │   │   └── __init__.py +│   │   │   │   │   │   ├── blocking +│   │   │   │   │   │   │   ├── client.py +│   │   │   │   │   │   │   └── __init__.py +│   │   │   │   │   │   ├── channelsabc.py +│   │   │   │   │   │   ├── channels.py +│   │   │   │   │   │   ├── clientabc.py +│   │   │   │   │   │   ├── client.py +│   │   │   │   │   │   ├── connect.py +│   │   │   │   │   │   ├── consoleapp.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── ioloop +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── manager.py +│   │   │   │   │   │   │   └── restarter.py +│   │   │   │   │   │   ├── jsonutil.py +│   │   │   │   │   │   ├── kernelapp.py +│   │   │   │   │   │   ├── kernelspecapp.py +│   │   │   │   │   │   ├── kernelspec.py +│   │   │   │   │   │   ├── launcher.py +│   │   │   │   │   │   ├── localinterfaces.py +│   │   │   │   │   │   ├── managerabc.py +│   │   │   │   │   │   ├── manager.py +│   │   │   │   │   │   ├── multikernelmanager.py +│   │   │   │   │   │   ├── provisioning +│   │   │   │   │   │   │   ├── factory.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── local_provisioner.py +│   │   │   │   │   │   │   └── provisioner_base.py +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── restarter.py +│   │   │   │   │   │   ├── runapp.py +│   │   │   │   │   │   ├── session.py +│   │   │   │   │   │   ├── ssh +│   │   │   │   │   │   │   ├── forward.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   └── tunnel.py +│   │   │   │   │   │   ├── threaded.py +│   │   │   │   │   │   ├── utils.py +│   │   │   │   │   │   ├── _version.py +│   │   │   │   │   │   └── win_interrupt.py +│   │   │   │   │   ├── jupyter_client-8.6.3.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── entry_points.txt +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── jupyter_core +│   │   │   │   │   │   ├── application.py +│   │   │   │   │   │   ├── command.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── __main__.py +│   │   │   │   │   │   ├── migrate.py +│   │   │   │   │   │   ├── paths.py +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── troubleshoot.py +│   │   │   │   │   │   ├── utils +│   │   │   │   │   │   │   └── __init__.py +│   │   │   │   │   │   └── version.py +│   │   │   │   │   ├── jupyter_core-5.9.1.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── entry_points.txt +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── jupyter.py +│   │   │   │   │   ├── mblack +│   │   │   │   │   │   ├── brackets.py +│   │   │   │   │   │   ├── cache.py +│   │   │   │   │   │   ├── comments.py +│   │   │   │   │   │   ├── concurrency.py +│   │   │   │   │   │   ├── const.py +│   │   │   │   │   │   ├── debug.py +│   │   │   │   │   │   ├── files.py +│   │   │   │   │   │   ├── handle_ipynb_magics.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── linegen.py +│   │   │   │   │   │   ├── lines.py +│   │   │   │   │   │   ├── __main__.py +│   │   │   │   │   │   ├── mode.py +│   │   │   │   │   │   ├── nodes.py +│   │   │   │   │   │   ├── numerics.py +│   │   │   │   │   │   ├── output.py +│   │   │   │   │   │   ├── parsing.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── brackets.cpython-312.pyc +│   │   │   │   │   │   │   ├── cache.cpython-312.pyc +│   │   │   │   │   │   │   ├── comments.cpython-312.pyc +│   │   │   │   │   │   │   ├── concurrency.cpython-312.pyc +│   │   │   │   │   │   │   ├── const.cpython-312.pyc +│   │   │   │   │   │   │   ├── files.cpython-312.pyc +│   │   │   │   │   │   │   ├── handle_ipynb_magics.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── linegen.cpython-312.pyc +│   │   │   │   │   │   │   ├── lines.cpython-312.pyc +│   │   │   │   │   │   │   ├── mode.cpython-312.pyc +│   │   │   │   │   │   │   ├── nodes.cpython-312.pyc +│   │   │   │   │   │   │   ├── numerics.cpython-312.pyc +│   │   │   │   │   │   │   ├── output.cpython-312.pyc +│   │   │   │   │   │   │   ├── parsing.cpython-312.pyc +│   │   │   │   │   │   │   ├── report.cpython-312.pyc +│   │   │   │   │   │   │   ├── rusty.cpython-312.pyc +│   │   │   │   │   │   │   ├── strings.cpython-312.pyc +│   │   │   │   │   │   │   └── trans.cpython-312.pyc +│   │   │   │   │   │   ├── report.py +│   │   │   │   │   │   ├── rusty.py +│   │   │   │   │   │   ├── strings.py +│   │   │   │   │   │   └── trans.py +│   │   │   │   │   ├── _mblack_version.py +│   │   │   │   │   ├── mblib2to3 +│   │   │   │   │   │   ├── Grammar.txt +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── PatternGrammar.txt +│   │   │   │   │   │   ├── pgen2 +│   │   │   │   │   │   │   ├── driver.py +│   │   │   │   │   │   │   ├── grammar.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── literals.py +│   │   │   │   │   │   │   ├── parse.py +│   │   │   │   │   │   │   ├── pgen.py +│   │   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   │   ├── driver.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── grammar.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── parse.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── pgen.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── token.cpython-312.pyc +│   │   │   │   │   │   │   │   └── tokenize.cpython-312.pyc +│   │   │   │   │   │   │   ├── tokenize.py +│   │   │   │   │   │   │   └── token.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── pygram.cpython-312.pyc +│   │   │   │   │   │   │   └── pytree.cpython-312.pyc +│   │   │   │   │   │   ├── pygram.py +│   │   │   │   │   │   └── pytree.py +│   │   │   │   │   ├── mojo +│   │   │   │   │   │   ├── _entrypoints.py +│   │   │   │   │   │   ├── importer.py +│   │   │   │   │   │   ├── notebook.py +│   │   │   │   │   │   ├── _package_root.py +│   │   │   │   │   │   ├── paths.py +│   │   │   │   │   │   └── run.py +│   │   │   │   │   ├── mypy_extensions-1.1.0.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── mypy_extensions.py +│   │   │   │   │   ├── mypy_protobuf +│   │   │   │   │   │   ├── extensions_pb2.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── main.py +│   │   │   │   │   ├── mypy_protobuf-5.1.0.dist-info +│   │   │   │   │   │   ├── entry_points.txt +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   ├── top_level.txt +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── packaging +│   │   │   │   │   │   ├── dependency_groups.py +│   │   │   │   │   │   ├── direct_url.py +│   │   │   │   │   │   ├── _elffile.py +│   │   │   │   │   │   ├── errors.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   └── _spdx.py +│   │   │   │   │   │   ├── _manylinux.py +│   │   │   │   │   │   ├── markers.py +│   │   │   │   │   │   ├── metadata.py +│   │   │   │   │   │   ├── _musllinux.py +│   │   │   │   │   │   ├── _parser.py +│   │   │   │   │   │   ├── pylock.py +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── requirements.py +│   │   │   │   │   │   ├── specifiers.py +│   │   │   │   │   │   ├── _structures.py +│   │   │   │   │   │   ├── tags.py +│   │   │   │   │   │   ├── _tokenizer.py +│   │   │   │   │   │   ├── utils.py +│   │   │   │   │   │   └── version.py +│   │   │   │   │   ├── packaging-26.2.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   ├── LICENSE +│   │   │   │   │   │   │   ├── LICENSE.APACHE +│   │   │   │   │   │   │   └── LICENSE.BSD +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── pathspec +│   │   │   │   │   │   ├── backend.py +│   │   │   │   │   │   ├── _backends +│   │   │   │   │   │   │   ├── agg.py +│   │   │   │   │   │   │   ├── hyperscan +│   │   │   │   │   │   │   │   ├── _base.py +│   │   │   │   │   │   │   │   ├── base.py +│   │   │   │   │   │   │   │   ├── gitignore.py +│   │   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   │   ├── pathspec.py +│   │   │   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   │   │   ├── _base.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── base.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── gitignore.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   └── pathspec.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   │   ├── agg.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   └── _utils.cpython-312.pyc +│   │   │   │   │   │   │   ├── re2 +│   │   │   │   │   │   │   │   ├── _base.py +│   │   │   │   │   │   │   │   ├── base.py +│   │   │   │   │   │   │   │   ├── gitignore.py +│   │   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   │   ├── pathspec.py +│   │   │   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   │   │   ├── _base.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── base.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── gitignore.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   └── pathspec.cpython-312.pyc +│   │   │   │   │   │   │   ├── simple +│   │   │   │   │   │   │   │   ├── gitignore.py +│   │   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   │   ├── pathspec.py +│   │   │   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   │   │   ├── gitignore.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   └── pathspec.cpython-312.pyc +│   │   │   │   │   │   │   └── _utils.py +│   │   │   │   │   │   ├── gitignore.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── _meta.py +│   │   │   │   │   │   ├── pathspec.py +│   │   │   │   │   │   ├── pattern.py +│   │   │   │   │   │   ├── patterns +│   │   │   │   │   │   │   ├── gitignore +│   │   │   │   │   │   │   │   ├── base.py +│   │   │   │   │   │   │   │   ├── basic.py +│   │   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   │   │   ├── base.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── basic.cpython-312.pyc +│   │   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   │   └── spec.cpython-312.pyc +│   │   │   │   │   │   │   │   └── spec.py +│   │   │   │   │   │   │   ├── gitwildmatch.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   │   ├── gitwildmatch.cpython-312.pyc +│   │   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── backend.cpython-312.pyc +│   │   │   │   │   │   │   ├── gitignore.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── _meta.cpython-312.pyc +│   │   │   │   │   │   │   ├── pathspec.cpython-312.pyc +│   │   │   │   │   │   │   ├── pattern.cpython-312.pyc +│   │   │   │   │   │   │   ├── _typing.cpython-312.pyc +│   │   │   │   │   │   │   ├── util.cpython-312.pyc +│   │   │   │   │   │   │   └── _version.cpython-312.pyc +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── _typing.py +│   │   │   │   │   │   ├── util.py +│   │   │   │   │   │   └── _version.py +│   │   │   │   │   ├── pathspec-1.1.1.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── platformdirs +│   │   │   │   │   │   ├── android.py +│   │   │   │   │   │   ├── api.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── macos.py +│   │   │   │   │   │   ├── __main__.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── api.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── unix.cpython-312.pyc +│   │   │   │   │   │   │   ├── version.cpython-312.pyc +│   │   │   │   │   │   │   └── _xdg.cpython-312.pyc +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── unix.py +│   │   │   │   │   │   ├── version.py +│   │   │   │   │   │   ├── windows.py +│   │   │   │   │   │   └── _xdg.py +│   │   │   │   │   ├── platformdirs-4.9.6.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── protobuf-7.34.1.dist-info +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── _mblack_version.cpython-312.pyc +│   │   │   │   │   │   └── mypy_extensions.cpython-312.pyc +│   │   │   │   │   ├── python_dateutil-2.9.0.post0.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   ├── top_level.txt +│   │   │   │   │   │   ├── WHEEL +│   │   │   │   │   │   └── zip-safe +│   │   │   │   │   ├── pyzmq-27.1.0.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   ├── LICENSE.md +│   │   │   │   │   │   │   └── licenses +│   │   │   │   │   │   │   └── LICENSE.tornado.txt +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── README.txt +│   │   │   │   │   ├── six-1.17.0.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   ├── top_level.txt +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── six.py +│   │   │   │   │   ├── tomli +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── _parser.py +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── _re.py +│   │   │   │   │   │   └── _types.py +│   │   │   │   │   ├── tomli-2.4.1.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── tornado +│   │   │   │   │   │   ├── auth.py +│   │   │   │   │   │   ├── autoreload.py +│   │   │   │   │   │   ├── concurrent.py +│   │   │   │   │   │   ├── curl_httpclient.py +│   │   │   │   │   │   ├── escape.py +│   │   │   │   │   │   ├── gen.py +│   │   │   │   │   │   ├── http1connection.py +│   │   │   │   │   │   ├── httpclient.py +│   │   │   │   │   │   ├── httpserver.py +│   │   │   │   │   │   ├── httputil.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── __init__.pyi +│   │   │   │   │   │   ├── ioloop.py +│   │   │   │   │   │   ├── iostream.py +│   │   │   │   │   │   ├── _locale_data.py +│   │   │   │   │   │   ├── locale.py +│   │   │   │   │   │   ├── locks.py +│   │   │   │   │   │   ├── log.py +│   │   │   │   │   │   ├── netutil.py +│   │   │   │   │   │   ├── options.py +│   │   │   │   │   │   ├── platform +│   │   │   │   │   │   │   ├── asyncio.py +│   │   │   │   │   │   │   ├── caresresolver.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   │   ├── asyncio.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── caresresolver.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   └── twisted.cpython-312.pyc +│   │   │   │   │   │   │   └── twisted.py +│   │   │   │   │   │   ├── process.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── auth.cpython-312.pyc +│   │   │   │   │   │   │   ├── autoreload.cpython-312.pyc +│   │   │   │   │   │   │   ├── concurrent.cpython-312.pyc +│   │   │   │   │   │   │   ├── curl_httpclient.cpython-312.pyc +│   │   │   │   │   │   │   ├── escape.cpython-312.pyc +│   │   │   │   │   │   │   ├── gen.cpython-312.pyc +│   │   │   │   │   │   │   ├── http1connection.cpython-312.pyc +│   │   │   │   │   │   │   ├── httpclient.cpython-312.pyc +│   │   │   │   │   │   │   ├── httpserver.cpython-312.pyc +│   │   │   │   │   │   │   ├── httputil.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── ioloop.cpython-312.pyc +│   │   │   │   │   │   │   ├── iostream.cpython-312.pyc +│   │   │   │   │   │   │   ├── locale.cpython-312.pyc +│   │   │   │   │   │   │   ├── _locale_data.cpython-312.pyc +│   │   │   │   │   │   │   ├── locks.cpython-312.pyc +│   │   │   │   │   │   │   ├── log.cpython-312.pyc +│   │   │   │   │   │   │   ├── netutil.cpython-312.pyc +│   │   │   │   │   │   │   ├── options.cpython-312.pyc +│   │   │   │   │   │   │   ├── process.cpython-312.pyc +│   │   │   │   │   │   │   ├── queues.cpython-312.pyc +│   │   │   │   │   │   │   ├── routing.cpython-312.pyc +│   │   │   │   │   │   │   ├── simple_httpclient.cpython-312.pyc +│   │   │   │   │   │   │   ├── tcpclient.cpython-312.pyc +│   │   │   │   │   │   │   ├── tcpserver.cpython-312.pyc +│   │   │   │   │   │   │   ├── template.cpython-312.pyc +│   │   │   │   │   │   │   ├── testing.cpython-312.pyc +│   │   │   │   │   │   │   ├── util.cpython-312.pyc +│   │   │   │   │   │   │   ├── web.cpython-312.pyc +│   │   │   │   │   │   │   ├── websocket.cpython-312.pyc +│   │   │   │   │   │   │   └── wsgi.cpython-312.pyc +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── queues.py +│   │   │   │   │   │   ├── routing.py +│   │   │   │   │   │   ├── simple_httpclient.py +│   │   │   │   │   │   ├── speedups.abi3.so +│   │   │   │   │   │   ├── speedups.pyi +│   │   │   │   │   │   ├── tcpclient.py +│   │   │   │   │   │   ├── tcpserver.py +│   │   │   │   │   │   ├── template.py +│   │   │   │   │   │   ├── test +│   │   │   │   │   │   │   ├── asyncio_test.py +│   │   │   │   │   │   │   ├── auth_test.py +│   │   │   │   │   │   │   ├── autoreload_test.py +│   │   │   │   │   │   │   ├── circlerefs_test.py +│   │   │   │   │   │   │   ├── concurrent_test.py +│   │   │   │   │   │   │   ├── csv_translations +│   │   │   │   │   │   │   │   └── fr_FR.csv +│   │   │   │   │   │   │   ├── curl_httpclient_test.py +│   │   │   │   │   │   │   ├── escape_test.py +│   │   │   │   │   │   │   ├── gen_test.py +│   │   │   │   │   │   │   ├── gettext_translations +│   │   │   │   │   │   │   │   └── fr_FR +│   │   │   │   │   │   │   │   └── LC_MESSAGES +│   │   │   │   │   │   │   │   ├── tornado_test.mo +│   │   │   │   │   │   │   │   └── tornado_test.po +│   │   │   │   │   │   │   ├── http1connection_test.py +│   │   │   │   │   │   │   ├── httpclient_test.py +│   │   │   │   │   │   │   ├── httpserver_test.py +│   │   │   │   │   │   │   ├── httputil_test.py +│   │   │   │   │   │   │   ├── import_test.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── ioloop_test.py +│   │   │   │   │   │   │   ├── iostream_test.py +│   │   │   │   │   │   │   ├── locale_test.py +│   │   │   │   │   │   │   ├── locks_test.py +│   │   │   │   │   │   │   ├── log_test.py +│   │   │   │   │   │   │   ├── __main__.py +│   │   │   │   │   │   │   ├── netutil_test.py +│   │   │   │   │   │   │   ├── options_test.cfg +│   │   │   │   │   │   │   ├── options_test.py +│   │   │   │   │   │   │   ├── options_test_types.cfg +│   │   │   │   │   │   │   ├── options_test_types_str.cfg +│   │   │   │   │   │   │   ├── process_test.py +│   │   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   │   ├── asyncio_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── auth_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── autoreload_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── circlerefs_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── concurrent_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── curl_httpclient_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── escape_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── gen_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── http1connection_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── httpclient_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── httpserver_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── httputil_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── import_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── ioloop_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── iostream_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── locale_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── locks_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── log_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __main__.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── netutil_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── options_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── process_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── queues_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── resolve_test_helper.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── routing_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── runtests.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── simple_httpclient_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── tcpclient_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── tcpserver_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── template_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── testing_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── twisted_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── util.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── util_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── websocket_test.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── web_test.cpython-312.pyc +│   │   │   │   │   │   │   │   └── wsgi_test.cpython-312.pyc +│   │   │   │   │   │   │   ├── queues_test.py +│   │   │   │   │   │   │   ├── resolve_test_helper.py +│   │   │   │   │   │   │   ├── routing_test.py +│   │   │   │   │   │   │   ├── runtests.py +│   │   │   │   │   │   │   ├── simple_httpclient_test.py +│   │   │   │   │   │   │   ├── static +│   │   │   │   │   │   │   │   ├── dir +│   │   │   │   │   │   │   │   │   └── index.html +│   │   │   │   │   │   │   │   ├── robots.txt +│   │   │   │   │   │   │   │   ├── sample.xml +│   │   │   │   │   │   │   │   ├── sample.xml.bz2 +│   │   │   │   │   │   │   │   └── sample.xml.gz +│   │   │   │   │   │   │   ├── static_foo.txt +│   │   │   │   │   │   │   ├── tcpclient_test.py +│   │   │   │   │   │   │   ├── tcpserver_test.py +│   │   │   │   │   │   │   ├── templates +│   │   │   │   │   │   │   │   └── utf8.html +│   │   │   │   │   │   │   ├── template_test.py +│   │   │   │   │   │   │   ├── test.crt +│   │   │   │   │   │   │   ├── testing_test.py +│   │   │   │   │   │   │   ├── test.key +│   │   │   │   │   │   │   ├── twisted_test.py +│   │   │   │   │   │   │   ├── util.py +│   │   │   │   │   │   │   ├── util_test.py +│   │   │   │   │   │   │   ├── websocket_test.py +│   │   │   │   │   │   │   ├── web_test.py +│   │   │   │   │   │   │   └── wsgi_test.py +│   │   │   │   │   │   ├── testing.py +│   │   │   │   │   │   ├── util.py +│   │   │   │   │   │   ├── web.py +│   │   │   │   │   │   ├── websocket.py +│   │   │   │   │   │   └── wsgi.py +│   │   │   │   │   ├── tornado-6.5.5.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   ├── top_level.txt +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── traitlets +│   │   │   │   │   │   ├── config +│   │   │   │   │   │   │   ├── application.py +│   │   │   │   │   │   │   ├── argcomplete_config.py +│   │   │   │   │   │   │   ├── configurable.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── loader.py +│   │   │   │   │   │   │   ├── manager.py +│   │   │   │   │   │   │   └── sphinxdoc.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── log.py +│   │   │   │   │   │   ├── py.typed +│   │   │   │   │   │   ├── tests +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── test_traitlets.py +│   │   │   │   │   │   │   └── utils.py +│   │   │   │   │   │   ├── traitlets.py +│   │   │   │   │   │   ├── utils +│   │   │   │   │   │   │   ├── bunch.py +│   │   │   │   │   │   │   ├── decorators.py +│   │   │   │   │   │   │   ├── descriptions.py +│   │   │   │   │   │   │   ├── getargspec.py +│   │   │   │   │   │   │   ├── importstring.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── nested_update.py +│   │   │   │   │   │   │   ├── sentinel.py +│   │   │   │   │   │   │   ├── text.py +│   │   │   │   │   │   │   └── warnings.py +│   │   │   │   │   │   └── _version.py +│   │   │   │   │   ├── traitlets-5.14.3.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── types_protobuf-7.34.1.20260408.dist-info +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   ├── top_level.txt +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   ├── zipp +│   │   │   │   │   │   ├── compat +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── overlay.py +│   │   │   │   │   │   │   ├── py310.py +│   │   │   │   │   │   │   └── py313.py +│   │   │   │   │   │   ├── _functools.py +│   │   │   │   │   │   ├── glob.py +│   │   │   │   │   │   └── __init__.py +│   │   │   │   │   ├── zipp-3.23.1.dist-info +│   │   │   │   │   │   ├── direct_url.json +│   │   │   │   │   │   ├── INSTALLER +│   │   │   │   │   │   ├── licenses +│   │   │   │   │   │   │   └── LICENSE +│   │   │   │   │   │   ├── METADATA +│   │   │   │   │   │   ├── RECORD +│   │   │   │   │   │   ├── REQUESTED +│   │   │   │   │   │   ├── top_level.txt +│   │   │   │   │   │   └── WHEEL +│   │   │   │   │   └── zmq +│   │   │   │   │   ├── asyncio.py +│   │   │   │   │   ├── auth +│   │   │   │   │   │   ├── asyncio.py +│   │   │   │   │   │   ├── base.py +│   │   │   │   │   │   ├── certs.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── ioloop.py +│   │   │   │   │   │   └── thread.py +│   │   │   │   │   ├── backend +│   │   │   │   │   │   ├── cffi +│   │   │   │   │   │   │   ├── _cdefs.h +│   │   │   │   │   │   │   ├── _cffi_src.c +│   │   │   │   │   │   │   ├── context.py +│   │   │   │   │   │   │   ├── devices.py +│   │   │   │   │   │   │   ├── error.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── message.py +│   │   │   │   │   │   │   ├── _poll.py +│   │   │   │   │   │   │   ├── README.md +│   │   │   │   │   │   │   ├── socket.py +│   │   │   │   │   │   │   └── utils.py +│   │   │   │   │   │   ├── cython +│   │   │   │   │   │   │   ├── constant_enums.pxi +│   │   │   │   │   │   │   ├── _externs.pxd +│   │   │   │   │   │   │   ├── __init__.pxd +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── libzmq.pxd +│   │   │   │   │   │   │   ├── _zmq.abi3.so +│   │   │   │   │   │   │   ├── _zmq.pxd +│   │   │   │   │   │   │   └── _zmq.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── __init__.pyi +│   │   │   │   │   │   └── select.py +│   │   │   │   │   ├── constants.py +│   │   │   │   │   ├── decorators.py +│   │   │   │   │   ├── devices +│   │   │   │   │   │   ├── basedevice.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── monitoredqueuedevice.py +│   │   │   │   │   │   ├── monitoredqueue.py +│   │   │   │   │   │   ├── proxydevice.py +│   │   │   │   │   │   └── proxysteerabledevice.py +│   │   │   │   │   ├── error.py +│   │   │   │   │   ├── eventloop +│   │   │   │   │   │   ├── _deprecated.py +│   │   │   │   │   │   ├── future.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── ioloop.py +│   │   │   │   │   │   └── zmqstream.py +│   │   │   │   │   ├── _future.py +│   │   │   │   │   ├── _future.pyi +│   │   │   │   │   ├── green +│   │   │   │   │   │   ├── core.py +│   │   │   │   │   │   ├── device.py +│   │   │   │   │   │   ├── eventloop +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── ioloop.py +│   │   │   │   │   │   │   └── zmqstream.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── poll.py +│   │   │   │   │   ├── __init__.pxd +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __init__.pyi +│   │   │   │   │   ├── log +│   │   │   │   │   │   ├── handlers.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── __main__.py +│   │   │   │   │   ├── py.typed +│   │   │   │   │   ├── ssh +│   │   │   │   │   │   ├── forward.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── tunnel.py +│   │   │   │   │   ├── sugar +│   │   │   │   │   │   ├── attrsettr.py +│   │   │   │   │   │   ├── context.py +│   │   │   │   │   │   ├── frame.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── __init__.pyi +│   │   │   │   │   │   ├── poll.py +│   │   │   │   │   │   ├── socket.py +│   │   │   │   │   │   ├── stopwatch.py +│   │   │   │   │   │   ├── tracker.py +│   │   │   │   │   │   └── version.py +│   │   │   │   │   ├── tests +│   │   │   │   │   │   └── __init__.py +│   │   │   │   │   ├── _typing.py +│   │   │   │   │   └── utils +│   │   │   │   │   ├── garbage.py +│   │   │   │   │   ├── getpid_compat.h +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── interop.py +│   │   │   │   │   ├── ipcmaxlen.h +│   │   │   │   │   ├── jsonapi.py +│   │   │   │   │   ├── monitor.py +│   │   │   │   │   ├── mutex.h +│   │   │   │   │   ├── pyversion_compat.h +│   │   │   │   │   ├── strtypes.py +│   │   │   │   │   ├── win32.py +│   │   │   │   │   ├── z85.py +│   │   │   │   │   └── zmq_compat.h +│   │   │   │   ├── site.py +│   │   │   │   ├── smtplib.py +│   │   │   │   ├── sndhdr.py +│   │   │   │   ├── socket.py +│   │   │   │   ├── socketserver.py +│   │   │   │   ├── sqlite3 +│   │   │   │   │   ├── dbapi2.py +│   │   │   │   │   ├── dump.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   └── __pycache__ +│   │   │   │   │   ├── dbapi2.cpython-312.pyc +│   │   │   │   │   ├── dump.cpython-312.pyc +│   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   └── __main__.cpython-312.pyc +│   │   │   │   ├── sre_compile.py +│   │   │   │   ├── sre_constants.py +│   │   │   │   ├── sre_parse.py +│   │   │   │   ├── ssl.py +│   │   │   │   ├── statistics.py +│   │   │   │   ├── stat.py +│   │   │   │   ├── stringprep.py +│   │   │   │   ├── string.py +│   │   │   │   ├── _strptime.py +│   │   │   │   ├── struct.py +│   │   │   │   ├── subprocess.py +│   │   │   │   ├── sunau.py +│   │   │   │   ├── symtable.py +│   │   │   │   ├── _sysconfigdata__linux_x86_64-linux-gnu.py +│   │   │   │   ├── _sysconfigdata__linux_x86_64-linux-gnu.py.orig +│   │   │   │   ├── _sysconfigdata_x86_64_conda_linux_gnu.py +│   │   │   │   ├── sysconfig.py +│   │   │   │   ├── tabnanny.py +│   │   │   │   ├── tarfile.py +│   │   │   │   ├── telnetlib.py +│   │   │   │   ├── tempfile.py +│   │   │   │   ├── test +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── test_script_helper.cpython-312.pyc +│   │   │   │   │   │   └── test_support.cpython-312.pyc +│   │   │   │   │   ├── support +│   │   │   │   │   │   ├── ast_helper.py +│   │   │   │   │   │   ├── asynchat.py +│   │   │   │   │   │   ├── asyncore.py +│   │   │   │   │   │   ├── bytecode_helper.py +│   │   │   │   │   │   ├── hashlib_helper.py +│   │   │   │   │   │   ├── hypothesis_helper.py +│   │   │   │   │   │   ├── _hypothesis_stubs +│   │   │   │   │   │   │   ├── _helpers.py +│   │   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   │   ├── _helpers.cpython-312.pyc +│   │   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   │   └── strategies.cpython-312.pyc +│   │   │   │   │   │   │   └── strategies.py +│   │   │   │   │   │   ├── i18n_helper.py +│   │   │   │   │   │   ├── import_helper.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── interpreters.py +│   │   │   │   │   │   ├── logging_helper.py +│   │   │   │   │   │   ├── os_helper.py +│   │   │   │   │   │   ├── pty_helper.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── ast_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── asynchat.cpython-312.pyc +│   │   │   │   │   │   │   ├── asyncore.cpython-312.pyc +│   │   │   │   │   │   │   ├── bytecode_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── hashlib_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── hypothesis_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── i18n_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── import_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── interpreters.cpython-312.pyc +│   │   │   │   │   │   │   ├── logging_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── os_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── pty_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── script_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── smtpd.cpython-312.pyc +│   │   │   │   │   │   │   ├── socket_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── testcase.cpython-312.pyc +│   │   │   │   │   │   │   ├── threading_helper.cpython-312.pyc +│   │   │   │   │   │   │   ├── venv.cpython-312.pyc +│   │   │   │   │   │   │   └── warnings_helper.cpython-312.pyc +│   │   │   │   │   │   ├── script_helper.py +│   │   │   │   │   │   ├── smtpd.py +│   │   │   │   │   │   ├── socket_helper.py +│   │   │   │   │   │   ├── testcase.py +│   │   │   │   │   │   ├── threading_helper.py +│   │   │   │   │   │   ├── venv.py +│   │   │   │   │   │   └── warnings_helper.py +│   │   │   │   │   ├── test_script_helper.py +│   │   │   │   │   └── test_support.py +│   │   │   │   ├── textwrap.py +│   │   │   │   ├── this.py +│   │   │   │   ├── _threading_local.py +│   │   │   │   ├── threading.py +│   │   │   │   ├── timeit.py +│   │   │   │   ├── tkinter +│   │   │   │   │   ├── colorchooser.py +│   │   │   │   │   ├── commondialog.py +│   │   │   │   │   ├── constants.py +│   │   │   │   │   ├── dialog.py +│   │   │   │   │   ├── dnd.py +│   │   │   │   │   ├── filedialog.py +│   │   │   │   │   ├── font.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── messagebox.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── colorchooser.cpython-312.pyc +│   │   │   │   │   │   ├── commondialog.cpython-312.pyc +│   │   │   │   │   │   ├── constants.cpython-312.pyc +│   │   │   │   │   │   ├── dialog.cpython-312.pyc +│   │   │   │   │   │   ├── dnd.cpython-312.pyc +│   │   │   │   │   │   ├── filedialog.cpython-312.pyc +│   │   │   │   │   │   ├── font.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── __main__.cpython-312.pyc +│   │   │   │   │   │   ├── messagebox.cpython-312.pyc +│   │   │   │   │   │   ├── scrolledtext.cpython-312.pyc +│   │   │   │   │   │   ├── simpledialog.cpython-312.pyc +│   │   │   │   │   │   ├── tix.cpython-312.pyc +│   │   │   │   │   │   └── ttk.cpython-312.pyc +│   │   │   │   │   ├── scrolledtext.py +│   │   │   │   │   ├── simpledialog.py +│   │   │   │   │   ├── tix.py +│   │   │   │   │   └── ttk.py +│   │   │   │   ├── tokenize.py +│   │   │   │   ├── token.py +│   │   │   │   ├── tomllib +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── _parser.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── _parser.cpython-312.pyc +│   │   │   │   │   │   ├── _re.cpython-312.pyc +│   │   │   │   │   │   └── _types.cpython-312.pyc +│   │   │   │   │   ├── _re.py +│   │   │   │   │   └── _types.py +│   │   │   │   ├── traceback.py +│   │   │   │   ├── tracemalloc.py +│   │   │   │   ├── trace.py +│   │   │   │   ├── tty.py +│   │   │   │   ├── turtledemo +│   │   │   │   │   ├── bytedesign.py +│   │   │   │   │   ├── chaos.py +│   │   │   │   │   ├── clock.py +│   │   │   │   │   ├── colormixer.py +│   │   │   │   │   ├── forest.py +│   │   │   │   │   ├── fractalcurves.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── lindenmayer.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── minimal_hanoi.py +│   │   │   │   │   ├── nim.py +│   │   │   │   │   ├── paint.py +│   │   │   │   │   ├── peace.py +│   │   │   │   │   ├── penrose.py +│   │   │   │   │   ├── planet_and_moon.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── bytedesign.cpython-312.pyc +│   │   │   │   │   │   ├── chaos.cpython-312.pyc +│   │   │   │   │   │   ├── clock.cpython-312.pyc +│   │   │   │   │   │   ├── colormixer.cpython-312.pyc +│   │   │   │   │   │   ├── forest.cpython-312.pyc +│   │   │   │   │   │   ├── fractalcurves.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── lindenmayer.cpython-312.pyc +│   │   │   │   │   │   ├── __main__.cpython-312.pyc +│   │   │   │   │   │   ├── minimal_hanoi.cpython-312.pyc +│   │   │   │   │   │   ├── nim.cpython-312.pyc +│   │   │   │   │   │   ├── paint.cpython-312.pyc +│   │   │   │   │   │   ├── peace.cpython-312.pyc +│   │   │   │   │   │   ├── penrose.cpython-312.pyc +│   │   │   │   │   │   ├── planet_and_moon.cpython-312.pyc +│   │   │   │   │   │   ├── rosette.cpython-312.pyc +│   │   │   │   │   │   ├── round_dance.cpython-312.pyc +│   │   │   │   │   │   ├── sorting_animate.cpython-312.pyc +│   │   │   │   │   │   ├── tree.cpython-312.pyc +│   │   │   │   │   │   ├── two_canvases.cpython-312.pyc +│   │   │   │   │   │   └── yinyang.cpython-312.pyc +│   │   │   │   │   ├── rosette.py +│   │   │   │   │   ├── round_dance.py +│   │   │   │   │   ├── sorting_animate.py +│   │   │   │   │   ├── tree.py +│   │   │   │   │   ├── turtle.cfg +│   │   │   │   │   ├── two_canvases.py +│   │   │   │   │   └── yinyang.py +│   │   │   │   ├── turtle.py +│   │   │   │   ├── types.py +│   │   │   │   ├── typing.py +│   │   │   │   ├── unittest +│   │   │   │   │   ├── async_case.py +│   │   │   │   │   ├── case.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── loader.py +│   │   │   │   │   ├── _log.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── main.py +│   │   │   │   │   ├── mock.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── async_case.cpython-312.pyc +│   │   │   │   │   │   ├── case.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── loader.cpython-312.pyc +│   │   │   │   │   │   ├── _log.cpython-312.pyc +│   │   │   │   │   │   ├── __main__.cpython-312.pyc +│   │   │   │   │   │   ├── main.cpython-312.pyc +│   │   │   │   │   │   ├── mock.cpython-312.pyc +│   │   │   │   │   │   ├── result.cpython-312.pyc +│   │   │   │   │   │   ├── runner.cpython-312.pyc +│   │   │   │   │   │   ├── signals.cpython-312.pyc +│   │   │   │   │   │   ├── suite.cpython-312.pyc +│   │   │   │   │   │   └── util.cpython-312.pyc +│   │   │   │   │   ├── result.py +│   │   │   │   │   ├── runner.py +│   │   │   │   │   ├── signals.py +│   │   │   │   │   ├── suite.py +│   │   │   │   │   └── util.py +│   │   │   │   ├── urllib +│   │   │   │   │   ├── error.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── parse.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── error.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── parse.cpython-312.pyc +│   │   │   │   │   │   ├── request.cpython-312.pyc +│   │   │   │   │   │   ├── response.cpython-312.pyc +│   │   │   │   │   │   └── robotparser.cpython-312.pyc +│   │   │   │   │   ├── request.py +│   │   │   │   │   ├── response.py +│   │   │   │   │   └── robotparser.py +│   │   │   │   ├── uuid.py +│   │   │   │   ├── uu.py +│   │   │   │   ├── venv +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   └── __main__.cpython-312.pyc +│   │   │   │   │   └── scripts +│   │   │   │   │   ├── common +│   │   │   │   │   │   ├── activate +│   │   │   │   │   │   └── Activate.ps1 +│   │   │   │   │   └── posix +│   │   │   │   │   ├── activate.csh +│   │   │   │   │   └── activate.fish +│   │   │   │   ├── warnings.py +│   │   │   │   ├── wave.py +│   │   │   │   ├── weakref.py +│   │   │   │   ├── _weakrefset.py +│   │   │   │   ├── webbrowser.py +│   │   │   │   ├── wsgiref +│   │   │   │   │   ├── handlers.py +│   │   │   │   │   ├── headers.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── handlers.cpython-312.pyc +│   │   │   │   │   │   ├── headers.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── simple_server.cpython-312.pyc +│   │   │   │   │   │   ├── types.cpython-312.pyc +│   │   │   │   │   │   ├── util.cpython-312.pyc +│   │   │   │   │   │   └── validate.cpython-312.pyc +│   │   │   │   │   ├── simple_server.py +│   │   │   │   │   ├── types.py +│   │   │   │   │   ├── util.py +│   │   │   │   │   └── validate.py +│   │   │   │   ├── xdrlib.py +│   │   │   │   ├── xml +│   │   │   │   │   ├── dom +│   │   │   │   │   │   ├── domreg.py +│   │   │   │   │   │   ├── expatbuilder.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   ├── minicompat.py +│   │   │   │   │   │   ├── minidom.py +│   │   │   │   │   │   ├── NodeFilter.py +│   │   │   │   │   │   ├── pulldom.py +│   │   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   │   ├── domreg.cpython-312.pyc +│   │   │   │   │   │   │   ├── expatbuilder.cpython-312.pyc +│   │   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   │   ├── minicompat.cpython-312.pyc +│   │   │   │   │   │   │   ├── minidom.cpython-312.pyc +│   │   │   │   │   │   │   ├── NodeFilter.cpython-312.pyc +│   │   │   │   │   │   │   ├── pulldom.cpython-312.pyc +│   │   │   │   │   │   │   └── xmlbuilder.cpython-312.pyc +│   │   │   │   │   │   └── xmlbuilder.py +│   │   │   │   │   ├── etree +│   │   │   │   │   │   ├── cElementTree.py +│   │   │   │   │   │   ├── ElementInclude.py +│   │   │   │   │   │   ├── ElementPath.py +│   │   │   │   │   │   ├── ElementTree.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   ├── cElementTree.cpython-312.pyc +│   │   │   │   │   │   ├── ElementInclude.cpython-312.pyc +│   │   │   │   │   │   ├── ElementPath.cpython-312.pyc +│   │   │   │   │   │   ├── ElementTree.cpython-312.pyc +│   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── parsers +│   │   │   │   │   │   ├── expat.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   ├── expat.cpython-312.pyc +│   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   └── sax +│   │   │   │   │   ├── _exceptions.py +│   │   │   │   │   ├── expatreader.py +│   │   │   │   │   ├── handler.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── _exceptions.cpython-312.pyc +│   │   │   │   │   │   ├── expatreader.cpython-312.pyc +│   │   │   │   │   │   ├── handler.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   ├── saxutils.cpython-312.pyc +│   │   │   │   │   │   └── xmlreader.cpython-312.pyc +│   │   │   │   │   ├── saxutils.py +│   │   │   │   │   └── xmlreader.py +│   │   │   │   ├── xmlrpc +│   │   │   │   │   ├── client.py +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __pycache__ +│   │   │   │   │   │   ├── client.cpython-312.pyc +│   │   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   │   └── server.cpython-312.pyc +│   │   │   │   │   └── server.py +│   │   │   │   ├── zipapp.py +│   │   │   │   ├── zipfile +│   │   │   │   │   ├── __init__.py +│   │   │   │   │   ├── __main__.py +│   │   │   │   │   ├── _path +│   │   │   │   │   │   ├── glob.py +│   │   │   │   │   │   ├── __init__.py +│   │   │   │   │   │   └── __pycache__ +│   │   │   │   │   │   ├── glob.cpython-312.pyc +│   │   │   │   │   │   └── __init__.cpython-312.pyc +│   │   │   │   │   └── __pycache__ +│   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   └── __main__.cpython-312.pyc +│   │   │   │   ├── zipimport.py +│   │   │   │   └── zoneinfo +│   │   │   │   ├── _common.py +│   │   │   │   ├── __init__.py +│   │   │   │   ├── __pycache__ +│   │   │   │   │   ├── _common.cpython-312.pyc +│   │   │   │   │   ├── __init__.cpython-312.pyc +│   │   │   │   │   ├── _tzpath.cpython-312.pyc +│   │   │   │   │   └── _zoneinfo.cpython-312.pyc +│   │   │   │   ├── _tzpath.py +│   │   │   │   └── _zoneinfo.py +│   │   │   ├── sqlite3.40.0 +│   │   │   │   ├── libsqlite3.40.0.so +│   │   │   │   └── pkgIndex.tcl +│   │   │   ├── tcl8 +│   │   │   │   ├── 8.4 +│   │   │   │   │   ├── platform +│   │   │   │   │   │   └── shell-1.1.4.tm +│   │   │   │   │   └── platform-1.0.19.tm +│   │   │   │   ├── 8.5 +│   │   │   │   │   ├── msgcat-1.6.1.tm +│   │   │   │   │   └── tcltest-2.5.5.tm +│   │   │   │   └── 8.6 +│   │   │   │   ├── http-2.9.8.tm +│   │   │   │   └── tdbc +│   │   │   │   └── sqlite3-1.1.5.tm +│   │   │   ├── tcl8.6 +│   │   │   │   ├── auto.tcl +│   │   │   │   ├── clock.tcl +│   │   │   │   ├── encoding +│   │   │   │   │   ├── ascii.enc +│   │   │   │   │   ├── big5.enc +│   │   │   │   │   ├── cns11643.enc +│   │   │   │   │   ├── cp1250.enc +│   │   │   │   │   ├── cp1251.enc +│   │   │   │   │   ├── cp1252.enc +│   │   │   │   │   ├── cp1253.enc +│   │   │   │   │   ├── cp1254.enc +│   │   │   │   │   ├── cp1255.enc +│   │   │   │   │   ├── cp1256.enc +│   │   │   │   │   ├── cp1257.enc +│   │   │   │   │   ├── cp1258.enc +│   │   │   │   │   ├── cp437.enc +│   │   │   │   │   ├── cp737.enc +│   │   │   │   │   ├── cp775.enc +│   │   │   │   │   ├── cp850.enc +│   │   │   │   │   ├── cp852.enc +│   │   │   │   │   ├── cp855.enc +│   │   │   │   │   ├── cp857.enc +│   │   │   │   │   ├── cp860.enc +│   │   │   │   │   ├── cp861.enc +│   │   │   │   │   ├── cp862.enc +│   │   │   │   │   ├── cp863.enc +│   │   │   │   │   ├── cp864.enc +│   │   │   │   │   ├── cp865.enc +│   │   │   │   │   ├── cp866.enc +│   │   │   │   │   ├── cp869.enc +│   │   │   │   │   ├── cp874.enc +│   │   │   │   │   ├── cp932.enc +│   │   │   │   │   ├── cp936.enc +│   │   │   │   │   ├── cp949.enc +│   │   │   │   │   ├── cp950.enc +│   │   │   │   │   ├── dingbats.enc +│   │   │   │   │   ├── ebcdic.enc +│   │   │   │   │   ├── euc-cn.enc +│   │   │   │   │   ├── euc-jp.enc +│   │   │   │   │   ├── euc-kr.enc +│   │   │   │   │   ├── gb12345.enc +│   │   │   │   │   ├── gb1988.enc +│   │   │   │   │   ├── gb2312.enc +│   │   │   │   │   ├── gb2312-raw.enc +│   │   │   │   │   ├── iso2022.enc +│   │   │   │   │   ├── iso2022-jp.enc +│   │   │   │   │   ├── iso2022-kr.enc +│   │   │   │   │   ├── iso8859-10.enc +│   │   │   │   │   ├── iso8859-11.enc +│   │   │   │   │   ├── iso8859-13.enc +│   │   │   │   │   ├── iso8859-14.enc +│   │   │   │   │   ├── iso8859-15.enc +│   │   │   │   │   ├── iso8859-16.enc +│   │   │   │   │   ├── iso8859-1.enc +│   │   │   │   │   ├── iso8859-2.enc +│   │   │   │   │   ├── iso8859-3.enc +│   │   │   │   │   ├── iso8859-4.enc +│   │   │   │   │   ├── iso8859-5.enc +│   │   │   │   │   ├── iso8859-6.enc +│   │   │   │   │   ├── iso8859-7.enc +│   │   │   │   │   ├── iso8859-8.enc +│   │   │   │   │   ├── iso8859-9.enc +│   │   │   │   │   ├── jis0201.enc +│   │   │   │   │   ├── jis0208.enc +│   │   │   │   │   ├── jis0212.enc +│   │   │   │   │   ├── koi8-r.enc +│   │   │   │   │   ├── koi8-u.enc +│   │   │   │   │   ├── ksc5601.enc +│   │   │   │   │   ├── macCentEuro.enc +│   │   │   │   │   ├── macCroatian.enc +│   │   │   │   │   ├── macCyrillic.enc +│   │   │   │   │   ├── macDingbats.enc +│   │   │   │   │   ├── macGreek.enc +│   │   │   │   │   ├── macIceland.enc +│   │   │   │   │   ├── macJapan.enc +│   │   │   │   │   ├── macRoman.enc +│   │   │   │   │   ├── macRomania.enc +│   │   │   │   │   ├── macThai.enc +│   │   │   │   │   ├── macTurkish.enc +│   │   │   │   │   ├── macUkraine.enc +│   │   │   │   │   ├── shiftjis.enc +│   │   │   │   │   ├── symbol.enc +│   │   │   │   │   └── tis-620.enc +│   │   │   │   ├── history.tcl +│   │   │   │   ├── http1.0 +│   │   │   │   │   ├── http.tcl +│   │   │   │   │   └── pkgIndex.tcl +│   │   │   │   ├── init.tcl +│   │   │   │   ├── msgs +│   │   │   │   │   ├── af.msg +│   │   │   │   │   ├── af_za.msg +│   │   │   │   │   ├── ar_in.msg +│   │   │   │   │   ├── ar_jo.msg +│   │   │   │   │   ├── ar_lb.msg +│   │   │   │   │   ├── ar.msg +│   │   │   │   │   ├── ar_sy.msg +│   │   │   │   │   ├── be.msg +│   │   │   │   │   ├── bg.msg +│   │   │   │   │   ├── bn_in.msg +│   │   │   │   │   ├── bn.msg +│   │   │   │   │   ├── ca.msg +│   │   │   │   │   ├── cs.msg +│   │   │   │   │   ├── da.msg +│   │   │   │   │   ├── de_at.msg +│   │   │   │   │   ├── de_be.msg +│   │   │   │   │   ├── de.msg +│   │   │   │   │   ├── el.msg +│   │   │   │   │   ├── en_au.msg +│   │   │   │   │   ├── en_be.msg +│   │   │   │   │   ├── en_bw.msg +│   │   │   │   │   ├── en_ca.msg +│   │   │   │   │   ├── en_gb.msg +│   │   │   │   │   ├── en_hk.msg +│   │   │   │   │   ├── en_ie.msg +│   │   │   │   │   ├── en_in.msg +│   │   │   │   │   ├── en_nz.msg +│   │   │   │   │   ├── en_ph.msg +│   │   │   │   │   ├── en_sg.msg +│   │   │   │   │   ├── en_za.msg +│   │   │   │   │   ├── en_zw.msg +│   │   │   │   │   ├── eo.msg +│   │   │   │   │   ├── es_ar.msg +│   │   │   │   │   ├── es_bo.msg +│   │   │   │   │   ├── es_cl.msg +│   │   │   │   │   ├── es_co.msg +│   │   │   │   │   ├── es_cr.msg +│   │   │   │   │   ├── es_do.msg +│   │   │   │   │   ├── es_ec.msg +│   │   │   │   │   ├── es_gt.msg +│   │   │   │   │   ├── es_hn.msg +│   │   │   │   │   ├── es.msg +│   │   │   │   │   ├── es_mx.msg +│   │   │   │   │   ├── es_ni.msg +│   │   │   │   │   ├── es_pa.msg +│   │   │   │   │   ├── es_pe.msg +│   │   │   │   │   ├── es_pr.msg +│   │   │   │   │   ├── es_py.msg +│   │   │   │   │   ├── es_sv.msg +│   │   │   │   │   ├── es_uy.msg +│   │   │   │   │   ├── es_ve.msg +│   │   │   │   │   ├── et.msg +│   │   │   │   │   ├── eu_es.msg +│   │   │   │   │   ├── eu.msg +│   │   │   │   │   ├── fa_in.msg +│   │   │   │   │   ├── fa_ir.msg +│   │   │   │   │   ├── fa.msg +│   │   │   │   │   ├── fi.msg +│   │   │   │   │   ├── fo_fo.msg +│   │   │   │   │   ├── fo.msg +│   │   │   │   │   ├── fr_be.msg +│   │   │   │   │   ├── fr_ca.msg +│   │   │   │   │   ├── fr_ch.msg +│   │   │   │   │   ├── fr.msg +│   │   │   │   │   ├── ga_ie.msg +│   │   │   │   │   ├── ga.msg +│   │   │   │   │   ├── gl_es.msg +│   │   │   │   │   ├── gl.msg +│   │   │   │   │   ├── gv_gb.msg +│   │   │   │   │   ├── gv.msg +│   │   │   │   │   ├── he.msg +│   │   │   │   │   ├── hi_in.msg +│   │   │   │   │   ├── hi.msg +│   │   │   │   │   ├── hr.msg +│   │   │   │   │   ├── hu.msg +│   │   │   │   │   ├── id_id.msg +│   │   │   │   │   ├── id.msg +│   │   │   │   │   ├── is.msg +│   │   │   │   │   ├── it_ch.msg +│   │   │   │   │   ├── it.msg +│   │   │   │   │   ├── ja.msg +│   │   │   │   │   ├── kl_gl.msg +│   │   │   │   │   ├── kl.msg +│   │   │   │   │   ├── kok_in.msg +│   │   │   │   │   ├── kok.msg +│   │   │   │   │   ├── ko_kr.msg +│   │   │   │   │   ├── ko.msg +│   │   │   │   │   ├── kw_gb.msg +│   │   │   │   │   ├── kw.msg +│   │   │   │   │   ├── lt.msg +│   │   │   │   │   ├── lv.msg +│   │   │   │   │   ├── mk.msg +│   │   │   │   │   ├── mr_in.msg +│   │   │   │   │   ├── mr.msg +│   │   │   │   │   ├── ms.msg +│   │   │   │   │   ├── ms_my.msg +│   │   │   │   │   ├── mt.msg +│   │   │   │   │   ├── nb.msg +│   │   │   │   │   ├── nl_be.msg +│   │   │   │   │   ├── nl.msg +│   │   │   │   │   ├── nn.msg +│   │   │   │   │   ├── pl.msg +│   │   │   │   │   ├── pt_br.msg +│   │   │   │   │   ├── pt.msg +│   │   │   │   │   ├── ro.msg +│   │   │   │   │   ├── ru.msg +│   │   │   │   │   ├── ru_ua.msg +│   │   │   │   │   ├── sh.msg +│   │   │   │   │   ├── sk.msg +│   │   │   │   │   ├── sl.msg +│   │   │   │   │   ├── sq.msg +│   │   │   │   │   ├── sr.msg +│   │   │   │   │   ├── sv.msg +│   │   │   │   │   ├── sw.msg +│   │   │   │   │   ├── ta_in.msg +│   │   │   │   │   ├── ta.msg +│   │   │   │   │   ├── te_in.msg +│   │   │   │   │   ├── te.msg +│   │   │   │   │   ├── th.msg +│   │   │   │   │   ├── tr.msg +│   │   │   │   │   ├── uk.msg +│   │   │   │   │   ├── vi.msg +│   │   │   │   │   ├── zh_cn.msg +│   │   │   │   │   ├── zh_hk.msg +│   │   │   │   │   ├── zh.msg +│   │   │   │   │   ├── zh_sg.msg +│   │   │   │   │   └── zh_tw.msg +│   │   │   │   ├── opt0.4 +│   │   │   │   │   ├── optparse.tcl +│   │   │   │   │   └── pkgIndex.tcl +│   │   │   │   ├── package.tcl +│   │   │   │   ├── parray.tcl +│   │   │   │   ├── safe.tcl +│   │   │   │   ├── tclAppInit.c +│   │   │   │   ├── tclIndex +│   │   │   │   ├── tm.tcl +│   │   │   │   └── word.tcl +│   │   │   ├── tclConfig.sh +│   │   │   ├── tclooConfig.sh +│   │   │   ├── tdbc1.1.5 +│   │   │   │   ├── libtdbc1.1.5.so +│   │   │   │   ├── libtdbcstub1.1.5.a +│   │   │   │   ├── pkgIndex.tcl +│   │   │   │   ├── tdbcConfig.sh +│   │   │   │   └── tdbc.tcl +│   │   │   ├── tdbcmysql1.1.5 +│   │   │   │   ├── libtdbcmysql1.1.5.so +│   │   │   │   ├── pkgIndex.tcl +│   │   │   │   └── tdbcmysql.tcl +│   │   │   ├── tdbcodbc1.1.5 +│   │   │   │   ├── libtdbcodbc1.1.5.so +│   │   │   │   ├── pkgIndex.tcl +│   │   │   │   └── tdbcodbc.tcl +│   │   │   ├── tdbcpostgres1.1.5 +│   │   │   │   ├── libtdbcpostgres1.1.5.so +│   │   │   │   ├── pkgIndex.tcl +│   │   │   │   └── tdbcpostgres.tcl +│   │   │   ├── terminfo -> ../share/terminfo +│   │   │   ├── thread2.8.8 +│   │   │   │   ├── libthread2.8.8.so +│   │   │   │   ├── pkgIndex.tcl +│   │   │   │   └── ttrace.tcl +│   │   │   ├── tk8.6 +│   │   │   │   ├── bgerror.tcl +│   │   │   │   ├── button.tcl +│   │   │   │   ├── choosedir.tcl +│   │   │   │   ├── clrpick.tcl +│   │   │   │   ├── comdlg.tcl +│   │   │   │   ├── console.tcl +│   │   │   │   ├── demos +│   │   │   │   │   ├── anilabel.tcl +│   │   │   │   │   ├── aniwave.tcl +│   │   │   │   │   ├── arrow.tcl +│   │   │   │   │   ├── bind.tcl +│   │   │   │   │   ├── bitmap.tcl +│   │   │   │   │   ├── browse +│   │   │   │   │   ├── button.tcl +│   │   │   │   │   ├── check.tcl +│   │   │   │   │   ├── clrpick.tcl +│   │   │   │   │   ├── colors.tcl +│   │   │   │   │   ├── combo.tcl +│   │   │   │   │   ├── cscroll.tcl +│   │   │   │   │   ├── ctext.tcl +│   │   │   │   │   ├── dialog1.tcl +│   │   │   │   │   ├── dialog2.tcl +│   │   │   │   │   ├── en.msg +│   │   │   │   │   ├── entry1.tcl +│   │   │   │   │   ├── entry2.tcl +│   │   │   │   │   ├── entry3.tcl +│   │   │   │   │   ├── filebox.tcl +│   │   │   │   │   ├── floor.tcl +│   │   │   │   │   ├── fontchoose.tcl +│   │   │   │   │   ├── form.tcl +│   │   │   │   │   ├── goldberg.tcl +│   │   │   │   │   ├── hello +│   │   │   │   │   ├── hscale.tcl +│   │   │   │   │   ├── icon.tcl +│   │   │   │   │   ├── image1.tcl +│   │   │   │   │   ├── image2.tcl +│   │   │   │   │   ├── images +│   │   │   │   │   │   ├── earth.gif +│   │   │   │   │   │   ├── earthmenu.png +│   │   │   │   │   │   ├── earthris.gif +│   │   │   │   │   │   ├── flagdown.xbm +│   │   │   │   │   │   ├── flagup.xbm +│   │   │   │   │   │   ├── gray25.xbm +│   │   │   │   │   │   ├── letters.xbm +│   │   │   │   │   │   ├── noletter.xbm +│   │   │   │   │   │   ├── ouster.png +│   │   │   │   │   │   ├── pattern.xbm +│   │   │   │   │   │   ├── tcllogo.gif +│   │   │   │   │   │   └── teapot.ppm +│   │   │   │   │   ├── items.tcl +│   │   │   │   │   ├── ixset +│   │   │   │   │   ├── knightstour.tcl +│   │   │   │   │   ├── labelframe.tcl +│   │   │   │   │   ├── label.tcl +│   │   │   │   │   ├── license.terms +│   │   │   │   │   ├── mclist.tcl +│   │   │   │   │   ├── menubu.tcl +│   │   │   │   │   ├── menu.tcl +│   │   │   │   │   ├── msgbox.tcl +│   │   │   │   │   ├── nl.msg +│   │   │   │   │   ├── paned1.tcl +│   │   │   │   │   ├── paned2.tcl +│   │   │   │   │   ├── pendulum.tcl +│   │   │   │   │   ├── plot.tcl +│   │   │   │   │   ├── puzzle.tcl +│   │   │   │   │   ├── radio.tcl +│   │   │   │   │   ├── README +│   │   │   │   │   ├── rmt +│   │   │   │   │   ├── rolodex +│   │   │   │   │   ├── ruler.tcl +│   │   │   │   │   ├── sayings.tcl +│   │   │   │   │   ├── search.tcl +│   │   │   │   │   ├── spin.tcl +│   │   │   │   │   ├── states.tcl +│   │   │   │   │   ├── style.tcl +│   │   │   │   │   ├── tclIndex +│   │   │   │   │   ├── tcolor +│   │   │   │   │   ├── textpeer.tcl +│   │   │   │   │   ├── text.tcl +│   │   │   │   │   ├── timer +│   │   │   │   │   ├── toolbar.tcl +│   │   │   │   │   ├── tree.tcl +│   │   │   │   │   ├── ttkbut.tcl +│   │   │   │   │   ├── ttkmenu.tcl +│   │   │   │   │   ├── ttknote.tcl +│   │   │   │   │   ├── ttkpane.tcl +│   │   │   │   │   ├── ttkprogress.tcl +│   │   │   │   │   ├── ttkscale.tcl +│   │   │   │   │   ├── twind.tcl +│   │   │   │   │   ├── unicodeout.tcl +│   │   │   │   │   ├── vscale.tcl +│   │   │   │   │   └── widget +│   │   │   │   ├── dialog.tcl +│   │   │   │   ├── entry.tcl +│   │   │   │   ├── focus.tcl +│   │   │   │   ├── fontchooser.tcl +│   │   │   │   ├── iconlist.tcl +│   │   │   │   ├── icons.tcl +│   │   │   │   ├── images +│   │   │   │   │   ├── logo100.gif +│   │   │   │   │   ├── logo64.gif +│   │   │   │   │   ├── logo.eps +│   │   │   │   │   ├── logoLarge.gif +│   │   │   │   │   ├── logoMed.gif +│   │   │   │   │   ├── pwrdLogo100.gif +│   │   │   │   │   ├── pwrdLogo150.gif +│   │   │   │   │   ├── pwrdLogo175.gif +│   │   │   │   │   ├── pwrdLogo200.gif +│   │   │   │   │   ├── pwrdLogo75.gif +│   │   │   │   │   ├── pwrdLogo.eps +│   │   │   │   │   ├── README +│   │   │   │   │   └── tai-ku.gif +│   │   │   │   ├── listbox.tcl +│   │   │   │   ├── megawidget.tcl +│   │   │   │   ├── menu.tcl +│   │   │   │   ├── mkpsenc.tcl +│   │   │   │   ├── msgbox.tcl +│   │   │   │   ├── msgs +│   │   │   │   │   ├── cs.msg +│   │   │   │   │   ├── da.msg +│   │   │   │   │   ├── de.msg +│   │   │   │   │   ├── el.msg +│   │   │   │   │   ├── en_gb.msg +│   │   │   │   │   ├── en.msg +│   │   │   │   │   ├── eo.msg +│   │   │   │   │   ├── es.msg +│   │   │   │   │   ├── fi.msg +│   │   │   │   │   ├── fr.msg +│   │   │   │   │   ├── hu.msg +│   │   │   │   │   ├── it.msg +│   │   │   │   │   ├── nl.msg +│   │   │   │   │   ├── pl.msg +│   │   │   │   │   ├── pt.msg +│   │   │   │   │   ├── ru.msg +│   │   │   │   │   ├── sv.msg +│   │   │   │   │   └── zh_cn.msg +│   │   │   │   ├── obsolete.tcl +│   │   │   │   ├── optMenu.tcl +│   │   │   │   ├── palette.tcl +│   │   │   │   ├── panedwindow.tcl +│   │   │   │   ├── pkgIndex.tcl +│   │   │   │   ├── safetk.tcl +│   │   │   │   ├── scale.tcl +│   │   │   │   ├── scrlbar.tcl +│   │   │   │   ├── spinbox.tcl +│   │   │   │   ├── tclIndex +│   │   │   │   ├── tearoff.tcl +│   │   │   │   ├── text.tcl +│   │   │   │   ├── tkAppInit.c +│   │   │   │   ├── tkfbox.tcl +│   │   │   │   ├── tk.tcl +│   │   │   │   ├── ttk +│   │   │   │   │   ├── altTheme.tcl +│   │   │   │   │   ├── aquaTheme.tcl +│   │   │   │   │   ├── button.tcl +│   │   │   │   │   ├── clamTheme.tcl +│   │   │   │   │   ├── classicTheme.tcl +│   │   │   │   │   ├── combobox.tcl +│   │   │   │   │   ├── cursors.tcl +│   │   │   │   │   ├── defaults.tcl +│   │   │   │   │   ├── entry.tcl +│   │   │   │   │   ├── fonts.tcl +│   │   │   │   │   ├── menubutton.tcl +│   │   │   │   │   ├── notebook.tcl +│   │   │   │   │   ├── panedwindow.tcl +│   │   │   │   │   ├── progress.tcl +│   │   │   │   │   ├── scale.tcl +│   │   │   │   │   ├── scrollbar.tcl +│   │   │   │   │   ├── sizegrip.tcl +│   │   │   │   │   ├── spinbox.tcl +│   │   │   │   │   ├── treeview.tcl +│   │   │   │   │   ├── ttk.tcl +│   │   │   │   │   ├── utils.tcl +│   │   │   │   │   ├── vistaTheme.tcl +│   │   │   │   │   ├── winTheme.tcl +│   │   │   │   │   └── xpTheme.tcl +│   │   │   │   ├── unsupported.tcl +│   │   │   │   └── xmfbox.tcl +│   │   │   └── tkConfig.sh +│   │   ├── sbin +│   │   │   ├── gss-server +│   │   │   ├── kadmind +│   │   │   ├── kadmin.local +│   │   │   ├── kdb5_util +│   │   │   ├── key.dns_resolver +│   │   │   ├── kprop +│   │   │   ├── kpropd +│   │   │   ├── kproplog +│   │   │   ├── krb5kdc +│   │   │   ├── krb5-send-pr +│   │   │   ├── request-key +│   │   │   ├── sim_server +│   │   │   ├── sserver +│   │   │   └── uuserver +│   │   ├── share +│   │   │   ├── doc +│   │   │   │   └── readline +│   │   │   │   ├── CHANGES +│   │   │   │   ├── history.html +│   │   │   │   ├── INSTALL +│   │   │   │   ├── readline.html +│   │   │   │   ├── README +│   │   │   │   └── rluserman.html +│   │   │   ├── et +│   │   │   │   ├── et_c.awk +│   │   │   │   └── et_h.awk +│   │   │   ├── examples +│   │   │   │   └── krb5 +│   │   │   │   ├── kdc.conf +│   │   │   │   ├── krb5.conf +│   │   │   │   └── services.append +│   │   │   ├── icu +│   │   │   │   └── 78.3 +│   │   │   │   ├── config +│   │   │   │   │   └── mh-linux +│   │   │   │   ├── install-sh +│   │   │   │   ├── LICENSE +│   │   │   │   └── mkinstalldirs +│   │   │   ├── info +│   │   │   │   ├── history.info +│   │   │   │   ├── libffi.info +│   │   │   │   ├── libgomp.info +│   │   │   │   ├── libquadmath.info +│   │   │   │   ├── readline.info +│   │   │   │   └── rluserman.info +│   │   │   ├── jupyter +│   │   │   │   └── kernels +│   │   │   │   └── mojo +│   │   │   │   ├── kernel.json +│   │   │   │   ├── logo-64x64.png +│   │   │   │   ├── logo.svg +│   │   │   │   ├── manage_kernel.py +│   │   │   │   ├── mojokernel.py +│   │   │   │   ├── nightly-logo-64x64.png +│   │   │   │   └── nightly-logo.svg +│   │   │   ├── keyutils +│   │   │   │   └── request-key-debug.sh +│   │   │   ├── licenses +│   │   │   │   ├── gcc-libs +│   │   │   │   │   ├── RUNTIME.LIBRARY.EXCEPTION +│   │   │   │   │   └── RUNTIME.LIBRARY.EXCEPTION.gomp_copy +│   │   │   │   └── libstdc++ +│   │   │   │   └── RUNTIME.LIBRARY.EXCEPTION +│   │   │   ├── locale +│   │   │   │   ├── de +│   │   │   │   │   └── LC_MESSAGES +│   │   │   │   │   └── mit-krb5.mo +│   │   │   │   ├── en_US +│   │   │   │   │   └── LC_MESSAGES +│   │   │   │   │   └── mit-krb5.mo +│   │   │   │   └── ka +│   │   │   │   └── LC_MESSAGES +│   │   │   │   └── mit-krb5.mo +│   │   │   ├── man +│   │   │   │   ├── man1 +│   │   │   │   │   ├── bzcmp.1 +│   │   │   │   │   ├── bzdiff.1 +│   │   │   │   │   ├── bzegrep.1 +│   │   │   │   │   ├── bzfgrep.1 +│   │   │   │   │   ├── bzgrep.1 +│   │   │   │   │   ├── bzip2.1 +│   │   │   │   │   ├── bzless.1 +│   │   │   │   │   ├── bzmore.1 +│   │   │   │   │   ├── compile_et.1 +│   │   │   │   │   ├── derb.1 +│   │   │   │   │   ├── genbrk.1 +│   │   │   │   │   ├── gencfu.1 +│   │   │   │   │   ├── gencnval.1 +│   │   │   │   │   ├── gendict.1 +│   │   │   │   │   ├── genrb.1 +│   │   │   │   │   ├── icu-config.1 +│   │   │   │   │   ├── icuexportdata.1 +│   │   │   │   │   ├── k5srvutil.1 +│   │   │   │   │   ├── kadmin.1 +│   │   │   │   │   ├── kdestroy.1 +│   │   │   │   │   ├── keyctl.1 +│   │   │   │   │   ├── kinit.1 +│   │   │   │   │   ├── klist.1 +│   │   │   │   │   ├── kpasswd.1 +│   │   │   │   │   ├── krb5-config.1 +│   │   │   │   │   ├── ksu.1 +│   │   │   │   │   ├── kswitch.1 +│   │   │   │   │   ├── ktutil.1 +│   │   │   │   │   ├── kvno.1 +│   │   │   │   │   ├── makeconv.1 +│   │   │   │   │   ├── mojo.1 +│   │   │   │   │   ├── mojo-build.1 +│   │   │   │   │   ├── mojo-debug.1 +│   │   │   │   │   ├── mojo-demangle.1 +│   │   │   │   │   ├── mojo-doc.1 +│   │   │   │   │   ├── mojo-format.1 +│   │   │   │   │   ├── mojo-package.1 +│   │   │   │   │   ├── mojo-repl.1 +│   │   │   │   │   ├── mojo-run.1 +│   │   │   │   │   ├── pkgdata.1 +│   │   │   │   │   ├── python3.1 -> python3.12.1 +│   │   │   │   │   ├── python3.12.1 +│   │   │   │   │   └── sclient.1 +│   │   │   │   ├── man3 +│   │   │   │   │   ├── crypt.3 +│   │   │   │   │   ├── crypt_checksalt.3 +│   │   │   │   │   ├── crypt_gensalt.3 +│   │   │   │   │   ├── crypt_gensalt_ra.3 +│   │   │   │   │   ├── crypt_gensalt_rn.3 +│   │   │   │   │   ├── crypt_preferred_method.3 +│   │   │   │   │   ├── crypt_r.3 +│   │   │   │   │   ├── crypt_ra.3 +│   │   │   │   │   ├── crypt_rn.3 +│   │   │   │   │   ├── editline.3 +│   │   │   │   │   ├── el_deletestr.3 -> editline.3 +│   │   │   │   │   ├── el_end.3 -> editline.3 +│   │   │   │   │   ├── el_get.3 -> editline.3 +│   │   │   │   │   ├── el_getc.3 -> editline.3 +│   │   │   │   │   ├── el_gets.3 -> editline.3 +│   │   │   │   │   ├── el_history.3 -> editline.3 +│   │   │   │   │   ├── el_history_end.3 -> editline.3 +│   │   │   │   │   ├── el_history_init.3 -> editline.3 +│   │   │   │   │   ├── el_history_w.3 -> editline.3 +│   │   │   │   │   ├── el_history_wend.3 -> editline.3 +│   │   │   │   │   ├── el_history_winit.3 -> editline.3 +│   │   │   │   │   ├── el_init.3 -> editline.3 +│   │   │   │   │   ├── el_init_fd.3 -> editline.3 +│   │   │   │   │   ├── el_insertstr.3 -> editline.3 +│   │   │   │   │   ├── el_line.3 -> editline.3 +│   │   │   │   │   ├── el_parse.3 -> editline.3 +│   │   │   │   │   ├── el_push.3 -> editline.3 +│   │   │   │   │   ├── el_reset.3 -> editline.3 +│   │   │   │   │   ├── el_resize.3 -> editline.3 +│   │   │   │   │   ├── el_set.3 -> editline.3 +│   │   │   │   │   ├── el_source.3 -> editline.3 +│   │   │   │   │   ├── el_tok_end.3 -> editline.3 +│   │   │   │   │   ├── el_tok_init.3 -> editline.3 +│   │   │   │   │   ├── el_tok_line.3 -> editline.3 +│   │   │   │   │   ├── el_tok_reset.3 -> editline.3 +│   │   │   │   │   ├── el_tok_str.3 -> editline.3 +│   │   │   │   │   ├── el_tok_wend.3 -> editline.3 +│   │   │   │   │   ├── el_tok_winit.3 -> editline.3 +│   │   │   │   │   ├── el_tok_wline.3 -> editline.3 +│   │   │   │   │   ├── el_tok_wreset.3 -> editline.3 +│   │   │   │   │   ├── el_tok_wstr.3 -> editline.3 +│   │   │   │   │   ├── el_wdeletestr.3 -> editline.3 +│   │   │   │   │   ├── el_wget.3 -> editline.3 +│   │   │   │   │   ├── el_wgetc.3 -> editline.3 +│   │   │   │   │   ├── el_wgets.3 -> editline.3 +│   │   │   │   │   ├── el_winsertstr.3 -> editline.3 +│   │   │   │   │   ├── el_wline.3 -> editline.3 +│   │   │   │   │   ├── el_wparse.3 -> editline.3 +│   │   │   │   │   ├── el_wpush.3 -> editline.3 +│   │   │   │   │   ├── el_wset.3 -> editline.3 +│   │   │   │   │   ├── ffi.3 +│   │   │   │   │   ├── ffi_call.3 +│   │   │   │   │   ├── ffi_prep_cif.3 +│   │   │   │   │   ├── ffi_prep_cif_var.3 +│   │   │   │   │   ├── find_key_by_type_and_name.3 +│   │   │   │   │   ├── history.3 +│   │   │   │   │   ├── keyctl.3 +│   │   │   │   │   ├── keyctl_assume_authority.3 -> keyctl_instantiate.3 +│   │   │   │   │   ├── keyctl_capabilities.3 +│   │   │   │   │   ├── keyctl_chown.3 +│   │   │   │   │   ├── keyctl_clear.3 +│   │   │   │   │   ├── keyctl_describe.3 +│   │   │   │   │   ├── keyctl_describe_alloc.3 -> keyctl_describe.3 +│   │   │   │   │   ├── keyctl_dh_compute.3 +│   │   │   │   │   ├── keyctl_dh_compute_alloc.3 -> keyctl_dh_compute.3 +│   │   │   │   │   ├── keyctl_dh_compute_kdf.3 -> keyctl_dh_compute.3 +│   │   │   │   │   ├── keyctl_get_keyring_ID.3 +│   │   │   │   │   ├── keyctl_get_persistent.3 +│   │   │   │   │   ├── keyctl_get_security.3 +│   │   │   │   │   ├── keyctl_get_security_alloc.3 -> keyctl_get_security.3 +│   │   │   │   │   ├── keyctl_instantiate.3 +│   │   │   │   │   ├── keyctl_instantiate_iov.3 -> keyctl_instantiate.3 +│   │   │   │   │   ├── keyctl_invalidate.3 +│   │   │   │   │   ├── keyctl_join_session_keyring.3 +│   │   │   │   │   ├── keyctl_link.3 +│   │   │   │   │   ├── keyctl_move.3 +│   │   │   │   │   ├── keyctl_negate.3 -> keyctl_instantiate.3 +│   │   │   │   │   ├── keyctl_pkey_decrypt.3 +│   │   │   │   │   ├── keyctl_pkey_encrypt.3 +│   │   │   │   │   ├── keyctl_pkey_query.3 +│   │   │   │   │   ├── keyctl_pkey_sign.3 +│   │   │   │   │   ├── keyctl_pkey_verify.3 +│   │   │   │   │   ├── keyctl_read.3 +│   │   │   │   │   ├── keyctl_read_alloc.3 -> keyctl_read.3 +│   │   │   │   │   ├── keyctl_reject.3 -> keyctl_instantiate.3 +│   │   │   │   │   ├── keyctl_restrict_keyring.3 +│   │   │   │   │   ├── keyctl_revoke.3 +│   │   │   │   │   ├── keyctl_search.3 +│   │   │   │   │   ├── keyctl_session_to_parent.3 +│   │   │   │   │   ├── keyctl_setperm.3 +│   │   │   │   │   ├── keyctl_set_reqkey_keyring.3 +│   │   │   │   │   ├── keyctl_set_timeout.3 +│   │   │   │   │   ├── keyctl_unlink.3 -> keyctl_link.3 +│   │   │   │   │   ├── keyctl_update.3 +│   │   │   │   │   ├── keyctl_watch_key.3 +│   │   │   │   │   ├── readline.3 +│   │   │   │   │   ├── recursive_key_scan.3 +│   │   │   │   │   └── recursive_session_key_scan.3 -> recursive_key_scan.3 +│   │   │   │   ├── man5 +│   │   │   │   │   ├── crypt.5 +│   │   │   │   │   ├── editrc.5 +│   │   │   │   │   ├── .k5identity.5 +│   │   │   │   │   ├── k5identity.5 +│   │   │   │   │   ├── .k5login.5 +│   │   │   │   │   ├── k5login.5 +│   │   │   │   │   ├── kadm5.acl.5 +│   │   │   │   │   ├── kdc.conf.5 +│   │   │   │   │   ├── key.dns_resolver.conf.5 +│   │   │   │   │   ├── krb5.conf.5 +│   │   │   │   │   └── request-key.conf.5 +│   │   │   │   ├── man7 +│   │   │   │   │   ├── asymmetric-key.7 +│   │   │   │   │   ├── editline.7 +│   │   │   │   │   ├── kerberos.7 +│   │   │   │   │   └── keyutils.7 +│   │   │   │   └── man8 +│   │   │   │   ├── genccode.8 +│   │   │   │   ├── gencmn.8 +│   │   │   │   ├── gensprep.8 +│   │   │   │   ├── icupkg.8 +│   │   │   │   ├── kadmind.8 +│   │   │   │   ├── kadmin.local.8 +│   │   │   │   ├── kdb5_ldap_util.8 +│   │   │   │   ├── kdb5_util.8 +│   │   │   │   ├── key.dns_resolver.8 +│   │   │   │   ├── kprop.8 +│   │   │   │   ├── kpropd.8 +│   │   │   │   ├── kproplog.8 +│   │   │   │   ├── krb5kdc.8 +│   │   │   │   ├── request-key.8 +│   │   │   │   └── sserver.8 +│   │   │   ├── max +│   │   │   │   ├── cache +│   │   │   │   │   └── .mojo_cache +│   │   │   │   │   └── mojo +│   │   │   │   │   └── transform +│   │   │   │   │   └── 1.0.0b1.dev2026042817a8e9fbebcd07fcee4a6fe028b12dff63-production +│   │   │   │   │   ├── Mzk3ZjcxZGY1NDM0ZDM1MDM4Mjk4N2I2Y2EwOTVjMmI +│   │   │   │   │   ├── NTA2OTA1YmU3ODI1ODJhYzQ2NTBjZmYzOWQ2NmUyYTY +│   │   │   │   │   ├── NTNmYzIyMjc0NGM4OTM2ODgxODEwOTgxZGQyMTAxMTM +│   │   │   │   │   ├── NzI5MmQ4YjVhYmQyNWYzNDYwZmQ2ODM0NjRhMmFhYWI +│   │   │   │   │   └── YmMwMTA3MDg1MTNhYjg4MTI4MTM1M2EzOWM4OTJiMjU +│   │   │   │   ├── crashdb +│   │   │   │   │   ├── attachments +│   │   │   │   │   ├── completed +│   │   │   │   │   ├── new +│   │   │   │   │   ├── pending +│   │   │   │   │   └── settings.dat +│   │   │   │   ├── firstActivation +│   │   │   │   └── modular.cfg +│   │   │   ├── tabset +│   │   │   │   ├── std +│   │   │   │   ├── stdcrt +│   │   │   │   ├── vt100 +│   │   │   │   └── vt300 +│   │   │   ├── terminfo +│   │   │   │   ├── 31 +│   │   │   │   │   ├── 1178 -> .././61/adm1178 +│   │   │   │   │   └── 1730-lm -> .././64/diablo1740-lm +│   │   │   │   ├── 32 +│   │   │   │   │   ├── 2621 -> .././68/hp2621 +│   │   │   │   │   ├── 2621a -> .././68/hp2621 +│   │   │   │   │   ├── 2621A -> .././68/hp2621 +│   │   │   │   │   └── 2621-wl -> .././68/hp2621 +│   │   │   │   ├── 33 +│   │   │   │   │   ├── 386at -> .././61/att6386 +│   │   │   │   │   └── 3b1 -> .././61/att7300 +│   │   │   │   ├── 34 +│   │   │   │   │   ├── 4025ex -> .././74/tek4025ex +│   │   │   │   │   ├── 4027ex -> .././74/tek4025ex +│   │   │   │   │   └── 4410-w -> .././61/att5410-w +│   │   │   │   ├── 35 +│   │   │   │   │   ├── 5051 -> .././69/ibm-pc +│   │   │   │   │   ├── 5410-w -> .././61/att5410-w +│   │   │   │   │   ├── 5620 -> .././61/att5620 +│   │   │   │   │   ├── 5630-24 -> .././61/att630-24 +│   │   │   │   │   └── 5630DMD-24 -> .././61/att630-24 +│   │   │   │   ├── 36 +│   │   │   │   │   ├── 6053 -> .././64/dg6053 +│   │   │   │   │   ├── 6053-dg -> .././64/dg6053 +│   │   │   │   │   ├── 605x -> .././64/dg6053 +│   │   │   │   │   ├── 605x-dg -> .././64/dg6053 +│   │   │   │   │   ├── 630-lm -> .././64/diablo1740-lm +│   │   │   │   │   └── 630MTG-24 -> .././61/att630-24 +│   │   │   │   ├── 37 +│   │   │   │   │   ├── 730MTG-24 -> .././61/att730-24 +│   │   │   │   │   ├── 730MTG-41 -> .././61/att730-41 +│   │   │   │   │   ├── 730MTG-41r -> .././61/att730r-41 +│   │   │   │   │   ├── 730MTGr -> .././61/att730r +│   │   │   │   │   └── 730MTGr-24 -> .././61/att730r-24 +│   │   │   │   ├── 38 +│   │   │   │   │   └── 8510 -> .././63/citoh +│   │   │   │   ├── 39 +│   │   │   │   │   ├── 955-hb -> .././74/tvi955-hb +│   │   │   │   │   ├── 955-w -> .././74/tvi955-w +│   │   │   │   │   └── 9term +│   │   │   │   ├── 41 +│   │   │   │   │   └── Apple_Terminal -> .././6e/nsterm +│   │   │   │   ├── 45 +│   │   │   │   │   ├── Eterm +│   │   │   │   │   ├── Eterm-256color +│   │   │   │   │   ├── Eterm-88color +│   │   │   │   │   └── Eterm-color -> .././45/Eterm +│   │   │   │   ├── 4c +│   │   │   │   │   └── LFT-PC850 -> .././6c/lft +│   │   │   │   ├── 4d +│   │   │   │   │   ├── MtxOrb +│   │   │   │   │   ├── MtxOrb162 +│   │   │   │   │   └── MtxOrb204 +│   │   │   │   ├── 4e +│   │   │   │   │   ├── NCR260VT300WPP -> .././6e/ncr260vt300wpp +│   │   │   │   │   └── NCRVT100WPP -> .././6e/ncrvt100wan +│   │   │   │   ├── 50 +│   │   │   │   │   ├── P12 -> .././70/prism12 +│   │   │   │   │   ├── P12-M -> .././70/prism12-m +│   │   │   │   │   ├── P12-M-W -> .././70/prism12-m-w +│   │   │   │   │   ├── P12-W -> .././70/prism12-w +│   │   │   │   │   ├── P14 -> .././70/prism14 +│   │   │   │   │   ├── P14-M -> .././70/prism14-m +│   │   │   │   │   ├── P14-M-W -> .././70/prism14-m-w +│   │   │   │   │   ├── P14-W -> .././70/prism14-w +│   │   │   │   │   ├── P4 -> .././70/prism4 +│   │   │   │   │   ├── P5 -> .././70/prism5 +│   │   │   │   │   ├── P7 -> .././70/prism7 +│   │   │   │   │   ├── P8 -> .././70/prism8 +│   │   │   │   │   ├── P8-W -> .././70/prism8-w +│   │   │   │   │   ├── P9 -> .././70/prism9 +│   │   │   │   │   ├── P9-8 -> .././70/prism9-8 +│   │   │   │   │   ├── P9-8-W -> .././70/prism9-8-w +│   │   │   │   │   └── P9-W -> .././70/prism9-w +│   │   │   │   ├── 51 +│   │   │   │   │   ├── Q306-8-pc -> .././62/bq300-8-pc +│   │   │   │   │   ├── Q310-vip-H -> .././76/vip-H +│   │   │   │   │   ├── Q310-vip-H-am -> .././76/vip-H +│   │   │   │   │   ├── Q310-vip-Hw -> .././76/vip-Hw +│   │   │   │   │   ├── Q310-vip-w -> .././76/vip-w +│   │   │   │   │   └── Q310-vip-w-am -> .././76/vip-w +│   │   │   │   ├── 58 +│   │   │   │   │   ├── X-hpterm -> .././68/hpterm +│   │   │   │   │   └── X-hpterm-color2 -> .././68/hpterm-color2 +│   │   │   │   ├── 61 +│   │   │   │   │   ├── a210 -> .././61/ampex210 +│   │   │   │   │   ├── a80 -> .././61/ampex80 +│   │   │   │   │   ├── a980 -> .././61/adds980 +│   │   │   │   │   ├── aa4080 -> .././61/annarbor4080 +│   │   │   │   │   ├── aaa +│   │   │   │   │   ├── aaa-18 +│   │   │   │   │   ├── aaa-18-rv +│   │   │   │   │   ├── aaa-20 +│   │   │   │   │   ├── aaa-22 +│   │   │   │   │   ├── aaa-24 +│   │   │   │   │   ├── aaa-24-rv +│   │   │   │   │   ├── aaa-26 +│   │   │   │   │   ├── aaa-28 +│   │   │   │   │   ├── aaa-30 -> .././61/aaa +│   │   │   │   │   ├── aaa-30-ctxt +│   │   │   │   │   ├── aaa-30-rv +│   │   │   │   │   ├── aaa-30-rv-ctxt +│   │   │   │   │   ├── aaa-30-s +│   │   │   │   │   ├── aaa-30-s-ctxt -> .././61/aaa-s-ctxt +│   │   │   │   │   ├── aaa-30-s-rv +│   │   │   │   │   ├── aaa-30-s-rv-ct -> .././61/aaa-s-rv-ctxt +│   │   │   │   │   ├── aaa-36 +│   │   │   │   │   ├── aaa-36-rv +│   │   │   │   │   ├── aaa-40 +│   │   │   │   │   ├── aaa-40-rv +│   │   │   │   │   ├── aaa-48 +│   │   │   │   │   ├── aaa-48-rv +│   │   │   │   │   ├── aaa-60 +│   │   │   │   │   ├── aaa-60-dec-rv +│   │   │   │   │   ├── aaa-60-rv +│   │   │   │   │   ├── aaa-60-s +│   │   │   │   │   ├── aaa-60-s-rv +│   │   │   │   │   ├── aaa-ctxt -> .././61/aaa-30-ctxt +│   │   │   │   │   ├── aaa-db +│   │   │   │   │   ├── aaa+dec +│   │   │   │   │   ├── aaa+rv +│   │   │   │   │   ├── aaa-rv -> .././61/aaa-30-rv +│   │   │   │   │   ├── aaa-rv-ctxt -> .././61/aaa-30-rv-ctxt +│   │   │   │   │   ├── aaa-rv-unk +│   │   │   │   │   ├── aaa-s -> .././61/aaa-30-s +│   │   │   │   │   ├── aaa-s-ctxt +│   │   │   │   │   ├── aaa-s-rv -> .././61/aaa-30-s-rv +│   │   │   │   │   ├── aaa-s-rv-ctxt +│   │   │   │   │   ├── aaa+unk +│   │   │   │   │   ├── aaa-unk -> .././61/aaa+unk +│   │   │   │   │   ├── aas1901 +│   │   │   │   │   ├── abm80 +│   │   │   │   │   ├── abm85 +│   │   │   │   │   ├── abm85e +│   │   │   │   │   ├── abm85h +│   │   │   │   │   ├── abm85h-old +│   │   │   │   │   ├── absolute +│   │   │   │   │   ├── act4 +│   │   │   │   │   ├── act5 +│   │   │   │   │   ├── addrinfo +│   │   │   │   │   ├── adds200 -> .././72/regent60 +│   │   │   │   │   ├── adds980 +│   │   │   │   │   ├── addsviewpoint -> .././76/viewpoint +│   │   │   │   │   ├── addsvp60 -> .././76/vp60 +│   │   │   │   │   ├── adm1 -> .././61/adm1a +│   │   │   │   │   ├── adm11 +│   │   │   │   │   ├── adm1178 +│   │   │   │   │   ├── adm12 +│   │   │   │   │   ├── adm1a +│   │   │   │   │   ├── adm2 +│   │   │   │   │   ├── adm20 +│   │   │   │   │   ├── adm21 +│   │   │   │   │   ├── adm22 +│   │   │   │   │   ├── adm3 +│   │   │   │   │   ├── adm31 +│   │   │   │   │   ├── adm31-old +│   │   │   │   │   ├── adm36 +│   │   │   │   │   ├── adm3a +│   │   │   │   │   ├── adm3a+ +│   │   │   │   │   ├── adm42 +│   │   │   │   │   ├── adm42-ns +│   │   │   │   │   ├── adm5 +│   │   │   │   │   ├── adm+sgr +│   │   │   │   │   ├── aepro +│   │   │   │   │   ├── aixterm +│   │   │   │   │   ├── aixterm-16color +│   │   │   │   │   ├── aixterm-m +│   │   │   │   │   ├── aixterm-m-old +│   │   │   │   │   ├── aixterm+sl +│   │   │   │   │   ├── aj -> .././61/aj830 +│   │   │   │   │   ├── aj510 +│   │   │   │   │   ├── aj830 +│   │   │   │   │   ├── aj832 -> .././61/aj830 +│   │   │   │   │   ├── alacritty +│   │   │   │   │   ├── alacritty+common +│   │   │   │   │   ├── alacritty-direct +│   │   │   │   │   ├── alt2 -> .././61/altos2 +│   │   │   │   │   ├── alt3 -> .././61/altos3 +│   │   │   │   │   ├── alt4 -> .././61/altos4 +│   │   │   │   │   ├── alt5 -> .././61/altos3 +│   │   │   │   │   ├── alt7 -> .././61/altos7 +│   │   │   │   │   ├── alt7pc -> .././61/altos7pc +│   │   │   │   │   ├── alto-h19 +│   │   │   │   │   ├── altoh19 -> .././61/alto-h19 +│   │   │   │   │   ├── alto-heath -> .././61/alto-h19 +│   │   │   │   │   ├── altoheath -> .././61/alto-h19 +│   │   │   │   │   ├── altos-2 -> .././61/altos2 +│   │   │   │   │   ├── altos2 +│   │   │   │   │   ├── altos-3 -> .././61/altos3 +│   │   │   │   │   ├── altos3 +│   │   │   │   │   ├── altos-4 -> .././61/altos4 +│   │   │   │   │   ├── altos4 +│   │   │   │   │   ├── altos-5 -> .././61/altos3 +│   │   │   │   │   ├── altos5 -> .././61/altos3 +│   │   │   │   │   ├── altos7 +│   │   │   │   │   ├── altos7pc +│   │   │   │   │   ├── ambas -> .././61/aaa +│   │   │   │   │   ├── ambassador -> .././61/aaa +│   │   │   │   │   ├── amiga +│   │   │   │   │   ├── amiga-8bit +│   │   │   │   │   ├── amiga-h +│   │   │   │   │   ├── amiga-vnc +│   │   │   │   │   ├── amp219 -> .././61/ampex219 +│   │   │   │   │   ├── amp219w -> .././61/ampex219w +│   │   │   │   │   ├── ampex175 +│   │   │   │   │   ├── ampex175-b +│   │   │   │   │   ├── ampex210 +│   │   │   │   │   ├── ampex-219 -> .././61/ampex219 +│   │   │   │   │   ├── ampex219 +│   │   │   │   │   ├── ampex-219w -> .././61/ampex219w +│   │   │   │   │   ├── ampex219w +│   │   │   │   │   ├── ampex-232 -> .././61/ampex232 +│   │   │   │   │   ├── ampex232 +│   │   │   │   │   ├── ampex232w +│   │   │   │   │   ├── ampex80 +│   │   │   │   │   ├── annarbor4080 +│   │   │   │   │   ├── ansi +│   │   │   │   │   ├── ansi43m -> .././70/pcansi-43-m +│   │   │   │   │   ├── ansi77 +│   │   │   │   │   ├── ansi80x25 -> .././63/cons25 +│   │   │   │   │   ├── ansi80x25-mono -> .././63/cons25-m +│   │   │   │   │   ├── ansi80x25-raw -> .././63/cons25w +│   │   │   │   │   ├── ansi80x30 -> .././63/cons30 +│   │   │   │   │   ├── ansi80x30-mono -> .././63/cons30-m +│   │   │   │   │   ├── ansi80x43 -> .././63/cons43 +│   │   │   │   │   ├── ansi80x43-mono -> .././63/cons43-m +│   │   │   │   │   ├── ansi80x50 -> .././63/cons50 +│   │   │   │   │   ├── ansi80x50-mono -> .././63/cons50-m +│   │   │   │   │   ├── ansi80x60 -> .././63/cons60 +│   │   │   │   │   ├── ansi80x60-mono -> .././63/cons60-m +│   │   │   │   │   ├── ansi+apparrows +│   │   │   │   │   ├── ansi+arrows +│   │   │   │   │   ├── ansi-color-2-emx +│   │   │   │   │   ├── ansi-color-3-emx +│   │   │   │   │   ├── ansi+cpr +│   │   │   │   │   ├── ansi+csr +│   │   │   │   │   ├── ansi+cup +│   │   │   │   │   ├── ansi-emx +│   │   │   │   │   ├── ansi+enq +│   │   │   │   │   ├── ansi+erase +│   │   │   │   │   ├── ansi-generic +│   │   │   │   │   ├── ansi+idc +│   │   │   │   │   ├── ansi+idc1 +│   │   │   │   │   ├── ansi+idl +│   │   │   │   │   ├── ansi+idl1 +│   │   │   │   │   ├── ansi+inittabs +│   │   │   │   │   ├── ansil -> .././63/cons50 +│   │   │   │   │   ├── ansil-mono -> .././63/cons50-m +│   │   │   │   │   ├── ansi+local +│   │   │   │   │   ├── ansi+local1 +│   │   │   │   │   ├── ansi-m +│   │   │   │   │   ├── ansi-mini +│   │   │   │   │   ├── ansi-mono -> .././61/ansi-m +│   │   │   │   │   ├── ansi-mr +│   │   │   │   │   ├── ansi-mtabs +│   │   │   │   │   ├── ansi-nt +│   │   │   │   │   ├── ansi+pp +│   │   │   │   │   ├── ansi+rca +│   │   │   │   │   ├── ansi+rca2 +│   │   │   │   │   ├── ansi+rep +│   │   │   │   │   ├── ansis -> .././63/cons25 +│   │   │   │   │   ├── ansi+sgr +│   │   │   │   │   ├── ansi+sgrbold +│   │   │   │   │   ├── ansi+sgrdim +│   │   │   │   │   ├── ansi+sgrso +│   │   │   │   │   ├── ansi+sgrul +│   │   │   │   │   ├── ansis-mono -> .././63/cons25-m +│   │   │   │   │   ├── ansi.sys +│   │   │   │   │   ├── ansi.sysk +│   │   │   │   │   ├── ansisysk -> .././61/ansi.sysk +│   │   │   │   │   ├── ansi.sys-old +│   │   │   │   │   ├── ansi+tabs +│   │   │   │   │   ├── ansiterm -> .././61/ansi-generic +│   │   │   │   │   ├── ansiw -> .././63/cons25w +│   │   │   │   │   ├── apl -> .././69/ibm-apl +│   │   │   │   │   ├── apollo +│   │   │   │   │   ├── apollo_15P +│   │   │   │   │   ├── apollo_19L +│   │   │   │   │   ├── apollo_color +│   │   │   │   │   ├── apollo+vt132 +│   │   │   │   │   ├── apple2e +│   │   │   │   │   ├── apple2e-p +│   │   │   │   │   ├── apple-80 +│   │   │   │   │   ├── apple80p +│   │   │   │   │   ├── apple-ae +│   │   │   │   │   ├── appleII +│   │   │   │   │   ├── appleIIc -> .././61/appleIIgs +│   │   │   │   │   ├── appleIIe -> .././61/appleIIgs +│   │   │   │   │   ├── appleIIgs +│   │   │   │   │   ├── apple-soroc +│   │   │   │   │   ├── apple-uterm +│   │   │   │   │   ├── apple-uterm-vb +│   │   │   │   │   ├── apple-videx +│   │   │   │   │   ├── apple-videx2 +│   │   │   │   │   ├── apple-videx3 +│   │   │   │   │   ├── apple-vm80 +│   │   │   │   │   ├── ap-vm80 -> .././61/apple-vm80 +│   │   │   │   │   ├── arm100 +│   │   │   │   │   ├── arm100-am -> .././61/arm100 +│   │   │   │   │   ├── arm100-w +│   │   │   │   │   ├── arm100-wam -> .././61/arm100-w +│   │   │   │   │   ├── at -> .././73/st52 +│   │   │   │   │   ├── at386 -> .././61/att6386 +│   │   │   │   │   ├── atari -> .././73/st52 +│   │   │   │   │   ├── atari-color -> .././73/st52-color +│   │   │   │   │   ├── atari-m -> .././73/st52 +│   │   │   │   │   ├── atari-old +│   │   │   │   │   ├── atari_st -> .././73/st52 +│   │   │   │   │   ├── atari_st-color -> .././73/st52-color +│   │   │   │   │   ├── atarist-m -> .././73/st52 +│   │   │   │   │   ├── at-color -> .././73/st52-color +│   │   │   │   │   ├── aterm +│   │   │   │   │   ├── at-m -> .././73/st52 +│   │   │   │   │   ├── att2300 +│   │   │   │   │   ├── att2350 +│   │   │   │   │   ├── att4410 +│   │   │   │   │   ├── att4410v1 -> .././61/att5410v1 +│   │   │   │   │   ├── att4410v1-w +│   │   │   │   │   ├── att4410-w -> .././61/att5410-w +│   │   │   │   │   ├── att4415 +│   │   │   │   │   ├── att4415+nl +│   │   │   │   │   ├── att4415-nl +│   │   │   │   │   ├── att4415-rv +│   │   │   │   │   ├── att4415-rv-nl +│   │   │   │   │   ├── att4415-w +│   │   │   │   │   ├── att4415-w-nl +│   │   │   │   │   ├── att4415-w-rv +│   │   │   │   │   ├── att4415-w-rv-n +│   │   │   │   │   ├── att4418 +│   │   │   │   │   ├── att4418-w +│   │   │   │   │   ├── att4420 +│   │   │   │   │   ├── att4424 +│   │   │   │   │   ├── att4424-1 +│   │   │   │   │   ├── att4424m +│   │   │   │   │   ├── att4425 -> .././61/att5425 +│   │   │   │   │   ├── att4425-nl -> .././61/att5425-nl +│   │   │   │   │   ├── att4425-w -> .././61/att5425-w +│   │   │   │   │   ├── att4426 +│   │   │   │   │   ├── att500 +│   │   │   │   │   ├── att505 +│   │   │   │   │   ├── att505-22 +│   │   │   │   │   ├── att505-24 +│   │   │   │   │   ├── att510a +│   │   │   │   │   ├── att510d +│   │   │   │   │   ├── att513 -> .././61/att500 +│   │   │   │   │   ├── att5310 +│   │   │   │   │   ├── att5320 -> .././61/att5310 +│   │   │   │   │   ├── att5410 -> .././61/att4410 +│   │   │   │   │   ├── att5410v1 +│   │   │   │   │   ├── att5410v1-w -> .././61/att4410v1-w +│   │   │   │   │   ├── att5410-w +│   │   │   │   │   ├── att5418 -> .././61/att4418 +│   │   │   │   │   ├── att5418-w -> .././61/att4418-w +│   │   │   │   │   ├── att5420 -> .././61/att4415 +│   │   │   │   │   ├── att5420_2 +│   │   │   │   │   ├── att5420_2-w +│   │   │   │   │   ├── att5420+nl -> .././61/att4415+nl +│   │   │   │   │   ├── att5420-nl -> .././61/att4415-nl +│   │   │   │   │   ├── att5420-rv -> .././61/att4415-rv +│   │   │   │   │   ├── att5420-rv-nl -> .././61/att4415-rv-nl +│   │   │   │   │   ├── att5420-w -> .././61/att4415-w +│   │   │   │   │   ├── att5420-w-nl -> .././61/att4415-w-nl +│   │   │   │   │   ├── att5420-w-rv -> .././61/att4415-w-rv +│   │   │   │   │   ├── att5420-w-rv-n -> .././61/att4415-w-rv-n +│   │   │   │   │   ├── att5425 +│   │   │   │   │   ├── att5425-nl +│   │   │   │   │   ├── att5425-w +│   │   │   │   │   ├── att5430 -> .././61/att505 +│   │   │   │   │   ├── att5620 +│   │   │   │   │   ├── att5620-1 +│   │   │   │   │   ├── att5620-24 +│   │   │   │   │   ├── att5620-34 +│   │   │   │   │   ├── att5620-s +│   │   │   │   │   ├── att605 +│   │   │   │   │   ├── att605-pc +│   │   │   │   │   ├── att605-w +│   │   │   │   │   ├── att610 +│   │   │   │   │   ├── att610-103k +│   │   │   │   │   ├── att610-103k-w +│   │   │   │   │   ├── att610+cvis +│   │   │   │   │   ├── att610+cvis0 +│   │   │   │   │   ├── att610-w +│   │   │   │   │   ├── att615 +│   │   │   │   │   ├── att615-103k +│   │   │   │   │   ├── att615-103k-w +│   │   │   │   │   ├── att615-w +│   │   │   │   │   ├── att620 +│   │   │   │   │   ├── att620-103k +│   │   │   │   │   ├── att620-103k-w +│   │   │   │   │   ├── att620-w +│   │   │   │   │   ├── att630 +│   │   │   │   │   ├── att630-24 +│   │   │   │   │   ├── att6386 +│   │   │   │   │   ├── att700 +│   │   │   │   │   ├── att730 +│   │   │   │   │   ├── att7300 +│   │   │   │   │   ├── att730-24 +│   │   │   │   │   ├── att730-41 +│   │   │   │   │   ├── att730r +│   │   │   │   │   ├── att730r-24 +│   │   │   │   │   ├── att730r-41 +│   │   │   │   │   ├── avatar +│   │   │   │   │   ├── avatar0 +│   │   │   │   │   ├── avatar0+ +│   │   │   │   │   ├── avatar1 -> .././61/avatar +│   │   │   │   │   ├── avt +│   │   │   │   │   ├── avt-ns +│   │   │   │   │   ├── avt-rv +│   │   │   │   │   ├── avt-rv-ns +│   │   │   │   │   ├── avt-rv-s -> .././61/avt-rv +│   │   │   │   │   ├── avt+s +│   │   │   │   │   ├── avt-s -> .././61/avt +│   │   │   │   │   ├── avt-w +│   │   │   │   │   ├── avt-w-ns +│   │   │   │   │   ├── avt-w-rv +│   │   │   │   │   ├── avt-w-rv-ns +│   │   │   │   │   ├── avt-w-rv-s -> .././61/avt-w-rv +│   │   │   │   │   ├── avt-w-s -> .././61/avt-w +│   │   │   │   │   ├── aws +│   │   │   │   │   └── awsc +│   │   │   │   ├── 62 +│   │   │   │   │   ├── b-128 -> .././63/commodore +│   │   │   │   │   ├── bantam +│   │   │   │   │   ├── basic4 -> .././6d/mai +│   │   │   │   │   ├── basis +│   │   │   │   │   ├── bct510a -> .././61/att510a +│   │   │   │   │   ├── bct510d -> .././61/att510d +│   │   │   │   │   ├── beacon +│   │   │   │   │   ├── bee -> .././62/beehive +│   │   │   │   │   ├── beehive +│   │   │   │   │   ├── beehive3 +│   │   │   │   │   ├── beehive4 +│   │   │   │   │   ├── beehiveIIIm -> .././62/beehive3 +│   │   │   │   │   ├── beterm +│   │   │   │   │   ├── bg1.25 +│   │   │   │   │   ├── bg1.25nv +│   │   │   │   │   ├── bg1.25rv +│   │   │   │   │   ├── bg2.0 +│   │   │   │   │   ├── bg2.0nv -> .././62/bitgraph +│   │   │   │   │   ├── bg2.0rv +│   │   │   │   │   ├── bg3.10 -> .././62/bg2.0 +│   │   │   │   │   ├── bg3.10nv -> .././62/bitgraph +│   │   │   │   │   ├── bg3.10rv -> .././62/bg2.0rv +│   │   │   │   │   ├── bh3m -> .././62/beehive3 +│   │   │   │   │   ├── bh4 -> .././62/beehive4 +│   │   │   │   │   ├── bitgraph +│   │   │   │   │   ├── blit +│   │   │   │   │   ├── bobcat +│   │   │   │   │   ├── bq300 +│   │   │   │   │   ├── bq300-8 +│   │   │   │   │   ├── bq300-8-pc +│   │   │   │   │   ├── bq300-8-pc-rv +│   │   │   │   │   ├── bq300-8-pc-w +│   │   │   │   │   ├── bq300-8-pc-w-rv +│   │   │   │   │   ├── bq300-8rv +│   │   │   │   │   ├── bq300-8w +│   │   │   │   │   ├── bq300-pc +│   │   │   │   │   ├── bq300-pc-rv +│   │   │   │   │   ├── bq300-pc-w +│   │   │   │   │   ├── bq300-pc-w-rv +│   │   │   │   │   ├── bq300-rv +│   │   │   │   │   ├── bq300-w +│   │   │   │   │   ├── bq300-w-8rv +│   │   │   │   │   ├── bq300-w-rv +│   │   │   │   │   ├── bracketed+paste +│   │   │   │   │   ├── bsdos-pc +│   │   │   │   │   ├── bsdos-pc-m +│   │   │   │   │   ├── bsdos-pc-mono -> .././62/bsdos-pc-m +│   │   │   │   │   ├── bsdos-pc-nobold +│   │   │   │   │   ├── bsdos-ppc +│   │   │   │   │   ├── bsdos-sparc +│   │   │   │   │   └── bterm +│   │   │   │   ├── 63 +│   │   │   │   │   ├── c100 +│   │   │   │   │   ├── c100-1p -> .././6f/oc100 +│   │   │   │   │   ├── c100-4p -> .././63/c100 +│   │   │   │   │   ├── c100-rv +│   │   │   │   │   ├── c100-rv-4p -> .././63/c100-rv +│   │   │   │   │   ├── c104 -> .././63/c100 +│   │   │   │   │   ├── c108 +│   │   │   │   │   ├── c108-4p +│   │   │   │   │   ├── c108-8p -> .././63/c108 +│   │   │   │   │   ├── c108-rv +│   │   │   │   │   ├── c108-rv-4p +│   │   │   │   │   ├── c108-rv-8p -> .././63/c108-rv +│   │   │   │   │   ├── c108-w +│   │   │   │   │   ├── c108-w-8p -> .././63/c108-w +│   │   │   │   │   ├── c300 -> .././63/contel300 +│   │   │   │   │   ├── c301 -> .././63/contel301 +│   │   │   │   │   ├── c321 -> .././63/contel301 +│   │   │   │   │   ├── ca22851 +│   │   │   │   │   ├── cad68-2 +│   │   │   │   │   ├── cad68-3 +│   │   │   │   │   ├── cbblit +│   │   │   │   │   ├── cbunix +│   │   │   │   │   ├── cci +│   │   │   │   │   ├── cci1 -> .././63/cci +│   │   │   │   │   ├── cdc456 +│   │   │   │   │   ├── cdc721 +│   │   │   │   │   ├── cdc721-esc +│   │   │   │   │   ├── cdc721ll +│   │   │   │   │   ├── cdc752 +│   │   │   │   │   ├── cdc756 +│   │   │   │   │   ├── cg7900 +│   │   │   │   │   ├── cgc2 -> .././63/cad68-2 +│   │   │   │   │   ├── cgc3 -> .././63/cad68-3 +│   │   │   │   │   ├── chromatics -> .././63/cg7900 +│   │   │   │   │   ├── ci8510 -> .././63/citoh +│   │   │   │   │   ├── cit101 +│   │   │   │   │   ├── cit101e +│   │   │   │   │   ├── cit101e-132 +│   │   │   │   │   ├── cit101e-n +│   │   │   │   │   ├── cit101e-n132 +│   │   │   │   │   ├── cit101e-rv +│   │   │   │   │   ├── cit500 +│   │   │   │   │   ├── cit-80 -> .././63/cit80 +│   │   │   │   │   ├── cit80 +│   │   │   │   │   ├── citc -> .././63/cit101 +│   │   │   │   │   ├── citoh +│   │   │   │   │   ├── citoh-6lpi +│   │   │   │   │   ├── citoh-8lpi +│   │   │   │   │   ├── citoh-comp +│   │   │   │   │   ├── citoh-elite +│   │   │   │   │   ├── citoh-pica +│   │   │   │   │   ├── citoh-prop +│   │   │   │   │   ├── citoh-ps -> .././63/citoh-prop +│   │   │   │   │   ├── coco3 +│   │   │   │   │   ├── coherent -> .././70/pc-coherent +│   │   │   │   │   ├── colorscan -> .././63/cs10 +│   │   │   │   │   ├── color_xterm +│   │   │   │   │   ├── commodore +│   │   │   │   │   ├── concept -> .././63/c100 +│   │   │   │   │   ├── concept100 -> .././63/c100 +│   │   │   │   │   ├── concept100-rv -> .././63/c100-rv +│   │   │   │   │   ├── concept108 -> .././63/c108 +│   │   │   │   │   ├── concept108-4p -> .././63/c108-4p +│   │   │   │   │   ├── concept108-8p -> .././63/c108 +│   │   │   │   │   ├── concept108rv4p -> .././63/c108-rv-4p +│   │   │   │   │   ├── concept108-w-8 -> .././63/c108-w +│   │   │   │   │   ├── concept108-w8p -> .././63/c108-w +│   │   │   │   │   ├── concept-avt -> .././61/avt +│   │   │   │   │   ├── cons25 +│   │   │   │   │   ├── cons25-debian +│   │   │   │   │   ├── cons25-iso8859 -> .././63/cons25l1 +│   │   │   │   │   ├── cons25-iso-m -> .././63/cons25l1-m +│   │   │   │   │   ├── cons25-koi8-r -> .././63/cons25r +│   │   │   │   │   ├── cons25-koi8r-m -> .././63/cons25r-m +│   │   │   │   │   ├── cons25l1 +│   │   │   │   │   ├── cons25l1-m +│   │   │   │   │   ├── cons25-m +│   │   │   │   │   ├── cons25r +│   │   │   │   │   ├── cons25r-m +│   │   │   │   │   ├── cons25w +│   │   │   │   │   ├── cons30 +│   │   │   │   │   ├── cons30-m +│   │   │   │   │   ├── cons43 +│   │   │   │   │   ├── cons43-m +│   │   │   │   │   ├── cons50 +│   │   │   │   │   ├── cons50-iso8859 -> .././63/cons50l1 +│   │   │   │   │   ├── cons50-iso-m -> .././63/cons50l1-m +│   │   │   │   │   ├── cons50-koi8r -> .././63/cons50r +│   │   │   │   │   ├── cons50-koi8r-m -> .././63/cons50r-m +│   │   │   │   │   ├── cons50l1 +│   │   │   │   │   ├── cons50l1-m +│   │   │   │   │   ├── cons50-m +│   │   │   │   │   ├── cons50r +│   │   │   │   │   ├── cons50r-m +│   │   │   │   │   ├── cons60 +│   │   │   │   │   ├── cons60-iso -> .././63/cons60l1 +│   │   │   │   │   ├── cons60-iso-m -> .././63/cons60l1-m +│   │   │   │   │   ├── cons60-koi8r -> .././63/cons60r +│   │   │   │   │   ├── cons60-koi8r-m -> .././63/cons60r-m +│   │   │   │   │   ├── cons60l1 +│   │   │   │   │   ├── cons60l1-m +│   │   │   │   │   ├── cons60-m +│   │   │   │   │   ├── cons60r +│   │   │   │   │   ├── cons60r-m +│   │   │   │   │   ├── contel300 +│   │   │   │   │   ├── contel301 +│   │   │   │   │   ├── contel320 -> .././63/contel300 +│   │   │   │   │   ├── contel321 -> .././63/contel301 +│   │   │   │   │   ├── contour +│   │   │   │   │   ├── contour-direct +│   │   │   │   │   ├── contour-latest -> .././63/contour +│   │   │   │   │   ├── cops -> .././63/cops10 +│   │   │   │   │   ├── cops-10 -> .././63/cops10 +│   │   │   │   │   ├── cops10 +│   │   │   │   │   ├── crt +│   │   │   │   │   ├── crt-vt220 -> .././63/crt +│   │   │   │   │   ├── cs10 +│   │   │   │   │   ├── cs10-w +│   │   │   │   │   ├── ct82 -> .././73/swtp +│   │   │   │   │   ├── ct8500 +│   │   │   │   │   ├── ctrm +│   │   │   │   │   ├── cx -> .././63/color_xterm +│   │   │   │   │   ├── cx100 -> .././63/color_xterm +│   │   │   │   │   ├── cyb110 +│   │   │   │   │   ├── cyb83 +│   │   │   │   │   ├── cygwin +│   │   │   │   │   ├── cygwinB19 +│   │   │   │   │   └── cygwinDBG +│   │   │   │   ├── 64 +│   │   │   │   │   ├── d132 +│   │   │   │   │   ├── d2 -> .././64/dg6053 +│   │   │   │   │   ├── d200 +│   │   │   │   │   ├── d200-dg -> .././64/d200 +│   │   │   │   │   ├── d210 +│   │   │   │   │   ├── d210-dg +│   │   │   │   │   ├── d211 +│   │   │   │   │   ├── d211-7b +│   │   │   │   │   ├── d211-dg +│   │   │   │   │   ├── d214 -> .././64/d210 +│   │   │   │   │   ├── d214-dg -> .././64/d210-dg +│   │   │   │   │   ├── d215 -> .././64/d211 +│   │   │   │   │   ├── d215-7b -> .././64/d211-7b +│   │   │   │   │   ├── d215-dg -> .././64/d211-dg +│   │   │   │   │   ├── d216+ -> .././64/d216-unix +│   │   │   │   │   ├── d216+25 -> .././64/d216-unix-25 +│   │   │   │   │   ├── d216+dg -> .././64/d216-dg +│   │   │   │   │   ├── d216-dg +│   │   │   │   │   ├── d216e+ -> .././64/d216-unix +│   │   │   │   │   ├── d216e+dg -> .././64/d216-dg +│   │   │   │   │   ├── d216e-dg -> .././64/d216-dg +│   │   │   │   │   ├── d216e-unix -> .././64/d216-unix +│   │   │   │   │   ├── d216-unix +│   │   │   │   │   ├── d216-unix-25 +│   │   │   │   │   ├── d217-dg -> .././64/d216-dg +│   │   │   │   │   ├── d217-unix +│   │   │   │   │   ├── d217-unix-25 +│   │   │   │   │   ├── d220 +│   │   │   │   │   ├── d220-7b +│   │   │   │   │   ├── d220-dg +│   │   │   │   │   ├── d230 -> .././64/d230c +│   │   │   │   │   ├── d230c +│   │   │   │   │   ├── d230c-dg +│   │   │   │   │   ├── d230-dg -> .././64/d230c-dg +│   │   │   │   │   ├── d2-dg -> .././64/dg6053 +│   │   │   │   │   ├── d400 +│   │   │   │   │   ├── d400-dg -> .././64/d400 +│   │   │   │   │   ├── d410 +│   │   │   │   │   ├── d410-7b +│   │   │   │   │   ├── d410-7b-w +│   │   │   │   │   ├── d410-dg +│   │   │   │   │   ├── d410-w +│   │   │   │   │   ├── d411 -> .././64/d410 +│   │   │   │   │   ├── d411-7b -> .././64/d410-7b +│   │   │   │   │   ├── d411-7b-w -> .././64/d410-7b-w +│   │   │   │   │   ├── d411-dg -> .././64/d410-dg +│   │   │   │   │   ├── d411-w -> .././64/d410-w +│   │   │   │   │   ├── d412+ -> .././64/d412-unix +│   │   │   │   │   ├── d412+25 -> .././64/d412-unix-25 +│   │   │   │   │   ├── d412+dg -> .././64/d412-dg +│   │   │   │   │   ├── d412-dg +│   │   │   │   │   ├── d412+s -> .././64/d412-unix-s +│   │   │   │   │   ├── d412+sr -> .././64/d412-unix-sr +│   │   │   │   │   ├── d412-unix +│   │   │   │   │   ├── d412-unix-25 +│   │   │   │   │   ├── d412-unix-s +│   │   │   │   │   ├── d412-unix-sr +│   │   │   │   │   ├── d412-unix-w +│   │   │   │   │   ├── d412+w -> .././64/d412-unix-w +│   │   │   │   │   ├── d413-dg -> .././64/d412-dg +│   │   │   │   │   ├── d413-unix +│   │   │   │   │   ├── d413-unix-25 +│   │   │   │   │   ├── d413-unix-s +│   │   │   │   │   ├── d413-unix-sr +│   │   │   │   │   ├── d413-unix-w +│   │   │   │   │   ├── d414-unix +│   │   │   │   │   ├── d414-unix-25 +│   │   │   │   │   ├── d414-unix-s +│   │   │   │   │   ├── d414-unix-sr +│   │   │   │   │   ├── d414-unix-w +│   │   │   │   │   ├── d430c-dg +│   │   │   │   │   ├── d430c-dg-ccc +│   │   │   │   │   ├── d430c-unix +│   │   │   │   │   ├── d430c-unix-25 +│   │   │   │   │   ├── d430c-unix-25-ccc +│   │   │   │   │   ├── d430c-unix-ccc +│   │   │   │   │   ├── d430c-unix-s +│   │   │   │   │   ├── d430c-unix-s-ccc +│   │   │   │   │   ├── d430c-unix-sr +│   │   │   │   │   ├── d430c-unix-sr-ccc +│   │   │   │   │   ├── d430c-unix-w +│   │   │   │   │   ├── d430c-unix-w-ccc +│   │   │   │   │   ├── d430-dg -> .././64/d430c-dg +│   │   │   │   │   ├── d430-dg-ccc -> .././64/d430c-dg-ccc +│   │   │   │   │   ├── d430-unix -> .././64/d430c-unix +│   │   │   │   │   ├── d430-unix-25 -> .././64/d430c-unix-25 +│   │   │   │   │   ├── d430-unix-25-ccc -> .././64/d430c-unix-25-ccc +│   │   │   │   │   ├── d430-unix-ccc -> .././64/d430c-unix-ccc +│   │   │   │   │   ├── d430-unix-s -> .././64/d430c-unix-s +│   │   │   │   │   ├── d430-unix-s-ccc -> .././64/d430c-unix-s-ccc +│   │   │   │   │   ├── d430-unix-sr -> .././64/d430c-unix-sr +│   │   │   │   │   ├── d430-unix-sr-ccc -> .././64/d430c-unix-sr-ccc +│   │   │   │   │   ├── d430-unix-w -> .././64/d430c-unix-w +│   │   │   │   │   ├── d430-unix-w-ccc -> .././64/d430c-unix-w-ccc +│   │   │   │   │   ├── d450 -> .././64/d400 +│   │   │   │   │   ├── d450-dg -> .././64/d400 +│   │   │   │   │   ├── d460 -> .././64/d410 +│   │   │   │   │   ├── d460-7b -> .././64/d410-7b +│   │   │   │   │   ├── d460-7b-w -> .././64/d410-7b-w +│   │   │   │   │   ├── d460-dg -> .././64/d410-dg +│   │   │   │   │   ├── d460-w -> .././64/d410-w +│   │   │   │   │   ├── d461 -> .././64/d410 +│   │   │   │   │   ├── d461-7b -> .././64/d410-7b +│   │   │   │   │   ├── d461-7b-w -> .././64/d410-7b-w +│   │   │   │   │   ├── d461-dg -> .././64/d410-dg +│   │   │   │   │   ├── d461-w -> .././64/d410-w +│   │   │   │   │   ├── d462+ -> .././64/d412-unix +│   │   │   │   │   ├── d462+25 -> .././64/d412-unix-25 +│   │   │   │   │   ├── d462+dg -> .././64/d412-dg +│   │   │   │   │   ├── d462-dg -> .././64/d412-dg +│   │   │   │   │   ├── d462e-dg -> .././64/d412-dg +│   │   │   │   │   ├── d462+s -> .././64/d412-unix-s +│   │   │   │   │   ├── d462+sr -> .././64/d412-unix-sr +│   │   │   │   │   ├── d462-unix -> .././64/d412-unix +│   │   │   │   │   ├── d462-unix-25 -> .././64/d412-unix-25 +│   │   │   │   │   ├── d462-unix-s -> .././64/d412-unix-s +│   │   │   │   │   ├── d462-unix-sr -> .././64/d412-unix-sr +│   │   │   │   │   ├── d462-unix-w -> .././64/d412-unix-w +│   │   │   │   │   ├── d462+w -> .././64/d412-unix-w +│   │   │   │   │   ├── d463-dg -> .././64/d412-dg +│   │   │   │   │   ├── d463-unix -> .././64/d413-unix +│   │   │   │   │   ├── d463-unix-25 -> .././64/d413-unix-25 +│   │   │   │   │   ├── d463-unix-s -> .././64/d413-unix-s +│   │   │   │   │   ├── d463-unix-sr -> .././64/d413-unix-sr +│   │   │   │   │   ├── d463-unix-w -> .././64/d413-unix-w +│   │   │   │   │   ├── d464-unix -> .././64/d414-unix +│   │   │   │   │   ├── d464-unix-25 -> .././64/d414-unix-25 +│   │   │   │   │   ├── d464-unix-s -> .././64/d414-unix-s +│   │   │   │   │   ├── d464-unix-sr -> .././64/d414-unix-sr +│   │   │   │   │   ├── d464-unix-w -> .././64/d414-unix-w +│   │   │   │   │   ├── d470 -> .././64/d470c +│   │   │   │   │   ├── d470-7b -> .././64/d470c-7b +│   │   │   │   │   ├── d470c +│   │   │   │   │   ├── d470c-7b +│   │   │   │   │   ├── d470c-dg +│   │   │   │   │   ├── d470-dg -> .././64/d470c-dg +│   │   │   │   │   ├── d555 +│   │   │   │   │   ├── d555-7b +│   │   │   │   │   ├── d555-7b-w +│   │   │   │   │   ├── d555-dg +│   │   │   │   │   ├── d555-w +│   │   │   │   │   ├── d577 +│   │   │   │   │   ├── d577-7b +│   │   │   │   │   ├── d577-7b-w +│   │   │   │   │   ├── d577-dg +│   │   │   │   │   ├── d577-w +│   │   │   │   │   ├── d578 +│   │   │   │   │   ├── d578-7b +│   │   │   │   │   ├── d578-dg -> .././64/d577-dg +│   │   │   │   │   ├── d80 -> .././61/ampex80 +│   │   │   │   │   ├── d800 +│   │   │   │   │   ├── darwin -> .././78/xnuppc +│   │   │   │   │   ├── darwin-100x37 -> .././78/xnuppc-100x37 +│   │   │   │   │   ├── darwin-100x37-m -> .././78/xnuppc-100x37-m +│   │   │   │   │   ├── darwin-112x37 -> .././78/xnuppc-112x37 +│   │   │   │   │   ├── darwin-112x37-m -> .././78/xnuppc-112x37-m +│   │   │   │   │   ├── darwin-128x40 -> .././78/xnuppc-128x40 +│   │   │   │   │   ├── darwin-128x40-m -> .././78/xnuppc-128x40-m +│   │   │   │   │   ├── darwin-128x48 -> .././78/xnuppc-128x48 +│   │   │   │   │   ├── darwin-128x48-m -> .././78/xnuppc-128x48-m +│   │   │   │   │   ├── darwin-144x48 -> .././78/xnuppc-144x48 +│   │   │   │   │   ├── darwin-144x48-m -> .././78/xnuppc-144x48-m +│   │   │   │   │   ├── darwin-160x64 -> .././78/xnuppc-160x64 +│   │   │   │   │   ├── darwin-160x64-m -> .././78/xnuppc-160x64-m +│   │   │   │   │   ├── darwin-200x64 -> .././78/xnuppc-200x64 +│   │   │   │   │   ├── darwin-200x64-m -> .././78/xnuppc-200x64-m +│   │   │   │   │   ├── darwin-200x75 -> .././78/xnuppc-200x75 +│   │   │   │   │   ├── darwin-200x75-m -> .././78/xnuppc-200x75-m +│   │   │   │   │   ├── darwin-256x96 -> .././78/xnuppc-256x96 +│   │   │   │   │   ├── darwin-256x96-m -> .././78/xnuppc-256x96-m +│   │   │   │   │   ├── darwin-80x25 -> .././78/xnuppc-80x25 +│   │   │   │   │   ├── darwin-80x25-m -> .././78/xnuppc-80x25-m +│   │   │   │   │   ├── darwin-80x30 -> .././78/xnuppc-80x30 +│   │   │   │   │   ├── darwin-80x30-m -> .././78/xnuppc-80x30-m +│   │   │   │   │   ├── darwin-90x30 -> .././78/xnuppc-90x30 +│   │   │   │   │   ├── darwin-90x30-m -> .././78/xnuppc-90x30-m +│   │   │   │   │   ├── darwin-b -> .././78/xnuppc-b +│   │   │   │   │   ├── darwin-f -> .././78/xnuppc-f +│   │   │   │   │   ├── darwin-f2 -> .././78/xnuppc-f2 +│   │   │   │   │   ├── darwin-m -> .././78/xnuppc-m +│   │   │   │   │   ├── darwin-m-b -> .././78/xnuppc-m-b +│   │   │   │   │   ├── darwin-m-f -> .././78/xnuppc-m-f +│   │   │   │   │   ├── darwin-m-f2 -> .././78/xnuppc-m-f2 +│   │   │   │   │   ├── datagraphix -> .././64/d132 +│   │   │   │   │   ├── datamedia2500 -> .././64/dm2500 +│   │   │   │   │   ├── datapoint -> .././64/dp3360 +│   │   │   │   │   ├── dataspeed40 -> .././74/tty40 +│   │   │   │   │   ├── dd5000 -> .././64/delta +│   │   │   │   │   ├── ddr +│   │   │   │   │   ├── ddr3180 -> .././64/ddr +│   │   │   │   │   ├── decansi +│   │   │   │   │   ├── decid+cpr +│   │   │   │   │   ├── dec+pp +│   │   │   │   │   ├── decpro -> .././70/pro350 +│   │   │   │   │   ├── dec+sl +│   │   │   │   │   ├── dec-vt100 +│   │   │   │   │   ├── dec-vt220 +│   │   │   │   │   ├── dec-vt330 -> .././76/vt340 +│   │   │   │   │   ├── dec-vt340 -> .././76/vt340 +│   │   │   │   │   ├── dec-vt400 -> .././76/vt400 +│   │   │   │   │   ├── decwriter -> .././64/dw2 +│   │   │   │   │   ├── delta +│   │   │   │   │   ├── dg100 -> .././64/dg6053-old +│   │   │   │   │   ├── dg200 +│   │   │   │   │   ├── dg210 +│   │   │   │   │   ├── dg211 +│   │   │   │   │   ├── dg450 +│   │   │   │   │   ├── dg460-ansi +│   │   │   │   │   ├── dg6053 +│   │   │   │   │   ├── dg6053-old +│   │   │   │   │   ├── dg605x -> .././64/dg6053 +│   │   │   │   │   ├── dg6134 -> .././64/dg450 +│   │   │   │   │   ├── dg-ansi -> .././64/dg210 +│   │   │   │   │   ├── dg+ccc +│   │   │   │   │   ├── dg+color +│   │   │   │   │   ├── dg+color8 +│   │   │   │   │   ├── dg+fixed +│   │   │   │   │   ├── dg-generic +│   │   │   │   │   ├── dgkeys+11 +│   │   │   │   │   ├── dgkeys+15 +│   │   │   │   │   ├── dgkeys+7b +│   │   │   │   │   ├── dgkeys+8b +│   │   │   │   │   ├── dgmode+color +│   │   │   │   │   ├── dgmode+color8 +│   │   │   │   │   ├── dgunix+ccc +│   │   │   │   │   ├── dgunix+fixed +│   │   │   │   │   ├── diablo -> .././64/diablo1640 +│   │   │   │   │   ├── diablo1620 +│   │   │   │   │   ├── diablo1620-m8 +│   │   │   │   │   ├── diablo1640 +│   │   │   │   │   ├── diablo1640-lm +│   │   │   │   │   ├── diablo1640-m8 -> .././64/diablo1620-m8 +│   │   │   │   │   ├── diablo1720 -> .././64/diablo1620 +│   │   │   │   │   ├── diablo1730 -> .././64/diablo1640 +│   │   │   │   │   ├── diablo1740 -> .././64/diablo1640 +│   │   │   │   │   ├── diablo1740-lm +│   │   │   │   │   ├── diablo450 -> .././64/diablo1620 +│   │   │   │   │   ├── diablo630 -> .././64/diablo1640 +│   │   │   │   │   ├── diablo-lm -> .././64/diablo1640-lm +│   │   │   │   │   ├── dialogue -> .././61/ampex80 +│   │   │   │   │   ├── dialogue80 -> .././61/ampex80 +│   │   │   │   │   ├── digilog +│   │   │   │   │   ├── djgpp +│   │   │   │   │   ├── djgpp203 +│   │   │   │   │   ├── djgpp204 +│   │   │   │   │   ├── dku7003 +│   │   │   │   │   ├── dku7003-dumb +│   │   │   │   │   ├── dku7102 -> .././74/tws-generic +│   │   │   │   │   ├── dku7102-old +│   │   │   │   │   ├── dku7102-sna -> .././74/tws2102-sna +│   │   │   │   │   ├── dku7103-sna -> .././74/tws2103-sna +│   │   │   │   │   ├── dku7202 +│   │   │   │   │   ├── dm1520 +│   │   │   │   │   ├── dm1521 -> .././64/dm1520 +│   │   │   │   │   ├── dm2500 +│   │   │   │   │   ├── dm3025 +│   │   │   │   │   ├── dm3045 +│   │   │   │   │   ├── dm80 +│   │   │   │   │   ├── dm80w +│   │   │   │   │   ├── dmchat +│   │   │   │   │   ├── dmd -> .././61/att5620 +│   │   │   │   │   ├── dmd1 -> .././61/att5620-1 +│   │   │   │   │   ├── dmd-24 -> .././61/att5620-24 +│   │   │   │   │   ├── dmd-34 -> .././61/att5620-34 +│   │   │   │   │   ├── dmdt80 -> .././64/dm80 +│   │   │   │   │   ├── dmdt80w -> .././64/dm80w +│   │   │   │   │   ├── dmterm +│   │   │   │   │   ├── domterm +│   │   │   │   │   ├── dp3360 +│   │   │   │   │   ├── dp8242 +│   │   │   │   │   ├── ds40 -> .././74/tty40 +│   │   │   │   │   ├── ds40-2 -> .././74/tty40 +│   │   │   │   │   ├── dt-100 -> .././64/dt100 +│   │   │   │   │   ├── dt100 +│   │   │   │   │   ├── dt-100w -> .././64/dt100w +│   │   │   │   │   ├── dt100w +│   │   │   │   │   ├── dt110 +│   │   │   │   │   ├── dt80 -> .././64/dm80 +│   │   │   │   │   ├── dt80-sas +│   │   │   │   │   ├── dt80w -> .././64/dm80w +│   │   │   │   │   ├── dtc300s +│   │   │   │   │   ├── dtc382 +│   │   │   │   │   ├── dtterm +│   │   │   │   │   ├── dumb +│   │   │   │   │   ├── dumb-emacs-ansi +│   │   │   │   │   ├── dvtm +│   │   │   │   │   ├── dvtm-256color +│   │   │   │   │   ├── dw -> .././64/dw2 +│   │   │   │   │   ├── dw1 +│   │   │   │   │   ├── dw2 +│   │   │   │   │   ├── dw3 +│   │   │   │   │   ├── dw4 +│   │   │   │   │   ├── dwk +│   │   │   │   │   └── dwk-vt -> .././64/dwk +│   │   │   │   ├── 65 +│   │   │   │   │   ├── ecma+color +│   │   │   │   │   ├── ecma+index +│   │   │   │   │   ├── ecma+italics +│   │   │   │   │   ├── ecma+sgr +│   │   │   │   │   ├── ecma+standout +│   │   │   │   │   ├── ecma+strikeout +│   │   │   │   │   ├── ecma+underline +│   │   │   │   │   ├── elks +│   │   │   │   │   ├── elks-ansi +│   │   │   │   │   ├── elks-glasstty +│   │   │   │   │   ├── elks-vt52 +│   │   │   │   │   ├── emots -> .././67/gs6300 +│   │   │   │   │   ├── emu +│   │   │   │   │   ├── emu-220 +│   │   │   │   │   ├── emx-base +│   │   │   │   │   ├── env230 +│   │   │   │   │   ├── envision230 -> .././65/env230 +│   │   │   │   │   ├── ep40 +│   │   │   │   │   ├── ep4000 -> .././65/ep40 +│   │   │   │   │   ├── ep4080 -> .././65/ep48 +│   │   │   │   │   ├── ep48 +│   │   │   │   │   ├── ergo4000 +│   │   │   │   │   ├── esprit +│   │   │   │   │   ├── esprit-am +│   │   │   │   │   ├── eterm +│   │   │   │   │   ├── eterm-color +│   │   │   │   │   ├── ex155 +│   │   │   │   │   ├── excel62 +│   │   │   │   │   ├── excel62-rv +│   │   │   │   │   ├── excel62-w +│   │   │   │   │   ├── excel64 -> .././65/excel62 +│   │   │   │   │   ├── excel64-rv -> .././65/excel62-rv +│   │   │   │   │   ├── excel64-w -> .././65/excel62-w +│   │   │   │   │   └── exec80 -> .././68/hazel +│   │   │   │   ├── 66 +│   │   │   │   │   ├── f100 +│   │   │   │   │   ├── f100-rv +│   │   │   │   │   ├── f110 +│   │   │   │   │   ├── f110-14 +│   │   │   │   │   ├── f110-14w +│   │   │   │   │   ├── f110-w +│   │   │   │   │   ├── f1720 +│   │   │   │   │   ├── f1720a -> .././66/f1720 +│   │   │   │   │   ├── f200 +│   │   │   │   │   ├── f200vi +│   │   │   │   │   ├── f200vi-w +│   │   │   │   │   ├── f200-w +│   │   │   │   │   ├── falco +│   │   │   │   │   ├── falco-p +│   │   │   │   │   ├── fbterm +│   │   │   │   │   ├── fenix -> .././70/pt100 +│   │   │   │   │   ├── fenixw -> .././70/pt100w +│   │   │   │   │   ├── fixterm -> .././63/cbblit +│   │   │   │   │   ├── foot +│   │   │   │   │   ├── foot+base +│   │   │   │   │   ├── foot-direct +│   │   │   │   │   ├── fortune -> .././66/fos +│   │   │   │   │   ├── fos +│   │   │   │   │   ├── fox +│   │   │   │   │   ├── freedom -> .././66/f100 +│   │   │   │   │   ├── freedom100 -> .././66/f100 +│   │   │   │   │   ├── freedom110 -> .././66/f110 +│   │   │   │   │   ├── freedom200 -> .././66/f200 +│   │   │   │   │   └── freedom-rv -> .././66/f100-rv +│   │   │   │   ├── 67 +│   │   │   │   │   ├── gator +│   │   │   │   │   ├── gator-52 +│   │   │   │   │   ├── gator-52t +│   │   │   │   │   ├── gator-t +│   │   │   │   │   ├── ghostty +│   │   │   │   │   ├── gigi +│   │   │   │   │   ├── glasstty +│   │   │   │   │   ├── gnome +│   │   │   │   │   ├── gnome-2007 +│   │   │   │   │   ├── gnome-2008 +│   │   │   │   │   ├── gnome-2012 +│   │   │   │   │   ├── gnome-256color +│   │   │   │   │   ├── gnome-fc5 +│   │   │   │   │   ├── gnome+pcfkeys +│   │   │   │   │   ├── gnome-rh62 +│   │   │   │   │   ├── gnome-rh72 +│   │   │   │   │   ├── gnome-rh80 +│   │   │   │   │   ├── gnome-rh90 +│   │   │   │   │   ├── go140 +│   │   │   │   │   ├── go140w +│   │   │   │   │   ├── go-225 -> .././67/go225 +│   │   │   │   │   ├── go225 +│   │   │   │   │   ├── graphos +│   │   │   │   │   ├── graphos-30 +│   │   │   │   │   ├── gs5430 -> .././61/att505 +│   │   │   │   │   ├── gs5430-22 -> .././61/att505-22 +│   │   │   │   │   ├── gs5430-24 -> .././61/att505-24 +│   │   │   │   │   ├── gs6300 +│   │   │   │   │   ├── gsi +│   │   │   │   │   ├── gt100 -> .././69/i100 +│   │   │   │   │   ├── gt100a -> .././69/i100 +│   │   │   │   │   ├── gt40 +│   │   │   │   │   ├── gt42 +│   │   │   │   │   ├── guru +│   │   │   │   │   ├── guru-24 +│   │   │   │   │   ├── guru-33 -> .././67/guru +│   │   │   │   │   ├── guru-33-rv -> .././67/guru-rv +│   │   │   │   │   ├── guru-33-s -> .././67/guru-s +│   │   │   │   │   ├── guru-44 +│   │   │   │   │   ├── guru-44-s +│   │   │   │   │   ├── guru-76 +│   │   │   │   │   ├── guru-76-lp +│   │   │   │   │   ├── guru-76-s +│   │   │   │   │   ├── guru-76-w +│   │   │   │   │   ├── guru-76-wm +│   │   │   │   │   ├── guru-76-w-s +│   │   │   │   │   ├── guru-lp -> .././67/guru-76-lp +│   │   │   │   │   ├── guru-nctxt +│   │   │   │   │   ├── guru+rv +│   │   │   │   │   ├── guru-rv +│   │   │   │   │   ├── guru+s +│   │   │   │   │   ├── guru-s +│   │   │   │   │   └── guru+unk -> .././67/guru +│   │   │   │   ├── 68 +│   │   │   │   │   ├── h-100 -> .././7a/z100 +│   │   │   │   │   ├── h100 -> .././7a/z100 +│   │   │   │   │   ├── h-100bw -> .././7a/z100bw +│   │   │   │   │   ├── h100bw -> .././7a/z100bw +│   │   │   │   │   ├── h19 +│   │   │   │   │   ├── h19-a +│   │   │   │   │   ├── h19a -> .././68/h19-a +│   │   │   │   │   ├── h19-b -> .././68/h19 +│   │   │   │   │   ├── h19-bs +│   │   │   │   │   ├── h19-g +│   │   │   │   │   ├── h19g -> .././68/h19-g +│   │   │   │   │   ├── h19k +│   │   │   │   │   ├── h19kermit -> .././68/h19k +│   │   │   │   │   ├── h19-smul -> .././68/h19-us +│   │   │   │   │   ├── h19-u +│   │   │   │   │   ├── h19-us +│   │   │   │   │   ├── h19us -> .././68/h19-us +│   │   │   │   │   ├── h29a-kc-bc -> .././7a/z29a +│   │   │   │   │   ├── h29a-kc-uc -> .././7a/z29a-kc-uc +│   │   │   │   │   ├── h29a-nkc-bc -> .././7a/z29a-nkc-bc +│   │   │   │   │   ├── h29a-nkc-uc -> .././7a/z29a-nkc-uc +│   │   │   │   │   ├── h80 -> .././68/hazel +│   │   │   │   │   ├── ha8675 +│   │   │   │   │   ├── ha8686 +│   │   │   │   │   ├── hazel +│   │   │   │   │   ├── hds200 +│   │   │   │   │   ├── he80 -> .././68/hazel +│   │   │   │   │   ├── heath -> .././68/h19 +│   │   │   │   │   ├── heath-19 -> .././68/h19 +│   │   │   │   │   ├── heath-ansi -> .././68/h19-a +│   │   │   │   │   ├── heathkit -> .././68/h19 +│   │   │   │   │   ├── heathkit-a -> .././68/h19-a +│   │   │   │   │   ├── hft -> .././69/ibm5081 +│   │   │   │   │   ├── hft-c +│   │   │   │   │   ├── hft-c-old +│   │   │   │   │   ├── hft-old +│   │   │   │   │   ├── hirez100 +│   │   │   │   │   ├── hirez100-w +│   │   │   │   │   ├── hmod1 +│   │   │   │   │   ├── hp -> .././68/hpgeneric +│   │   │   │   │   ├── hp110 +│   │   │   │   │   ├── hp150 +│   │   │   │   │   ├── hp2 +│   │   │   │   │   ├── hp236 +│   │   │   │   │   ├── hp2382 -> .././68/hp2382a +│   │   │   │   │   ├── hp2382a +│   │   │   │   │   ├── hp2392 +│   │   │   │   │   ├── hp2397 -> .././68/hp2397a +│   │   │   │   │   ├── hp2397a +│   │   │   │   │   ├── hp2621 +│   │   │   │   │   ├── hp2621-48 +│   │   │   │   │   ├── hp2621-a +│   │   │   │   │   ├── hp2621a -> .././68/hp2621 +│   │   │   │   │   ├── hp2621A -> .././68/hp2621 +│   │   │   │   │   ├── hp2621a-a -> .././68/hp2621-a +│   │   │   │   │   ├── hp2621b +│   │   │   │   │   ├── hp2621-ba +│   │   │   │   │   ├── hp2621b-kx +│   │   │   │   │   ├── hp2621b-kx-p +│   │   │   │   │   ├── hp2621b-p +│   │   │   │   │   ├── hp2621-fl +│   │   │   │   │   ├── hp2621-k45 +│   │   │   │   │   ├── hp2621k45 -> .././68/hp2621-k45 +│   │   │   │   │   ├── hp2621-nl +│   │   │   │   │   ├── hp2621-nt +│   │   │   │   │   ├── hp2621p +│   │   │   │   │   ├── hp2621p-a +│   │   │   │   │   ├── hp2621-wl -> .././68/hp2621 +│   │   │   │   │   ├── hp2622 +│   │   │   │   │   ├── hp2622a -> .././68/hp2622 +│   │   │   │   │   ├── hp2623 +│   │   │   │   │   ├── hp2623a -> .././68/hp2623 +│   │   │   │   │   ├── hp2624 +│   │   │   │   │   ├── hp2624-10p +│   │   │   │   │   ├── hp2624a -> .././68/hp2624 +│   │   │   │   │   ├── hp2624a-10p -> .././68/hp2624-10p +│   │   │   │   │   ├── hp2624b -> .././68/hp2624 +│   │   │   │   │   ├── hp2624b-10p -> .././68/hp2624-10p +│   │   │   │   │   ├── hp2624b-10p-p +│   │   │   │   │   ├── hp2624b-4p -> .././68/hp2624 +│   │   │   │   │   ├── hp2624b-4p-p -> .././68/hp2624b-p +│   │   │   │   │   ├── hp2624b-p +│   │   │   │   │   ├── hp2626 +│   │   │   │   │   ├── hp2626-12 +│   │   │   │   │   ├── hp2626-12-s +│   │   │   │   │   ├── hp2626-12x40 +│   │   │   │   │   ├── hp2626a -> .././68/hp2626 +│   │   │   │   │   ├── hp2626-ns +│   │   │   │   │   ├── hp2626p -> .././68/hp2626 +│   │   │   │   │   ├── hp2626-s +│   │   │   │   │   ├── hp2626-x40 +│   │   │   │   │   ├── hp2627a +│   │   │   │   │   ├── hp2627a-rev +│   │   │   │   │   ├── hp2627c +│   │   │   │   │   ├── hp262x +│   │   │   │   │   ├── hp2640a +│   │   │   │   │   ├── hp2640b +│   │   │   │   │   ├── hp2641a +│   │   │   │   │   ├── hp2644a -> .././68/hp2640b +│   │   │   │   │   ├── hp2645 +│   │   │   │   │   ├── hp2645a -> .././68/hp2641a +│   │   │   │   │   ├── hp2647a -> .././68/hp2641a +│   │   │   │   │   ├── hp2648 +│   │   │   │   │   ├── hp2648a -> .././68/hp2648 +│   │   │   │   │   ├── hp300h +│   │   │   │   │   ├── hp45 -> .././68/hp2645 +│   │   │   │   │   ├── hp700 -> .././68/hpansi +│   │   │   │   │   ├── hp70092 +│   │   │   │   │   ├── hp70092a -> .././68/hp70092 +│   │   │   │   │   ├── hp70092A -> .././68/hp70092 +│   │   │   │   │   ├── hp700-wy +│   │   │   │   │   ├── hp9837 +│   │   │   │   │   ├── hp9845 +│   │   │   │   │   ├── hp98550 +│   │   │   │   │   ├── hp98550a -> .././68/hp98550 +│   │   │   │   │   ├── hp98550a-color -> .././68/hp98550-color +│   │   │   │   │   ├── hp98550-color +│   │   │   │   │   ├── hp98720 -> .././68/hp9837 +│   │   │   │   │   ├── hp98721 -> .././68/hp9837 +│   │   │   │   │   ├── hpansi +│   │   │   │   │   ├── hp+arrows +│   │   │   │   │   ├── hp+color +│   │   │   │   │   ├── hpex +│   │   │   │   │   ├── hpex2 -> .././68/hp2 +│   │   │   │   │   ├── hpgeneric +│   │   │   │   │   ├── hp+labels +│   │   │   │   │   ├── hp+pfk+arrows +│   │   │   │   │   ├── hp+pfk+cr +│   │   │   │   │   ├── hp+pfk-cr +│   │   │   │   │   ├── hp+printer +│   │   │   │   │   ├── hpsub +│   │   │   │   │   ├── hpterm +│   │   │   │   │   ├── hpterm-color +│   │   │   │   │   ├── hpterm-color2 +│   │   │   │   │   ├── hterm +│   │   │   │   │   ├── hterm-256color +│   │   │   │   │   ├── htx11 -> .././7a/ztx +│   │   │   │   │   ├── hurd +│   │   │   │   │   ├── hz1000 +│   │   │   │   │   ├── hz1420 +│   │   │   │   │   ├── hz1500 +│   │   │   │   │   ├── hz1510 +│   │   │   │   │   ├── hz1520 +│   │   │   │   │   ├── hz1520-noesc +│   │   │   │   │   ├── hz1552 +│   │   │   │   │   ├── hz1552-rv +│   │   │   │   │   └── hz2000 +│   │   │   │   ├── 69 +│   │   │   │   │   ├── i100 +│   │   │   │   │   ├── i3101 -> .././69/ibm3101 +│   │   │   │   │   ├── i3164 -> .././69/ibm3164 +│   │   │   │   │   ├── i400 +│   │   │   │   │   ├── ibcs2 +│   │   │   │   │   ├── ibm+16color +│   │   │   │   │   ├── ibm3101 +│   │   │   │   │   ├── ibm3151 +│   │   │   │   │   ├── ibm3161 +│   │   │   │   │   ├── ibm3161-C +│   │   │   │   │   ├── ibm3162 +│   │   │   │   │   ├── ibm3163 -> .././69/ibm3161 +│   │   │   │   │   ├── ibm3164 +│   │   │   │   │   ├── ibm327x +│   │   │   │   │   ├── ibm5051 -> .././69/ibm-pc +│   │   │   │   │   ├── ibm5081 +│   │   │   │   │   ├── ibm5081-c +│   │   │   │   │   ├── ibm5151 +│   │   │   │   │   ├── ibm5154 +│   │   │   │   │   ├── ibm5154-c -> .././69/ibmega-c +│   │   │   │   │   ├── ibm6153 +│   │   │   │   │   ├── ibm6153-40 +│   │   │   │   │   ├── ibm6153-90 +│   │   │   │   │   ├── ibm6154 +│   │   │   │   │   ├── ibm6154-c -> .././69/ibmapa8c-c +│   │   │   │   │   ├── ibm6155 +│   │   │   │   │   ├── ibm8503 +│   │   │   │   │   ├── ibm8507 -> .././69/ibm8503 +│   │   │   │   │   ├── ibm8512 +│   │   │   │   │   ├── ibm8513 -> .././69/ibm8512 +│   │   │   │   │   ├── ibm8514 +│   │   │   │   │   ├── ibm8514-c +│   │   │   │   │   ├── ibm8604 -> .././69/ibm8503 +│   │   │   │   │   ├── ibmaed +│   │   │   │   │   ├── ibmapa16 -> .././72/rtpc +│   │   │   │   │   ├── ibmapa8 -> .././69/ibmapa8c +│   │   │   │   │   ├── ibmapa8c +│   │   │   │   │   ├── ibmapa8c-c +│   │   │   │   │   ├── ibm-apl +│   │   │   │   │   ├── ibm+color +│   │   │   │   │   ├── ibmega +│   │   │   │   │   ├── ibmega-c +│   │   │   │   │   ├── ibmmono +│   │   │   │   │   ├── ibmmpel-c -> .././69/ibm5081-c +│   │   │   │   │   ├── ibm-pc +│   │   │   │   │   ├── ibmpc +│   │   │   │   │   ├── ibmpc3 +│   │   │   │   │   ├── ibmpc3r -> .././63/cons25r +│   │   │   │   │   ├── ibmpc3r-mono -> .././63/cons25r-m +│   │   │   │   │   ├── ibmpcx +│   │   │   │   │   ├── ibm-system1 +│   │   │   │   │   ├── ibmvga +│   │   │   │   │   ├── ibmvga-c +│   │   │   │   │   ├── ibmx -> .././69/ibmpcx +│   │   │   │   │   ├── icl6402 -> .././69/icl6404 +│   │   │   │   │   ├── icl6404 +│   │   │   │   │   ├── icl6404-w +│   │   │   │   │   ├── ifmr +│   │   │   │   │   ├── illumos +│   │   │   │   │   ├── ims950 +│   │   │   │   │   ├── ims950-b +│   │   │   │   │   ├── ims950-rv +│   │   │   │   │   ├── ims-ansi +│   │   │   │   │   ├── infoton +│   │   │   │   │   ├── infoton2 +│   │   │   │   │   ├── interix +│   │   │   │   │   ├── interix-nti +│   │   │   │   │   ├── intertec -> .././69/intertube +│   │   │   │   │   ├── intertube +│   │   │   │   │   ├── intertube2 +│   │   │   │   │   ├── intext +│   │   │   │   │   ├── intext2 +│   │   │   │   │   ├── intextii -> .././69/intext2 +│   │   │   │   │   ├── ips -> .././63/citoh-prop +│   │   │   │   │   ├── ipsi -> .././64/diablo1620 +│   │   │   │   │   ├── iq120 -> .././73/soroc120 +│   │   │   │   │   ├── iq140 -> .././73/soroc140 +│   │   │   │   │   ├── iris40 -> .././77/wsiris +│   │   │   │   │   ├── iris-ansi +│   │   │   │   │   ├── iris-ansi-ap +│   │   │   │   │   ├── iris-ansi-net -> .././69/iris-ansi +│   │   │   │   │   ├── iris-color +│   │   │   │   │   ├── iterm -> .././69/iTerm.app +│   │   │   │   │   ├── iterm2 -> .././69/iTerm2.app +│   │   │   │   │   ├── iTerm2.app +│   │   │   │   │   ├── iterm2-direct +│   │   │   │   │   └── iTerm.app +│   │   │   │   ├── 6a +│   │   │   │   │   ├── jaixterm +│   │   │   │   │   ├── jaixterm-m +│   │   │   │   │   ├── jerq -> .././62/blit +│   │   │   │   │   └── jfbterm +│   │   │   │   ├── 6b +│   │   │   │   │   ├── k45 -> .././68/hp2621-k45 +│   │   │   │   │   ├── kaypro +│   │   │   │   │   ├── kaypro2 -> .././6b/kaypro +│   │   │   │   │   ├── kds6402 -> .././69/icl6404 +│   │   │   │   │   ├── kds7372 -> .././69/icl6404 +│   │   │   │   │   ├── kds7372-w -> .././69/icl6404-w +│   │   │   │   │   ├── kermit +│   │   │   │   │   ├── kermit-am +│   │   │   │   │   ├── kitty +│   │   │   │   │   ├── kitty+common +│   │   │   │   │   ├── kitty-direct +│   │   │   │   │   ├── kitty+setal +│   │   │   │   │   ├── klone+acs +│   │   │   │   │   ├── klone+color +│   │   │   │   │   ├── klone+koi8acs +│   │   │   │   │   ├── klone+sgr +│   │   │   │   │   ├── klone+sgr8 +│   │   │   │   │   ├── klone+sgr-dumb +│   │   │   │   │   ├── kon +│   │   │   │   │   ├── kon2 -> .././6b/kon +│   │   │   │   │   ├── konsole +│   │   │   │   │   ├── konsole-16color +│   │   │   │   │   ├── konsole-256color +│   │   │   │   │   ├── konsole-base +│   │   │   │   │   ├── konsole-direct +│   │   │   │   │   ├── konsole-linux +│   │   │   │   │   ├── konsole+pcfkeys +│   │   │   │   │   ├── konsole-solaris +│   │   │   │   │   ├── konsole-vt100 +│   │   │   │   │   ├── konsole-vt420pc +│   │   │   │   │   ├── konsole-xf3x +│   │   │   │   │   ├── konsole-xf4x +│   │   │   │   │   ├── kt7 +│   │   │   │   │   ├── kt7ix +│   │   │   │   │   ├── kterm +│   │   │   │   │   ├── kterm-co -> .././6b/kterm-color +│   │   │   │   │   ├── kterm-color +│   │   │   │   │   ├── ktm -> .././73/synertek +│   │   │   │   │   └── kvt +│   │   │   │   ├── 6c +│   │   │   │   │   ├── la120 -> .././64/dw3 +│   │   │   │   │   ├── layer -> .././61/att5620-s +│   │   │   │   │   ├── lft +│   │   │   │   │   ├── lft-pc850 -> .././6c/lft +│   │   │   │   │   ├── linux +│   │   │   │   │   ├── linux-16color +│   │   │   │   │   ├── linux2.2 +│   │   │   │   │   ├── linux2.6 +│   │   │   │   │   ├── linux2.6.26 +│   │   │   │   │   ├── linux3.0 +│   │   │   │   │   ├── linux-basic +│   │   │   │   │   ├── linux-c +│   │   │   │   │   ├── linux-c-nc +│   │   │   │   │   ├── linux+decid +│   │   │   │   │   ├── linux+kbs +│   │   │   │   │   ├── linux-koi8 +│   │   │   │   │   ├── linux-koi8r +│   │   │   │   │   ├── linux-lat +│   │   │   │   │   ├── linux+lockeys +│   │   │   │   │   ├── linux-m +│   │   │   │   │   ├── linux-m1 +│   │   │   │   │   ├── linux-m1b +│   │   │   │   │   ├── linux-m2 +│   │   │   │   │   ├── linux-nic +│   │   │   │   │   ├── linux-s +│   │   │   │   │   ├── linux+sfkeys +│   │   │   │   │   ├── linux-vt +│   │   │   │   │   ├── lisa +│   │   │   │   │   ├── lisaterm +│   │   │   │   │   ├── lisaterm-w +│   │   │   │   │   ├── liswb +│   │   │   │   │   ├── ln03 +│   │   │   │   │   ├── ln03-w +│   │   │   │   │   ├── lpr +│   │   │   │   │   ├── luna +│   │   │   │   │   └── luna68k -> .././6c/luna +│   │   │   │   ├── 6d +│   │   │   │   │   ├── m2-nam +│   │   │   │   │   ├── mac +│   │   │   │   │   ├── mach +│   │   │   │   │   ├── mach-bold +│   │   │   │   │   ├── mach-color +│   │   │   │   │   ├── mach-gnu +│   │   │   │   │   ├── mach-gnu-color +│   │   │   │   │   ├── macintosh -> .././6d/mac +│   │   │   │   │   ├── macterminal-w -> .././6d/mac-w +│   │   │   │   │   ├── mac-w +│   │   │   │   │   ├── mai +│   │   │   │   │   ├── masscomp +│   │   │   │   │   ├── masscomp1 +│   │   │   │   │   ├── masscomp2 +│   │   │   │   │   ├── mdl110 -> .././63/cyb110 +│   │   │   │   │   ├── megatek +│   │   │   │   │   ├── memhp +│   │   │   │   │   ├── mgr +│   │   │   │   │   ├── mgr-linux +│   │   │   │   │   ├── mgr-sun +│   │   │   │   │   ├── mgt +│   │   │   │   │   ├── mgterm +│   │   │   │   │   ├── microb +│   │   │   │   │   ├── microbee -> .././6d/microb +│   │   │   │   │   ├── microterm -> .././61/act4 +│   │   │   │   │   ├── microterm5 -> .././61/act5 +│   │   │   │   │   ├── mime +│   │   │   │   │   ├── mime1 -> .././6d/mime +│   │   │   │   │   ├── mime2 -> .././6d/mime +│   │   │   │   │   ├── mime2a +│   │   │   │   │   ├── mime2a-s +│   │   │   │   │   ├── mime2a-v -> .././6d/mime2a +│   │   │   │   │   ├── mime314 +│   │   │   │   │   ├── mime340 -> .././6d/mm340 +│   │   │   │   │   ├── mime3a +│   │   │   │   │   ├── mime-3ax -> .././6d/mime3ax +│   │   │   │   │   ├── mime3ax +│   │   │   │   │   ├── mime-fb +│   │   │   │   │   ├── mime-hb +│   │   │   │   │   ├── mimei -> .././6d/mime +│   │   │   │   │   ├── mimeii -> .././6d/mime +│   │   │   │   │   ├── minitel -> .././6d/m2-nam +│   │   │   │   │   ├── minitel1 +│   │   │   │   │   ├── minitel12-80 +│   │   │   │   │   ├── minitel1b +│   │   │   │   │   ├── minitel1b-80 +│   │   │   │   │   ├── minitel1b-nb +│   │   │   │   │   ├── minitel1-nb +│   │   │   │   │   ├── minitel-2 -> .././6d/m2-nam +│   │   │   │   │   ├── minitel2-80 +│   │   │   │   │   ├── minitel-2-nam -> .././6d/m2-nam +│   │   │   │   │   ├── minix +│   │   │   │   │   ├── minix-1.5 -> .././6d/minix-old +│   │   │   │   │   ├── minix-1.7 +│   │   │   │   │   ├── minix-3.0 +│   │   │   │   │   ├── minix-old +│   │   │   │   │   ├── minix-old-am +│   │   │   │   │   ├── mintty +│   │   │   │   │   ├── mintty+common +│   │   │   │   │   ├── mintty-direct +│   │   │   │   │   ├── mintty+keypad +│   │   │   │   │   ├── mlterm +│   │   │   │   │   ├── mlterm2 +│   │   │   │   │   ├── mlterm-256color +│   │   │   │   │   ├── mlterm3 +│   │   │   │   │   ├── mlterm-direct +│   │   │   │   │   ├── mlterm+pcfkeys +│   │   │   │   │   ├── mm314 -> .././6d/mime314 +│   │   │   │   │   ├── mm340 +│   │   │   │   │   ├── mod -> .././6d/modgraph48 +│   │   │   │   │   ├── mod24 -> .././6d/modgraph +│   │   │   │   │   ├── modgraph +│   │   │   │   │   ├── modgraph2 +│   │   │   │   │   ├── modgraph48 +│   │   │   │   │   ├── mono-emx +│   │   │   │   │   ├── morphos +│   │   │   │   │   ├── mosh +│   │   │   │   │   ├── mosh-256color +│   │   │   │   │   ├── mostlike +│   │   │   │   │   ├── mouse-sun -> .././6d/mterm +│   │   │   │   │   ├── mrxvt +│   │   │   │   │   ├── mrxvt-256color +│   │   │   │   │   ├── msk227 +│   │   │   │   │   ├── msk22714 +│   │   │   │   │   ├── msk227am +│   │   │   │   │   ├── mskermit227 -> .././6d/msk227 +│   │   │   │   │   ├── mskermit22714 -> .././6d/msk22714 +│   │   │   │   │   ├── mskermit227am -> .././6d/msk227am +│   │   │   │   │   ├── ms+terminal +│   │   │   │   │   ├── ms-terminal +│   │   │   │   │   ├── ms-terminal-direct +│   │   │   │   │   ├── ms-vt100 +│   │   │   │   │   ├── ms-vt100+ +│   │   │   │   │   ├── ms-vt100-16color +│   │   │   │   │   ├── ms-vt100-color +│   │   │   │   │   ├── ms-vt-utf8 +│   │   │   │   │   ├── mt4520-rv +│   │   │   │   │   ├── mt-70 -> .././6d/mt70 +│   │   │   │   │   ├── mt70 +│   │   │   │   │   ├── mterm +│   │   │   │   │   ├── mterm-ansi +│   │   │   │   │   └── mvterm +│   │   │   │   ├── 6e +│   │   │   │   │   ├── n7900 -> .././6e/ncr7900i +│   │   │   │   │   ├── nansi.sys +│   │   │   │   │   ├── nansisys -> .././6e/nansi.sys +│   │   │   │   │   ├── nansi.sysk +│   │   │   │   │   ├── nansisysk -> .././6e/nansi.sysk +│   │   │   │   │   ├── ncr160vppp +│   │   │   │   │   ├── ncr160vpwpp +│   │   │   │   │   ├── ncr160vt100an +│   │   │   │   │   ├── ncr160vt100pp +│   │   │   │   │   ├── ncr160vt100wan +│   │   │   │   │   ├── ncr160vt100wpp +│   │   │   │   │   ├── ncr160vt200an +│   │   │   │   │   ├── ncr160vt200pp +│   │   │   │   │   ├── ncr160vt200wan +│   │   │   │   │   ├── ncr160vt200wpp +│   │   │   │   │   ├── ncr160vt300an +│   │   │   │   │   ├── ncr160vt300pp +│   │   │   │   │   ├── ncr160vt300wan +│   │   │   │   │   ├── ncr160vt300wpp +│   │   │   │   │   ├── ncr160wy50+pp +│   │   │   │   │   ├── ncr160wy50+wpp +│   │   │   │   │   ├── ncr160wy60pp +│   │   │   │   │   ├── ncr160wy60wpp +│   │   │   │   │   ├── ncr260intan +│   │   │   │   │   ├── ncr260intpp +│   │   │   │   │   ├── ncr260intwan +│   │   │   │   │   ├── ncr260intwpp +│   │   │   │   │   ├── ncr260vppp +│   │   │   │   │   ├── ncr260vp+sl +│   │   │   │   │   ├── ncr260vpwpp +│   │   │   │   │   ├── ncr260vt100an +│   │   │   │   │   ├── ncr260vt100pp +│   │   │   │   │   ├── ncr260vt100wan +│   │   │   │   │   ├── ncr260vt100wpp +│   │   │   │   │   ├── ncr260vt200an +│   │   │   │   │   ├── ncr260vt200pp +│   │   │   │   │   ├── ncr260vt200wan +│   │   │   │   │   ├── ncr260vt200wpp +│   │   │   │   │   ├── ncr260vt300an +│   │   │   │   │   ├── ncr260vt300pp +│   │   │   │   │   ├── ncr260vt300wan +│   │   │   │   │   ├── ncr260vt300wpp +│   │   │   │   │   ├── ncr260vt+sl +│   │   │   │   │   ├── ncr260wy325pp +│   │   │   │   │   ├── ncr260wy325wpp +│   │   │   │   │   ├── ncr260wy350pp +│   │   │   │   │   ├── ncr260wy350wpp +│   │   │   │   │   ├── ncr260wy50+pp +│   │   │   │   │   ├── ncr260wy50+wpp +│   │   │   │   │   ├── ncr260wy60pp +│   │   │   │   │   ├── ncr260wy60wpp +│   │   │   │   │   ├── ncr7900 -> .././6e/ncr7900i +│   │   │   │   │   ├── ncr7900i +│   │   │   │   │   ├── ncr7900iv +│   │   │   │   │   ├── ncr7901 +│   │   │   │   │   ├── ncrvt100an +│   │   │   │   │   ├── ncrvt100pp -> .././6e/ncrvt100an +│   │   │   │   │   ├── ncrvt100wan +│   │   │   │   │   ├── ncrvt100wpp -> .././6e/ncrvt100wan +│   │   │   │   │   ├── ncsa +│   │   │   │   │   ├── ncsa-m +│   │   │   │   │   ├── ncsa-m-ns +│   │   │   │   │   ├── ncsa-ns +│   │   │   │   │   ├── ncsa-vt220 +│   │   │   │   │   ├── ncsa-vt220-8 -> .././6e/ncsa-m +│   │   │   │   │   ├── nd9500 -> .././6e/ndr9500 +│   │   │   │   │   ├── ndr9500 +│   │   │   │   │   ├── ndr9500-25 +│   │   │   │   │   ├── ndr9500-25-mc +│   │   │   │   │   ├── ndr9500-25-mc-nl +│   │   │   │   │   ├── ndr9500-25-nl +│   │   │   │   │   ├── ndr9500-mc +│   │   │   │   │   ├── ndr9500-mc-nl +│   │   │   │   │   ├── ndr9500-nl +│   │   │   │   │   ├── nec -> .././6e/nec5520 +│   │   │   │   │   ├── nec5520 +│   │   │   │   │   ├── netbsd6 +│   │   │   │   │   ├── newhp +│   │   │   │   │   ├── newhpkeyboard +│   │   │   │   │   ├── news -> .././6e/nwp512 +│   │   │   │   │   ├── news28 +│   │   │   │   │   ├── news28-a -> .././6e/news29 +│   │   │   │   │   ├── news-29 +│   │   │   │   │   ├── news29 +│   │   │   │   │   ├── news-29-euc +│   │   │   │   │   ├── news-29-sjis +│   │   │   │   │   ├── news31 -> .././6e/nwp513 +│   │   │   │   │   ├── news31-a -> .././6e/nwp513-a +│   │   │   │   │   ├── news31-o -> .././6e/nwp513 +│   │   │   │   │   ├── news-33 +│   │   │   │   │   ├── news33 -> .././6e/nwp513-a +│   │   │   │   │   ├── news-33-euc +│   │   │   │   │   ├── news-33-sjis +│   │   │   │   │   ├── news40 -> .././6e/nwp512 +│   │   │   │   │   ├── news40-a -> .././6e/nwp512-a +│   │   │   │   │   ├── news40-o -> .././6e/nwp512 +│   │   │   │   │   ├── news-42 +│   │   │   │   │   ├── news42 -> .././6e/nwp512-a +│   │   │   │   │   ├── news-42-euc +│   │   │   │   │   ├── news-42-sjis +│   │   │   │   │   ├── news-a -> .././6e/nwp512-a +│   │   │   │   │   ├── newscbm -> .././6e/nwp513 +│   │   │   │   │   ├── newscbm33 -> .././6e/nwp513-a +│   │   │   │   │   ├── newscbm-a -> .././6e/nwp513-a +│   │   │   │   │   ├── newscbm-o -> .././6e/nwp513 +│   │   │   │   │   ├── news-o -> .././6e/nwp512 +│   │   │   │   │   ├── news-old-unk +│   │   │   │   │   ├── news-unk +│   │   │   │   │   ├── next +│   │   │   │   │   ├── nextshell +│   │   │   │   │   ├── no+brackets +│   │   │   │   │   ├── northstar +│   │   │   │   │   ├── nsterm +│   │   │   │   │   ├── nsterm-16color +│   │   │   │   │   ├── nsterm-256color -> .././6e/nsterm +│   │   │   │   │   ├── nsterm+7 +│   │   │   │   │   ├── nsterm-7 +│   │   │   │   │   ├── nsterm-7-c +│   │   │   │   │   ├── nsterm-7-c-s -> .././6e/nsterm-c-s-7 +│   │   │   │   │   ├── nsterm-7-m -> .././6e/nsterm-m-7 +│   │   │   │   │   ├── nsterm-7-m-s -> .././6e/nsterm-m-s-7 +│   │   │   │   │   ├── nsterm-7-s -> .././6e/nsterm-s-7 +│   │   │   │   │   ├── nsterm+acs +│   │   │   │   │   ├── nsterm-acs +│   │   │   │   │   ├── nsterm-acs-c -> .././6e/nsterm-c-acs +│   │   │   │   │   ├── nsterm-acs-c-s -> .././6e/nsterm-c-s-acs +│   │   │   │   │   ├── nsterm-acs-m -> .././6e/nsterm-m-acs +│   │   │   │   │   ├── nsterm-acs-m-s -> .././6e/nsterm-m-s-acs +│   │   │   │   │   ├── nsterm-acs-s -> .././6e/nsterm-s-acs +│   │   │   │   │   ├── nsterm-bce +│   │   │   │   │   ├── nsterm-build309 +│   │   │   │   │   ├── nsterm-build326 +│   │   │   │   │   ├── nsterm-build343 +│   │   │   │   │   ├── nsterm-build361 +│   │   │   │   │   ├── nsterm-build400 +│   │   │   │   │   ├── nsterm-build440 +│   │   │   │   │   ├── nsterm+c +│   │   │   │   │   ├── nsterm-c +│   │   │   │   │   ├── nsterm+c41 +│   │   │   │   │   ├── nsterm-c-7 -> .././6e/nsterm-7-c +│   │   │   │   │   ├── nsterm-c-acs +│   │   │   │   │   ├── nsterm-c-s +│   │   │   │   │   ├── nsterm-c-s-7 +│   │   │   │   │   ├── nsterm-c-s-acs +│   │   │   │   │   ├── nsterm-direct +│   │   │   │   │   ├── nsterm-m +│   │   │   │   │   ├── nsterm-m-7 +│   │   │   │   │   ├── nsterm+mac +│   │   │   │   │   ├── nsterm-m-acs +│   │   │   │   │   ├── nsterm-m-s +│   │   │   │   │   ├── nsterm-m-s-7 +│   │   │   │   │   ├── nsterm-m-s-acs +│   │   │   │   │   ├── nsterm-old +│   │   │   │   │   ├── nsterm+s +│   │   │   │   │   ├── nsterm-s +│   │   │   │   │   ├── nsterm-s-7 +│   │   │   │   │   ├── nsterm-s-acs +│   │   │   │   │   ├── ntconsole -> .././69/interix +│   │   │   │   │   ├── ntconsole-100 -> .././6f/opennt-100 +│   │   │   │   │   ├── ntconsole-100-nti -> .././6f/opennt-100-nti +│   │   │   │   │   ├── ntconsole-25 -> .././69/interix +│   │   │   │   │   ├── ntconsole-25-nti -> .././69/interix-nti +│   │   │   │   │   ├── ntconsole-25-w -> .././6f/opennt-w +│   │   │   │   │   ├── ntconsole-25-w-vt -> .././6f/opennt-w-vt +│   │   │   │   │   ├── ntconsole-35 -> .././6f/opennt-35 +│   │   │   │   │   ├── ntconsole-35-nti -> .././6f/opennt-35-nti +│   │   │   │   │   ├── ntconsole-35-w -> .././6f/opennt-35-w +│   │   │   │   │   ├── ntconsole-50 -> .././6f/opennt-50 +│   │   │   │   │   ├── ntconsole-50-nti -> .././6f/opennt-50-nti +│   │   │   │   │   ├── ntconsole-50-w -> .././6f/opennt-50-w +│   │   │   │   │   ├── ntconsole-60 -> .././6f/opennt-60 +│   │   │   │   │   ├── ntconsole-60-nti -> .././6f/opennt-60-nti +│   │   │   │   │   ├── ntconsole-60-w -> .././6f/opennt-60-w +│   │   │   │   │   ├── ntconsole-w -> .././6f/opennt-w +│   │   │   │   │   ├── ntconsole-w-vt -> .././6f/opennt-w-vt +│   │   │   │   │   ├── nwe501 -> .././6e/nwp513 +│   │   │   │   │   ├── nwe501-a -> .././6e/nwp513-a +│   │   │   │   │   ├── nwe501-o -> .././6e/nwp513 +│   │   │   │   │   ├── nwp251-a -> .././6e/nwp513-a +│   │   │   │   │   ├── nwp251-o -> .././6e/nwp513 +│   │   │   │   │   ├── nwp-511 -> .././6e/nwp511 +│   │   │   │   │   ├── nwp511 +│   │   │   │   │   ├── nwp512 +│   │   │   │   │   ├── nwp512-a +│   │   │   │   │   ├── nwp512-o -> .././6e/nwp512 +│   │   │   │   │   ├── nwp513 +│   │   │   │   │   ├── nwp513-a +│   │   │   │   │   ├── nwp513-o -> .././6e/nwp513 +│   │   │   │   │   ├── nwp514 -> .././6e/nwp512 +│   │   │   │   │   ├── nwp514-a -> .././6e/nwp512-a +│   │   │   │   │   ├── nwp514-o -> .././6e/nwp512 +│   │   │   │   │   ├── nwp-517 -> .././6e/nwp517 +│   │   │   │   │   ├── nwp517 +│   │   │   │   │   ├── nwp-517-w -> .././6e/nwp517-w +│   │   │   │   │   ├── nwp517-w +│   │   │   │   │   ├── nwp518 -> .././6e/nwp513 +│   │   │   │   │   ├── nwp518-a -> .././6e/nwp513-a +│   │   │   │   │   ├── nwp518-o -> .././6e/nwp513 +│   │   │   │   │   └── nxterm -> .././78/xterm-color +│   │   │   │   ├── 6f +│   │   │   │   │   ├── o31 -> .././61/adm31-old +│   │   │   │   │   ├── o4112-nd -> .././6f/otek4112 +│   │   │   │   │   ├── o85h -> .././61/abm85h-old +│   │   │   │   │   ├── oabm85h -> .././61/abm85h-old +│   │   │   │   │   ├── oblit +│   │   │   │   │   ├── oc100 +│   │   │   │   │   ├── oconcept -> .././6f/oc100 +│   │   │   │   │   ├── ofcons +│   │   │   │   │   ├── ojerq -> .././6f/oblit +│   │   │   │   │   ├── oldibmpc3 -> .././6f/oldpc3 +│   │   │   │   │   ├── oldpc3 +│   │   │   │   │   ├── old-st -> .././73/simpleterm +│   │   │   │   │   ├── oldsun +│   │   │   │   │   ├── oldxterm+sm+1006 +│   │   │   │   │   ├── omron +│   │   │   │   │   ├── opennt -> .././69/interix +│   │   │   │   │   ├── opennt-100 +│   │   │   │   │   ├── opennt-100-nti +│   │   │   │   │   ├── opennt-25 -> .././69/interix +│   │   │   │   │   ├── opennt-25-nti -> .././69/interix-nti +│   │   │   │   │   ├── opennt-25-w -> .././6f/opennt-w +│   │   │   │   │   ├── opennt-25-w-vt -> .././6f/opennt-w-vt +│   │   │   │   │   ├── opennt-35 +│   │   │   │   │   ├── opennt-35-nti +│   │   │   │   │   ├── opennt-35-w +│   │   │   │   │   ├── opennt-50 +│   │   │   │   │   ├── opennt-50-nti +│   │   │   │   │   ├── opennt-50-w +│   │   │   │   │   ├── opennt-60 +│   │   │   │   │   ├── opennt-60-nti +│   │   │   │   │   ├── opennt-60-w +│   │   │   │   │   ├── opennt-nti -> .././69/interix-nti +│   │   │   │   │   ├── opennt-w +│   │   │   │   │   ├── opennt-w-vt +│   │   │   │   │   ├── opus3n1+ +│   │   │   │   │   ├── origibmpc3 -> .././6f/origpc3 +│   │   │   │   │   ├── origpc3 +│   │   │   │   │   ├── os9LII -> .././63/coco3 +│   │   │   │   │   ├── osborne +│   │   │   │   │   ├── osborne1 -> .././6f/osborne +│   │   │   │   │   ├── osborne1-w -> .././6f/osborne-w +│   │   │   │   │   ├── osborne-w +│   │   │   │   │   ├── osexec +│   │   │   │   │   ├── otek4112 +│   │   │   │   │   ├── otek4113 -> .././6f/otek4112 +│   │   │   │   │   ├── otek4114 -> .././6f/otek4112 +│   │   │   │   │   ├── otek4115 +│   │   │   │   │   └── owl +│   │   │   │   ├── 70 +│   │   │   │   │   ├── p12 -> .././70/prism12 +│   │   │   │   │   ├── p12-m -> .././70/prism12-m +│   │   │   │   │   ├── p12-m-w -> .././70/prism12-m-w +│   │   │   │   │   ├── p12-w -> .././70/prism12-w +│   │   │   │   │   ├── p14 -> .././70/prism14 +│   │   │   │   │   ├── p14-m -> .././70/prism14-m +│   │   │   │   │   ├── p14-m-w -> .././70/prism14-m-w +│   │   │   │   │   ├── p14-w -> .././70/prism14-w +│   │   │   │   │   ├── p19 +│   │   │   │   │   ├── p4 -> .././70/prism4 +│   │   │   │   │   ├── p5 -> .././70/prism5 +│   │   │   │   │   ├── p7 -> .././70/prism7 +│   │   │   │   │   ├── p8 -> .././70/prism8 +│   │   │   │   │   ├── p8gl +│   │   │   │   │   ├── p8-w -> .././70/prism8-w +│   │   │   │   │   ├── p9 -> .././70/prism9 +│   │   │   │   │   ├── p9-8 -> .././70/prism9-8 +│   │   │   │   │   ├── p9-8-w -> .././70/prism9-8-w +│   │   │   │   │   ├── p9-w -> .././70/prism9-w +│   │   │   │   │   ├── pangoterm +│   │   │   │   │   ├── pangoterm-256color +│   │   │   │   │   ├── pangoterm-direct +│   │   │   │   │   ├── pc3 +│   │   │   │   │   ├── pc3-bold -> .././69/ibmpc3 +│   │   │   │   │   ├── pc3r -> .././63/cons25r +│   │   │   │   │   ├── pc3r-m -> .././63/cons25r-m +│   │   │   │   │   ├── pc6300plus +│   │   │   │   │   ├── pc7300 -> .././61/att7300 +│   │   │   │   │   ├── pcansi +│   │   │   │   │   ├── pcansi-25 +│   │   │   │   │   ├── pcansi25 -> .././70/pcansi-25 +│   │   │   │   │   ├── pcansi-25-m +│   │   │   │   │   ├── pcansi25m -> .././70/pcansi-25-m +│   │   │   │   │   ├── pcansi-33 +│   │   │   │   │   ├── pcansi33 -> .././70/pcansi-33 +│   │   │   │   │   ├── pcansi-33-m +│   │   │   │   │   ├── pcansi33m -> .././70/pcansi-33-m +│   │   │   │   │   ├── pcansi-43 +│   │   │   │   │   ├── pcansi43 -> .././70/pcansi-43 +│   │   │   │   │   ├── pcansi-43-m +│   │   │   │   │   ├── pcansi-m +│   │   │   │   │   ├── pcansi-mono -> .././70/pcansi-m +│   │   │   │   │   ├── pc-coherent +│   │   │   │   │   ├── pccon +│   │   │   │   │   ├── pccon0 +│   │   │   │   │   ├── pccon0-m +│   │   │   │   │   ├── pccon+base +│   │   │   │   │   ├── pccon+colors +│   │   │   │   │   ├── pccon+keys +│   │   │   │   │   ├── pccon-m +│   │   │   │   │   ├── pccons +│   │   │   │   │   ├── pccon+sgr+acs +│   │   │   │   │   ├── pccon+sgr+acs0 +│   │   │   │   │   ├── pcconsole -> .././70/pccons +│   │   │   │   │   ├── pcix +│   │   │   │   │   ├── pckermit +│   │   │   │   │   ├── pckermit12 -> .././70/pckermit +│   │   │   │   │   ├── pckermit120 +│   │   │   │   │   ├── pc-minix +│   │   │   │   │   ├── pcmw +│   │   │   │   │   ├── pcplot +│   │   │   │   │   ├── pc-venix +│   │   │   │   │   ├── pcvt25 +│   │   │   │   │   ├── pcvt25-color +│   │   │   │   │   ├── pcvt25w +│   │   │   │   │   ├── pcvt28 +│   │   │   │   │   ├── pcvt28w +│   │   │   │   │   ├── pcvt35 +│   │   │   │   │   ├── pcvt35w +│   │   │   │   │   ├── pcvt40 +│   │   │   │   │   ├── pcvt40w +│   │   │   │   │   ├── pcvt43 +│   │   │   │   │   ├── pcvt43w +│   │   │   │   │   ├── pcvt50 +│   │   │   │   │   ├── pcvt50w +│   │   │   │   │   ├── pcvtXX +│   │   │   │   │   ├── pcz19 -> .././70/pc-coherent +│   │   │   │   │   ├── pe1100 -> .././66/fox +│   │   │   │   │   ├── pe1200 -> .././6f/owl +│   │   │   │   │   ├── pe1251 +│   │   │   │   │   ├── pe550 -> .././62/bantam +│   │   │   │   │   ├── pe6100 -> .././62/bantam +│   │   │   │   │   ├── pe6300 -> .././70/pe1251 +│   │   │   │   │   ├── pe6312 -> .././70/pe1251 +│   │   │   │   │   ├── pe7000c +│   │   │   │   │   ├── pe7000m +│   │   │   │   │   ├── pilot +│   │   │   │   │   ├── pmcons +│   │   │   │   │   ├── pmconsole -> .././70/pmcons +│   │   │   │   │   ├── printer -> .././6c/lpr +│   │   │   │   │   ├── prism12 +│   │   │   │   │   ├── prism12-m +│   │   │   │   │   ├── prism12-m-w +│   │   │   │   │   ├── prism12-w +│   │   │   │   │   ├── prism14 +│   │   │   │   │   ├── prism14-m +│   │   │   │   │   ├── prism14-m-w +│   │   │   │   │   ├── prism14-w +│   │   │   │   │   ├── prism2 +│   │   │   │   │   ├── prism4 +│   │   │   │   │   ├── prism5 +│   │   │   │   │   ├── prism7 +│   │   │   │   │   ├── prism8 +│   │   │   │   │   ├── prism8gl -> .././70/p8gl +│   │   │   │   │   ├── prism8-w +│   │   │   │   │   ├── prism9 +│   │   │   │   │   ├── prism9-8 +│   │   │   │   │   ├── prism9-8-w +│   │   │   │   │   ├── prism9-w +│   │   │   │   │   ├── pro350 +│   │   │   │   │   ├── ps300 +│   │   │   │   │   ├── psterm +│   │   │   │   │   ├── psterm-80x24 +│   │   │   │   │   ├── psterm-90x28 +│   │   │   │   │   ├── psterm-96x48 +│   │   │   │   │   ├── psterm-basic -> .././70/psterm +│   │   │   │   │   ├── psterm-fast +│   │   │   │   │   ├── psx_ansi -> .././61/ansi-nt +│   │   │   │   │   ├── pt100 +│   │   │   │   │   ├── pt100w +│   │   │   │   │   ├── pt200 -> .././70/pt100 +│   │   │   │   │   ├── pt200w -> .././70/pt100w +│   │   │   │   │   ├── pt210 +│   │   │   │   │   ├── pt250 +│   │   │   │   │   ├── pt250w +│   │   │   │   │   ├── pt505 -> .././61/att505 +│   │   │   │   │   ├── pt505-22 -> .././61/att505-22 +│   │   │   │   │   ├── pt505-24 -> .././61/att505-24 +│   │   │   │   │   ├── pty +│   │   │   │   │   ├── putty +│   │   │   │   │   ├── putty-256color +│   │   │   │   │   ├── putty+cursor +│   │   │   │   │   ├── putty+fnkeys +│   │   │   │   │   ├── putty+fnkeys+esc +│   │   │   │   │   ├── putty+fnkeys+linux +│   │   │   │   │   ├── putty+fnkeys+sco +│   │   │   │   │   ├── putty+fnkeys+vt100 +│   │   │   │   │   ├── putty+fnkeys+vt400 +│   │   │   │   │   ├── putty+fnkeys+xterm +│   │   │   │   │   ├── putty+keypad +│   │   │   │   │   ├── putty-m1 +│   │   │   │   │   ├── putty-m1b +│   │   │   │   │   ├── putty-m2 +│   │   │   │   │   ├── putty-noapp +│   │   │   │   │   ├── putty-sco +│   │   │   │   │   ├── putty+screen +│   │   │   │   │   ├── putty-screen +│   │   │   │   │   └── putty-vt100 +│   │   │   │   ├── 71 +│   │   │   │   │   ├── qansi +│   │   │   │   │   ├── qansi-g +│   │   │   │   │   ├── qansi-m +│   │   │   │   │   ├── qansi-t +│   │   │   │   │   ├── qansi-w +│   │   │   │   │   ├── qdcons -> .././71/qdss +│   │   │   │   │   ├── qdss +│   │   │   │   │   ├── qnx +│   │   │   │   │   ├── qnx4 -> .././71/qnx +│   │   │   │   │   ├── qnxm +│   │   │   │   │   ├── qnxt +│   │   │   │   │   ├── qnxt2 +│   │   │   │   │   ├── qnxt4 -> .././71/qnxt +│   │   │   │   │   ├── qnxtmono +│   │   │   │   │   ├── qnxw +│   │   │   │   │   ├── qume -> .././71/qume5 +│   │   │   │   │   ├── qume5 +│   │   │   │   │   ├── qvt101 +│   │   │   │   │   ├── qvt101+ +│   │   │   │   │   ├── qvt101p -> .././71/qvt101+ +│   │   │   │   │   ├── qvt102 +│   │   │   │   │   ├── qvt103 +│   │   │   │   │   ├── qvt103-w +│   │   │   │   │   ├── qvt108 -> .././71/qvt101 +│   │   │   │   │   ├── qvt119 -> .././71/qvt119+ +│   │   │   │   │   ├── qvt119+ +│   │   │   │   │   ├── qvt119+-25 +│   │   │   │   │   ├── qvt119+-25-w +│   │   │   │   │   ├── qvt119-25-w -> .././71/qvt119+-25-w +│   │   │   │   │   ├── qvt119p -> .././71/qvt119+ +│   │   │   │   │   ├── qvt119p-25 -> .././71/qvt119+-25 +│   │   │   │   │   ├── qvt119p-25-w -> .././71/qvt119+-25-w +│   │   │   │   │   ├── qvt119p-w -> .././71/qvt119+-w +│   │   │   │   │   ├── qvt119-w -> .././71/qvt119+-w +│   │   │   │   │   ├── qvt119+-w +│   │   │   │   │   ├── qvt203 +│   │   │   │   │   ├── qvt203+ -> .././71/qvt203 +│   │   │   │   │   ├── qvt203-25 +│   │   │   │   │   ├── qvt203-25-w +│   │   │   │   │   ├── qvt203-w +│   │   │   │   │   └── qvt203-w-am -> .././71/qvt203-w +│   │   │   │   ├── 72 +│   │   │   │   │   ├── rbcomm +│   │   │   │   │   ├── rbcomm-nam +│   │   │   │   │   ├── rbcomm-w +│   │   │   │   │   ├── rca +│   │   │   │   │   ├── rcons +│   │   │   │   │   ├── rcons-color +│   │   │   │   │   ├── rebus3180 -> .././64/ddr +│   │   │   │   │   ├── regent +│   │   │   │   │   ├── regent100 +│   │   │   │   │   ├── regent20 +│   │   │   │   │   ├── regent200 -> .././72/regent60 +│   │   │   │   │   ├── regent25 +│   │   │   │   │   ├── regent40 +│   │   │   │   │   ├── regent40+ +│   │   │   │   │   ├── regent60 +│   │   │   │   │   ├── report+da2 +│   │   │   │   │   ├── report+version +│   │   │   │   │   ├── rio +│   │   │   │   │   ├── rio-direct +│   │   │   │   │   ├── rlogin-color +│   │   │   │   │   ├── rt6221 +│   │   │   │   │   ├── rt6221-w +│   │   │   │   │   ├── rtpc +│   │   │   │   │   ├── rxvt +│   │   │   │   │   ├── rxvt-16color +│   │   │   │   │   ├── rxvt-256color +│   │   │   │   │   ├── rxvt-88color +│   │   │   │   │   ├── rxvt-basic +│   │   │   │   │   ├── rxvt-color -> .././72/rxvt +│   │   │   │   │   ├── rxvt-cygwin +│   │   │   │   │   ├── rxvt-cygwin-native +│   │   │   │   │   ├── rxvt+pcfkeys +│   │   │   │   │   └── rxvt-xpm +│   │   │   │   ├── 73 +│   │   │   │   │   ├── s4 -> .././61/att7300 +│   │   │   │   │   ├── sb1 +│   │   │   │   │   ├── sb2 +│   │   │   │   │   ├── sb3 -> .././73/sb2 +│   │   │   │   │   ├── sbi +│   │   │   │   │   ├── sbobcat -> .././62/bobcat +│   │   │   │   │   ├── sc410 -> .././73/scanset +│   │   │   │   │   ├── sc415 -> .././73/scanset +│   │   │   │   │   ├── scanset +│   │   │   │   │   ├── sclp +│   │   │   │   │   ├── scoansi +│   │   │   │   │   ├── scoansi-new +│   │   │   │   │   ├── scoansi-old +│   │   │   │   │   ├── screen +│   │   │   │   │   ├── screen-16color +│   │   │   │   │   ├── screen-16color-bce +│   │   │   │   │   ├── screen-16color-bce-s +│   │   │   │   │   ├── screen-16color-s +│   │   │   │   │   ├── screen2 +│   │   │   │   │   ├── screen-256color +│   │   │   │   │   ├── screen-256color-bce +│   │   │   │   │   ├── screen-256color-bce-s +│   │   │   │   │   ├── screen-256color-s +│   │   │   │   │   ├── screen3 +│   │   │   │   │   ├── screen4 +│   │   │   │   │   ├── screen5 +│   │   │   │   │   ├── screen-base +│   │   │   │   │   ├── screen-bce +│   │   │   │   │   ├── screen-bce.Eterm +│   │   │   │   │   ├── screen-bce.gnome +│   │   │   │   │   ├── screen-bce.konsole +│   │   │   │   │   ├── screen-bce.linux +│   │   │   │   │   ├── screen-bce.mrxvt +│   │   │   │   │   ├── screen-bce.rxvt +│   │   │   │   │   ├── screen-bce.xterm-new +│   │   │   │   │   ├── screen.Eterm +│   │   │   │   │   ├── screen+fkeys +│   │   │   │   │   ├── screen.gnome +│   │   │   │   │   ├── screen+italics +│   │   │   │   │   ├── screen.konsole +│   │   │   │   │   ├── screen.konsole-256color +│   │   │   │   │   ├── screen.linux +│   │   │   │   │   ├── screen.linux-m1 +│   │   │   │   │   ├── screen.linux-m1b +│   │   │   │   │   ├── screen.linux-m2 +│   │   │   │   │   ├── screen.linux-s -> .././73/screen.linux +│   │   │   │   │   ├── screen.minitel1 +│   │   │   │   │   ├── screen.minitel12-80 -> .././73/screen.minitel1b-80 +│   │   │   │   │   ├── screen.minitel1b +│   │   │   │   │   ├── screen.minitel1b-80 +│   │   │   │   │   ├── screen.minitel1b-nb +│   │   │   │   │   ├── screen.minitel1-nb +│   │   │   │   │   ├── screen.minitel2-80 -> .././73/screen.minitel1b-80 +│   │   │   │   │   ├── screen.mlterm +│   │   │   │   │   ├── screen.mlterm-256color +│   │   │   │   │   ├── screen.mrxvt +│   │   │   │   │   ├── screen.putty +│   │   │   │   │   ├── screen.putty-256color +│   │   │   │   │   ├── screen.putty-m1 +│   │   │   │   │   ├── screen.putty-m1b +│   │   │   │   │   ├── screen.putty-m2 +│   │   │   │   │   ├── screen.rxvt +│   │   │   │   │   ├── screen-s +│   │   │   │   │   ├── screen.teraterm +│   │   │   │   │   ├── screen.vte +│   │   │   │   │   ├── screen.vte-256color +│   │   │   │   │   ├── screen-w +│   │   │   │   │   ├── screen.xterm-256color +│   │   │   │   │   ├── screen.xterm-new -> .././73/screen.xterm-xfree86 +│   │   │   │   │   ├── screen.xterm-r6 +│   │   │   │   │   ├── screen.xterm-xfree86 +│   │   │   │   │   ├── screwpoint +│   │   │   │   │   ├── scrhp +│   │   │   │   │   ├── scrt +│   │   │   │   │   ├── securecrt -> .././73/scrt +│   │   │   │   │   ├── sibo +│   │   │   │   │   ├── simpleterm +│   │   │   │   │   ├── simterm +│   │   │   │   │   ├── soroc -> .././73/soroc120 +│   │   │   │   │   ├── soroc120 +│   │   │   │   │   ├── soroc140 +│   │   │   │   │   ├── spinwriter -> .././6e/nec5520 +│   │   │   │   │   ├── st +│   │   │   │   │   ├── st-0.6 +│   │   │   │   │   ├── st-0.7 +│   │   │   │   │   ├── st-0.8 +│   │   │   │   │   ├── st-0.8.5 +│   │   │   │   │   ├── st-16color +│   │   │   │   │   ├── st-256color +│   │   │   │   │   ├── st52 +│   │   │   │   │   ├── st52-color +│   │   │   │   │   ├── st52-m -> .././73/st52 +│   │   │   │   │   ├── st52-old +│   │   │   │   │   ├── st-direct +│   │   │   │   │   ├── stterm -> .././73/st +│   │   │   │   │   ├── stterm-16color -> .././73/st-16color +│   │   │   │   │   ├── stterm-256color -> .././73/st-256color +│   │   │   │   │   ├── stv52 +│   │   │   │   │   ├── stv52pc +│   │   │   │   │   ├── sun +│   │   │   │   │   ├── sun-1 +│   │   │   │   │   ├── sun1 -> .././73/sun +│   │   │   │   │   ├── sun-12 +│   │   │   │   │   ├── sun-16color +│   │   │   │   │   ├── sun-17 +│   │   │   │   │   ├── sun2 -> .././73/sun +│   │   │   │   │   ├── sun-24 +│   │   │   │   │   ├── sun-256color +│   │   │   │   │   ├── sun-34 +│   │   │   │   │   ├── sun-48 +│   │   │   │   │   ├── sun-c +│   │   │   │   │   ├── sun-cgsix +│   │   │   │   │   ├── sun-cmd -> .././73/sun-c +│   │   │   │   │   ├── sun-color +│   │   │   │   │   ├── sun-direct +│   │   │   │   │   ├── sun-e +│   │   │   │   │   ├── sune -> .././73/sun-e +│   │   │   │   │   ├── sun-e-s +│   │   │   │   │   ├── sun-il +│   │   │   │   │   ├── sun-nic -> .././73/sun-e +│   │   │   │   │   ├── sun-s +│   │   │   │   │   ├── sun-s-e -> .././73/sun-e-s +│   │   │   │   │   ├── sun+sl +│   │   │   │   │   ├── sun-ss5 -> .././73/sun-cgsix +│   │   │   │   │   ├── sun-type4 +│   │   │   │   │   ├── superbee -> .././73/sbi +│   │   │   │   │   ├── superbeeic +│   │   │   │   │   ├── superbee-xsb +│   │   │   │   │   ├── superbrain +│   │   │   │   │   ├── sv80 -> .././61/att2300 +│   │   │   │   │   ├── swtp +│   │   │   │   │   ├── synertek +│   │   │   │   │   ├── synertek380 -> .././73/synertek +│   │   │   │   │   └── system1 -> .././69/ibm-system1 +│   │   │   │   ├── 74 +│   │   │   │   │   ├── t10 +│   │   │   │   │   ├── t1061 +│   │   │   │   │   ├── t1061f +│   │   │   │   │   ├── t16 +│   │   │   │   │   ├── t3700 +│   │   │   │   │   ├── t3800 +│   │   │   │   │   ├── t653x -> .././74/tandem653 +│   │   │   │   │   ├── tab -> .././74/tab132 +│   │   │   │   │   ├── tab132 +│   │   │   │   │   ├── tab132-15 -> .././74/tab132 +│   │   │   │   │   ├── tab132-rv +│   │   │   │   │   ├── tab132-w +│   │   │   │   │   ├── tab132-w-rv +│   │   │   │   │   ├── tandem6510 +│   │   │   │   │   ├── tandem653 +│   │   │   │   │   ├── tek +│   │   │   │   │   ├── tek4012 -> .././74/tek +│   │   │   │   │   ├── tek4013 +│   │   │   │   │   ├── tek4014 +│   │   │   │   │   ├── tek4014-sm +│   │   │   │   │   ├── tek4015 +│   │   │   │   │   ├── tek4015-sm +│   │   │   │   │   ├── tek4023 +│   │   │   │   │   ├── tek4024 +│   │   │   │   │   ├── tek4025 -> .././74/tek4024 +│   │   │   │   │   ├── tek4025-17 +│   │   │   │   │   ├── tek4025-17-ws +│   │   │   │   │   ├── tek4025a +│   │   │   │   │   ├── tek4025-cr +│   │   │   │   │   ├── tek4025-ex +│   │   │   │   │   ├── tek4025ex +│   │   │   │   │   ├── tek4027 -> .././74/tek4024 +│   │   │   │   │   ├── tek4027-ex -> .././74/tek4025-ex +│   │   │   │   │   ├── tek4105 +│   │   │   │   │   ├── tek4105-30 +│   │   │   │   │   ├── tek4105a +│   │   │   │   │   ├── tek4106brl +│   │   │   │   │   ├── tek4107 +│   │   │   │   │   ├── tek4107brl -> .././74/tek4106brl +│   │   │   │   │   ├── tek4109 -> .././74/tek4107 +│   │   │   │   │   ├── tek4109brl -> .././74/tek4106brl +│   │   │   │   │   ├── tek4112 +│   │   │   │   │   ├── tek4112-5 +│   │   │   │   │   ├── tek4112-nd +│   │   │   │   │   ├── tek4113 +│   │   │   │   │   ├── tek4113-34 +│   │   │   │   │   ├── tek4113-nd +│   │   │   │   │   ├── tek4114 -> .././74/tek4112 +│   │   │   │   │   ├── tek4115 +│   │   │   │   │   ├── tek4125 +│   │   │   │   │   ├── tek4205 +│   │   │   │   │   ├── tek4207 +│   │   │   │   │   ├── tek4207-s +│   │   │   │   │   ├── tek4404 +│   │   │   │   │   ├── teken +│   │   │   │   │   ├── teken-16color +│   │   │   │   │   ├── teken-2018 +│   │   │   │   │   ├── teken-2022 +│   │   │   │   │   ├── teken-sc +│   │   │   │   │   ├── teken-sc+fkeys +│   │   │   │   │   ├── teken-vt -> .././74/teken +│   │   │   │   │   ├── teken-vt+fkeys +│   │   │   │   │   ├── teleray -> .././74/t1061 +│   │   │   │   │   ├── teletec +│   │   │   │   │   ├── teraterm +│   │   │   │   │   ├── teraterm2.3 +│   │   │   │   │   ├── teraterm-256color +│   │   │   │   │   ├── teraterm4.59 +│   │   │   │   │   ├── teraterm4.97 +│   │   │   │   │   ├── teraterm5.0 +│   │   │   │   │   ├── terminator +│   │   │   │   │   ├── terminet -> .././74/terminet1200 +│   │   │   │   │   ├── terminet1200 +│   │   │   │   │   ├── terminet300 -> .././74/terminet1200 +│   │   │   │   │   ├── terminology +│   │   │   │   │   ├── terminology-0.6.1 +│   │   │   │   │   ├── terminology-1.0.0 +│   │   │   │   │   ├── terminology-1.8.1 +│   │   │   │   │   ├── termite +│   │   │   │   │   ├── tgtelnet -> .././70/pilot +│   │   │   │   │   ├── ti700 +│   │   │   │   │   ├── ti703 +│   │   │   │   │   ├── ti703-w +│   │   │   │   │   ├── ti707 -> .././74/ti703 +│   │   │   │   │   ├── ti707-w -> .././74/ti703-w +│   │   │   │   │   ├── ti733 -> .././74/ti700 +│   │   │   │   │   ├── ti735 -> .././74/ti700 +│   │   │   │   │   ├── ti745 -> .././74/ti700 +│   │   │   │   │   ├── ti800 -> .././74/ti700 +│   │   │   │   │   ├── ti916 +│   │   │   │   │   ├── ti916-132 +│   │   │   │   │   ├── ti916-220-7 -> .././74/ti916 +│   │   │   │   │   ├── ti916-220-8 -> .././74/ti916-8 +│   │   │   │   │   ├── ti916-8 +│   │   │   │   │   ├── ti916-8-132 +│   │   │   │   │   ├── ti924 +│   │   │   │   │   ├── ti924-8 +│   │   │   │   │   ├── ti924-8w +│   │   │   │   │   ├── ti924w +│   │   │   │   │   ├── ti926 +│   │   │   │   │   ├── ti926-8 +│   │   │   │   │   ├── ti928 +│   │   │   │   │   ├── ti928-8 +│   │   │   │   │   ├── ti931 +│   │   │   │   │   ├── ti_ansi +│   │   │   │   │   ├── tkterm -> .././74/tt +│   │   │   │   │   ├── tmux +│   │   │   │   │   ├── tmux-256color +│   │   │   │   │   ├── tmux-direct +│   │   │   │   │   ├── tn1200 -> .././74/terminet1200 +│   │   │   │   │   ├── tn300 -> .././74/terminet1200 +│   │   │   │   │   ├── trs16 +│   │   │   │   │   ├── trs2 +│   │   │   │   │   ├── trs80II -> .././74/trs2 +│   │   │   │   │   ├── trsII -> .././74/trs2 +│   │   │   │   │   ├── ts-1 -> .././66/falco +│   │   │   │   │   ├── ts1 -> .././66/falco +│   │   │   │   │   ├── ts100 +│   │   │   │   │   ├── ts100-ctxt +│   │   │   │   │   ├── ts100-sp -> .././74/ts100 +│   │   │   │   │   ├── ts-1p -> .././66/falco-p +│   │   │   │   │   ├── ts1p -> .././66/falco-p +│   │   │   │   │   ├── tt +│   │   │   │   │   ├── tt52 +│   │   │   │   │   ├── tty33 +│   │   │   │   │   ├── tty35 -> .././74/tty33 +│   │   │   │   │   ├── tty37 +│   │   │   │   │   ├── tty40 +│   │   │   │   │   ├── tty43 +│   │   │   │   │   ├── tty4420 -> .././61/att4420 +│   │   │   │   │   ├── tty4424 -> .././61/att4424 +│   │   │   │   │   ├── tty4424-1 -> .././61/att4424-1 +│   │   │   │   │   ├── tty4424m -> .././61/att4424m +│   │   │   │   │   ├── tty4426 -> .././61/att4426 +│   │   │   │   │   ├── tty5410 -> .././61/att4410 +│   │   │   │   │   ├── tty5410v1 -> .././61/att5410v1 +│   │   │   │   │   ├── tty5410v1-w -> .././61/att4410v1-w +│   │   │   │   │   ├── tty5410-w -> .././61/att5410-w +│   │   │   │   │   ├── tty5420 -> .././61/att4415 +│   │   │   │   │   ├── tty5420+nl -> .././61/att4415+nl +│   │   │   │   │   ├── tty5420-nl -> .././61/att4415-nl +│   │   │   │   │   ├── tty5420-rv -> .././61/att4415-rv +│   │   │   │   │   ├── tty5420-rv-nl -> .././61/att4415-rv-nl +│   │   │   │   │   ├── tty5420-w -> .././61/att4415-w +│   │   │   │   │   ├── tty5420-w-nl -> .././61/att4415-w-nl +│   │   │   │   │   ├── tty5420-w-rv -> .././61/att4415-w-rv +│   │   │   │   │   ├── tty5420-w-rv-n -> .././61/att4415-w-rv-n +│   │   │   │   │   ├── tty5425 -> .././61/att5425 +│   │   │   │   │   ├── tty5425-nl -> .././61/att5425-nl +│   │   │   │   │   ├── tty5425-w -> .././61/att5425-w +│   │   │   │   │   ├── tty5620 -> .././61/att5620 +│   │   │   │   │   ├── tty5620-1 -> .././61/att5620-1 +│   │   │   │   │   ├── tty5620-24 -> .././61/att5620-24 +│   │   │   │   │   ├── tty5620-34 -> .././61/att5620-34 +│   │   │   │   │   ├── tty5620-s -> .././61/att5620-s +│   │   │   │   │   ├── ttydmd -> .././61/att5620 +│   │   │   │   │   ├── tvi803 +│   │   │   │   │   ├── tvi9065 +│   │   │   │   │   ├── tvi910 +│   │   │   │   │   ├── tvi910+ +│   │   │   │   │   ├── tvi912 +│   │   │   │   │   ├── tvi912b +│   │   │   │   │   ├── tvi912b+2p +│   │   │   │   │   ├── tvi912b-2p +│   │   │   │   │   ├── tvi912b-2p-mc +│   │   │   │   │   ├── tvi912b-2p-p +│   │   │   │   │   ├── tvi912b-2p-unk +│   │   │   │   │   ├── tvi912b+dim +│   │   │   │   │   ├── tvi912b+mc +│   │   │   │   │   ├── tvi912b-mc +│   │   │   │   │   ├── tvi912b-mc-2p -> .././74/tvi912b-2p-mc +│   │   │   │   │   ├── tvi912b-mc-vb -> .././74/tvi912b-vb-mc +│   │   │   │   │   ├── tvi912b-p +│   │   │   │   │   ├── tvi912b-p-2p -> .././74/tvi912b-2p-p +│   │   │   │   │   ├── tvi912b+printer +│   │   │   │   │   ├── tvi912b-p-vb -> .././74/tvi912b-vb-p +│   │   │   │   │   ├── tvi912b-unk +│   │   │   │   │   ├── tvi912b-unk-2p -> .././74/tvi912b-2p-unk +│   │   │   │   │   ├── tvi912b-unk-vb -> .././74/tvi912b-vb-unk +│   │   │   │   │   ├── tvi912b+vb +│   │   │   │   │   ├── tvi912b-vb +│   │   │   │   │   ├── tvi912b-vb-mc +│   │   │   │   │   ├── tvi912b-vb-p +│   │   │   │   │   ├── tvi912b-vb-unk +│   │   │   │   │   ├── tvi912c -> .././74/tvi912b +│   │   │   │   │   ├── tvi912c-2p -> .././74/tvi912b-2p +│   │   │   │   │   ├── tvi912c-2p-mc -> .././74/tvi912b-2p-mc +│   │   │   │   │   ├── tvi912c-2p-p -> .././74/tvi912b-2p-p +│   │   │   │   │   ├── tvi912c-2p-unk -> .././74/tvi912b-2p-unk +│   │   │   │   │   ├── tvi912cc +│   │   │   │   │   ├── tvi912c-mc -> .././74/tvi912b-mc +│   │   │   │   │   ├── tvi912c-mc-2p -> .././74/tvi912b-2p-mc +│   │   │   │   │   ├── tvi912c-mc-vb -> .././74/tvi912b-vb-mc +│   │   │   │   │   ├── tvi912c-p -> .././74/tvi912b-p +│   │   │   │   │   ├── tvi912c-p-2p -> .././74/tvi912b-2p-p +│   │   │   │   │   ├── tvi912c-p-vb -> .././74/tvi912b-vb-p +│   │   │   │   │   ├── tvi912c-unk -> .././74/tvi912b-unk +│   │   │   │   │   ├── tvi912c-unk-2p -> .././74/tvi912b-2p-unk +│   │   │   │   │   ├── tvi912c-unk-vb -> .././74/tvi912b-vb-unk +│   │   │   │   │   ├── tvi912c-vb -> .././74/tvi912b-vb +│   │   │   │   │   ├── tvi912c-vb-mc -> .././74/tvi912b-vb-mc +│   │   │   │   │   ├── tvi912c-vb-p -> .././74/tvi912b-vb-p +│   │   │   │   │   ├── tvi912c-vb-unk -> .././74/tvi912b-vb-unk +│   │   │   │   │   ├── tvi914 -> .././74/tvi912 +│   │   │   │   │   ├── tvi920 -> .././74/tvi912 +│   │   │   │   │   ├── tvi920b +│   │   │   │   │   ├── tvi920b-2p +│   │   │   │   │   ├── tvi920b-2p-mc +│   │   │   │   │   ├── tvi920b-2p-p +│   │   │   │   │   ├── tvi920b-2p-unk +│   │   │   │   │   ├── tvi920b+fn +│   │   │   │   │   ├── tvi920b-mc +│   │   │   │   │   ├── tvi920b-mc-2p -> .././74/tvi920b-2p-mc +│   │   │   │   │   ├── tvi920b-mc-vb -> .././74/tvi920b-vb-mc +│   │   │   │   │   ├── tvi920b-p +│   │   │   │   │   ├── tvi920b-p-2p -> .././74/tvi920b-2p-p +│   │   │   │   │   ├── tvi920b-p-vb -> .././74/tvi920b-vb-p +│   │   │   │   │   ├── tvi920b-unk +│   │   │   │   │   ├── tvi920b-unk-2p -> .././74/tvi920b-2p-unk +│   │   │   │   │   ├── tvi920b-unk-vb -> .././74/tvi920b-vb-unk +│   │   │   │   │   ├── tvi920b-vb +│   │   │   │   │   ├── tvi920b-vb-mc +│   │   │   │   │   ├── tvi920b-vb-p +│   │   │   │   │   ├── tvi920b-vb-unk +│   │   │   │   │   ├── tvi920c -> .././74/tvi920b +│   │   │   │   │   ├── tvi920c-2p -> .././74/tvi920b-2p +│   │   │   │   │   ├── tvi920c-2p-mc -> .././74/tvi920b-2p-mc +│   │   │   │   │   ├── tvi920c-2p-p -> .././74/tvi920b-2p-p +│   │   │   │   │   ├── tvi920c-2p-unk -> .././74/tvi920b-2p-unk +│   │   │   │   │   ├── tvi920c-mc -> .././74/tvi920b-mc +│   │   │   │   │   ├── tvi920c-mc-2p -> .././74/tvi920b-2p-mc +│   │   │   │   │   ├── tvi920c-mc-vb -> .././74/tvi920b-vb-mc +│   │   │   │   │   ├── tvi920c-p -> .././74/tvi920b-p +│   │   │   │   │   ├── tvi920c-p-2p -> .././74/tvi920b-2p-p +│   │   │   │   │   ├── tvi920c-p-vb -> .././74/tvi920b-vb-p +│   │   │   │   │   ├── tvi920c-unk -> .././74/tvi920b-unk +│   │   │   │   │   ├── tvi920c-unk-2p -> .././74/tvi920b-2p-unk +│   │   │   │   │   ├── tvi920c-unk-vb -> .././74/tvi920b-vb-unk +│   │   │   │   │   ├── tvi920c-vb -> .././74/tvi920b-vb +│   │   │   │   │   ├── tvi920c-vb-mc -> .././74/tvi920b-vb-mc +│   │   │   │   │   ├── tvi920c-vb-p -> .././74/tvi920b-vb-p +│   │   │   │   │   ├── tvi920c-vb-unk -> .././74/tvi920b-vb-unk +│   │   │   │   │   ├── tvi921 +│   │   │   │   │   ├── tvi924 +│   │   │   │   │   ├── tvi925 +│   │   │   │   │   ├── tvi925-hi +│   │   │   │   │   ├── tvi92B +│   │   │   │   │   ├── tvi92D +│   │   │   │   │   ├── tvi950 +│   │   │   │   │   ├── tvi950-2p +│   │   │   │   │   ├── tvi950-4p +│   │   │   │   │   ├── tvi950-rv +│   │   │   │   │   ├── tvi950-rv-2p +│   │   │   │   │   ├── tvi950-rv-4p +│   │   │   │   │   ├── tvi955 +│   │   │   │   │   ├── tvi955-hb +│   │   │   │   │   ├── tvi955-w +│   │   │   │   │   ├── tvi970 +│   │   │   │   │   ├── tvi970-2p +│   │   │   │   │   ├── tvi970-vb +│   │   │   │   │   ├── tvipt +│   │   │   │   │   ├── tw100 +│   │   │   │   │   ├── tw52 +│   │   │   │   │   ├── tw52-color -> .././74/tw52 +│   │   │   │   │   ├── tw52-m +│   │   │   │   │   ├── tws2102-sna +│   │   │   │   │   ├── tws2103 +│   │   │   │   │   ├── tws2103-sna +│   │   │   │   │   └── tws-generic +│   │   │   │   ├── 75 +│   │   │   │   │   ├── ultima2 -> .././69/ims-ansi +│   │   │   │   │   ├── ultimaII -> .././69/ims-ansi +│   │   │   │   │   ├── uniterm +│   │   │   │   │   ├── uniterm49 -> .././75/uniterm +│   │   │   │   │   ├── unixpc -> .././61/att7300 +│   │   │   │   │   ├── unknown +│   │   │   │   │   ├── uts30 +│   │   │   │   │   └── uwin +│   │   │   │   ├── 76 +│   │   │   │   │   ├── v200-nam -> .././76/vt220-nam +│   │   │   │   │   ├── v320n -> .././76/vt320nam +│   │   │   │   │   ├── v3220 +│   │   │   │   │   ├── v5410 +│   │   │   │   │   ├── vanilla +│   │   │   │   │   ├── vapple -> .././61/apple-videx3 +│   │   │   │   │   ├── vc103 -> .././76/vc303 +│   │   │   │   │   ├── vc203 -> .././76/vc303 +│   │   │   │   │   ├── vc303 +│   │   │   │   │   ├── vc303a +│   │   │   │   │   ├── vc403a -> .././76/vc303a +│   │   │   │   │   ├── vc404 +│   │   │   │   │   ├── vc404-s +│   │   │   │   │   ├── vc414 +│   │   │   │   │   ├── vc414h -> .././76/vc414 +│   │   │   │   │   ├── vc415 +│   │   │   │   │   ├── venix -> .././70/pc-venix +│   │   │   │   │   ├── versaterm +│   │   │   │   │   ├── vi200 +│   │   │   │   │   ├── vi200-f +│   │   │   │   │   ├── vi200-rv +│   │   │   │   │   ├── vi300 +│   │   │   │   │   ├── vi300-old +│   │   │   │   │   ├── vi50 +│   │   │   │   │   ├── vi500 +│   │   │   │   │   ├── vi50adm +│   │   │   │   │   ├── vi55 +│   │   │   │   │   ├── vi550 +│   │   │   │   │   ├── vi603 +│   │   │   │   │   ├── viewdata +│   │   │   │   │   ├── viewdata-o +│   │   │   │   │   ├── viewdata-rv +│   │   │   │   │   ├── viewpoint +│   │   │   │   │   ├── viewpoint3a+ -> .././76/vp3a+ +│   │   │   │   │   ├── viewpoint60 -> .././76/vp60 +│   │   │   │   │   ├── viewpoint90 -> .././76/vp90 +│   │   │   │   │   ├── vip +│   │   │   │   │   ├── vip7800-H -> .././76/vip-H +│   │   │   │   │   ├── vip7800-Hw -> .././76/vip-Hw +│   │   │   │   │   ├── vip7800-w -> .././76/vip-w +│   │   │   │   │   ├── vip-H +│   │   │   │   │   ├── vip-Hw +│   │   │   │   │   ├── vip-w +│   │   │   │   │   ├── visa50 +│   │   │   │   │   ├── visual603 -> .././76/vi603 +│   │   │   │   │   ├── vitty -> .././61/att5620-s +│   │   │   │   │   ├── vk100 -> .././67/gigi +│   │   │   │   │   ├── vp3a+ +│   │   │   │   │   ├── vp60 +│   │   │   │   │   ├── vp90 +│   │   │   │   │   ├── vremote +│   │   │   │   │   ├── vs100 -> .././78/xterm-24 +│   │   │   │   │   ├── vs100-x10 -> .././78/x10term +│   │   │   │   │   ├── vsc +│   │   │   │   │   ├── vscode +│   │   │   │   │   ├── vscode-direct +│   │   │   │   │   ├── vt100 +│   │   │   │   │   ├── vt100+ -> .././6d/ms-vt100+ +│   │   │   │   │   ├── vt100+4bsd +│   │   │   │   │   ├── vt100-am -> .././76/vt100 +│   │   │   │   │   ├── vt100-bm -> .././6e/nwp512 +│   │   │   │   │   ├── vt100-bm-o -> .././6e/nwp512 +│   │   │   │   │   ├── vt100-bot-s -> .././76/vt100-s-bot +│   │   │   │   │   ├── vt100+enq +│   │   │   │   │   ├── vt100+fnkeys +│   │   │   │   │   ├── vt100+keypad +│   │   │   │   │   ├── vt100-nam -> .././76/vt100nam +│   │   │   │   │   ├── vt100nam +│   │   │   │   │   ├── vt100-nam-w -> .././76/vt100-w-nam +│   │   │   │   │   ├── vt100-nav +│   │   │   │   │   ├── vt100-nav-w +│   │   │   │   │   ├── vt100+noapp +│   │   │   │   │   ├── vt100+noapp+pc +│   │   │   │   │   ├── vt100+pf1-pf4 +│   │   │   │   │   ├── vt100+pfkeys +│   │   │   │   │   ├── vt100-putty +│   │   │   │   │   ├── vt100-s +│   │   │   │   │   ├── vt100-s-bot +│   │   │   │   │   ├── vt100-s-top -> .././76/vt100-s +│   │   │   │   │   ├── vt100-top-s -> .././76/vt100-s +│   │   │   │   │   ├── vt100-vb +│   │   │   │   │   ├── vt100-w +│   │   │   │   │   ├── vt100-w-am -> .././76/vt100-w +│   │   │   │   │   ├── vt100-w-nam +│   │   │   │   │   ├── vt100-w-nav -> .././76/vt100-nav-w +│   │   │   │   │   ├── vt102 +│   │   │   │   │   ├── vt102+enq +│   │   │   │   │   ├── vt102-nsgr +│   │   │   │   │   ├── vt102-w +│   │   │   │   │   ├── vt125 +│   │   │   │   │   ├── vt131 +│   │   │   │   │   ├── vt132 +│   │   │   │   │   ├── vt200 -> .././76/vt220 +│   │   │   │   │   ├── vt200-8 -> .././76/vt220-8bit +│   │   │   │   │   ├── vt200-8bit -> .././76/vt220-8bit +│   │   │   │   │   ├── vt200-js +│   │   │   │   │   ├── vt200-old -> .././76/vt220-old +│   │   │   │   │   ├── vt200-w -> .././76/vt220-w +│   │   │   │   │   ├── vt220 +│   │   │   │   │   ├── vt220-8 -> .././76/vt220-8bit +│   │   │   │   │   ├── vt220-8bit +│   │   │   │   │   ├── vt220-base +│   │   │   │   │   ├── vt220+cvis +│   │   │   │   │   ├── vt220+cvis8 +│   │   │   │   │   ├── vt220d +│   │   │   │   │   ├── vt220-js -> .././76/vt200-js +│   │   │   │   │   ├── vt220+keypad +│   │   │   │   │   ├── vt220-nam +│   │   │   │   │   ├── vt220-old +│   │   │   │   │   ├── vt220+pcedit +│   │   │   │   │   ├── vt220+sfkeys +│   │   │   │   │   ├── vt220+ufkeys +│   │   │   │   │   ├── vt220+vtedit +│   │   │   │   │   ├── vt220-w +│   │   │   │   │   ├── vt300 -> .././76/vt320 +│   │   │   │   │   ├── vt300-nam -> .././76/vt320-nam +│   │   │   │   │   ├── vt300-w -> .././76/vt320-w +│   │   │   │   │   ├── vt300-w-nam -> .././76/vt320-w-nam +│   │   │   │   │   ├── vt320 +│   │   │   │   │   ├── vt320-k3 +│   │   │   │   │   ├── vt320-k311 +│   │   │   │   │   ├── vt320-nam +│   │   │   │   │   ├── vt320nam +│   │   │   │   │   ├── vt320-w +│   │   │   │   │   ├── vt320-w-nam +│   │   │   │   │   ├── vt330 -> .././76/vt340 +│   │   │   │   │   ├── vt340 +│   │   │   │   │   ├── vt400 +│   │   │   │   │   ├── vt400-24 -> .././76/vt400 +│   │   │   │   │   ├── vt420 +│   │   │   │   │   ├── vt420f +│   │   │   │   │   ├── vt420+lrmm +│   │   │   │   │   ├── vt420pc +│   │   │   │   │   ├── vt420pcdos +│   │   │   │   │   ├── vt50 +│   │   │   │   │   ├── vt50h +│   │   │   │   │   ├── vt510 +│   │   │   │   │   ├── vt510pc +│   │   │   │   │   ├── vt510pcdos +│   │   │   │   │   ├── vt52 +│   │   │   │   │   ├── vt520 +│   │   │   │   │   ├── vt520ansi +│   │   │   │   │   ├── vt520-w +│   │   │   │   │   ├── vt525 +│   │   │   │   │   ├── vt525-w +│   │   │   │   │   ├── vt52+arrows +│   │   │   │   │   ├── vt52-basic +│   │   │   │   │   ├── vt52+keypad +│   │   │   │   │   ├── vt-61 -> .././76/vt61 +│   │   │   │   │   ├── vt61 +│   │   │   │   │   ├── vt61.5 -> .././76/vt61 +│   │   │   │   │   ├── vte +│   │   │   │   │   ├── vte-2007 +│   │   │   │   │   ├── vte-2008 +│   │   │   │   │   ├── vte-2012 +│   │   │   │   │   ├── vte-2014 +│   │   │   │   │   ├── vte-2017 +│   │   │   │   │   ├── vte-2018 +│   │   │   │   │   ├── vte-2022 +│   │   │   │   │   ├── vte-256color +│   │   │   │   │   ├── vte-direct +│   │   │   │   │   ├── vte+pcfkeys +│   │   │   │   │   ├── vtnt -> .././6d/ms-vt100-color +│   │   │   │   │   ├── vt-utf8 -> .././6d/ms-vt-utf8 +│   │   │   │   │   ├── vv100 -> .././6d/mvterm +│   │   │   │   │   └── vwmterm +│   │   │   │   ├── 77 +│   │   │   │   │   ├── wezterm +│   │   │   │   │   ├── winconsole +│   │   │   │   │   ├── wren -> .././70/pt100 +│   │   │   │   │   ├── wrenw -> .././70/pt100w +│   │   │   │   │   ├── wsiris +│   │   │   │   │   ├── wsvt25 +│   │   │   │   │   ├── wsvt25m +│   │   │   │   │   ├── wy100 +│   │   │   │   │   ├── wy100q +│   │   │   │   │   ├── wy120 +│   │   │   │   │   ├── wy120-25 +│   │   │   │   │   ├── wy120-25-w +│   │   │   │   │   ├── wy120-vb +│   │   │   │   │   ├── wy120-w +│   │   │   │   │   ├── wy120-w-vb +│   │   │   │   │   ├── wy120-wvb -> .././77/wy120-w-vb +│   │   │   │   │   ├── wy150 -> .././77/wy120 +│   │   │   │   │   ├── wy150-25 -> .././77/wy120-25 +│   │   │   │   │   ├── wy150-25-w -> .././77/wy120-25-w +│   │   │   │   │   ├── wy150-vb -> .././77/wy120-vb +│   │   │   │   │   ├── wy150-w -> .././77/wy120-w +│   │   │   │   │   ├── wy150-w-vb -> .././77/wy120-w-vb +│   │   │   │   │   ├── wy160 +│   │   │   │   │   ├── wy160-25 +│   │   │   │   │   ├── wy160-25-w +│   │   │   │   │   ├── wy160-42 +│   │   │   │   │   ├── wy160-42-w +│   │   │   │   │   ├── wy160-43 +│   │   │   │   │   ├── wy160-43-w +│   │   │   │   │   ├── wy160-tek +│   │   │   │   │   ├── wy160-vb +│   │   │   │   │   ├── wy160-w +│   │   │   │   │   ├── wy160-w-vb +│   │   │   │   │   ├── wy160-wvb -> .././77/wy160-w-vb +│   │   │   │   │   ├── wy185 +│   │   │   │   │   ├── wy185-24 +│   │   │   │   │   ├── wy185-vb +│   │   │   │   │   ├── wy185-w +│   │   │   │   │   ├── wy185-wvb +│   │   │   │   │   ├── wy30 +│   │   │   │   │   ├── wy30-mc +│   │   │   │   │   ├── wy30-vb +│   │   │   │   │   ├── wy325 +│   │   │   │   │   ├── wy325-25 +│   │   │   │   │   ├── wy325-25w +│   │   │   │   │   ├── wy325-42 +│   │   │   │   │   ├── wy325-42w +│   │   │   │   │   ├── wy325-42w-vb +│   │   │   │   │   ├── wy325-42wvb -> .././77/wy325-42w-vb +│   │   │   │   │   ├── wy325-43 +│   │   │   │   │   ├── wy325-43w +│   │   │   │   │   ├── wy325-43w-vb +│   │   │   │   │   ├── wy325-43wvb -> .././77/wy325-43w-vb +│   │   │   │   │   ├── wy325-80 -> .././77/wy325-25 +│   │   │   │   │   ├── wy325-vb +│   │   │   │   │   ├── wy325-w +│   │   │   │   │   ├── wy325w-24 -> .././77/wy325-w +│   │   │   │   │   ├── wy325-w-vb +│   │   │   │   │   ├── wy325-wvb -> .././77/wy325-w-vb +│   │   │   │   │   ├── wy350 +│   │   │   │   │   ├── wy350-vb +│   │   │   │   │   ├── wy350-w +│   │   │   │   │   ├── wy350-wvb +│   │   │   │   │   ├── wy370 +│   │   │   │   │   ├── wy370-101k -> .././77/wy370 +│   │   │   │   │   ├── wy370-105k +│   │   │   │   │   ├── wy370-EPC +│   │   │   │   │   ├── wy370-nk +│   │   │   │   │   ├── wy370-rv +│   │   │   │   │   ├── wy370-tek +│   │   │   │   │   ├── wy370-vb +│   │   │   │   │   ├── wy370-w +│   │   │   │   │   ├── wy370-wvb +│   │   │   │   │   ├── wy50 +│   │   │   │   │   ├── wy50-mc +│   │   │   │   │   ├── wy50-vb +│   │   │   │   │   ├── wy50-w +│   │   │   │   │   ├── wy50-wvb +│   │   │   │   │   ├── wy520 +│   │   │   │   │   ├── wy520-24 +│   │   │   │   │   ├── wy520-36 +│   │   │   │   │   ├── wy520-36pc +│   │   │   │   │   ├── wy520-36w +│   │   │   │   │   ├── wy520-36wpc +│   │   │   │   │   ├── wy520-48 +│   │   │   │   │   ├── wy520-48pc +│   │   │   │   │   ├── wy520-48w +│   │   │   │   │   ├── wy520-48wpc +│   │   │   │   │   ├── wy520-epc +│   │   │   │   │   ├── wy520-epc-24 +│   │   │   │   │   ├── wy520-epc-vb +│   │   │   │   │   ├── wy520-epc-w +│   │   │   │   │   ├── wy520-epc-wvb +│   │   │   │   │   ├── wy520-vb +│   │   │   │   │   ├── wy520-w +│   │   │   │   │   ├── wy520-wvb +│   │   │   │   │   ├── wy60 +│   │   │   │   │   ├── wy60-25 +│   │   │   │   │   ├── wy60-25-w +│   │   │   │   │   ├── wy60-316X -> .././69/ibm3161 +│   │   │   │   │   ├── wy60-42 +│   │   │   │   │   ├── wy60-42-w +│   │   │   │   │   ├── wy60-43 +│   │   │   │   │   ├── wy60-43-w +│   │   │   │   │   ├── wy60-AT -> .././69/ibm5151 +│   │   │   │   │   ├── wy60-PC -> .././69/ibmpc +│   │   │   │   │   ├── wy60-vb +│   │   │   │   │   ├── wy60-w +│   │   │   │   │   ├── wy60-w-vb +│   │   │   │   │   ├── wy60-wvb -> .././77/wy60-w-vb +│   │   │   │   │   ├── wy75 +│   │   │   │   │   ├── wy-75ap -> .././77/wy75ap +│   │   │   │   │   ├── wy75ap +│   │   │   │   │   ├── wy75-mc +│   │   │   │   │   ├── wy75-vb +│   │   │   │   │   ├── wy75-w +│   │   │   │   │   ├── wy75-wvb +│   │   │   │   │   ├── wy85 +│   │   │   │   │   ├── wy85-8bit +│   │   │   │   │   ├── wy85-vb +│   │   │   │   │   ├── wy85-w +│   │   │   │   │   ├── wy85-wvb +│   │   │   │   │   ├── wy99a-ansi +│   │   │   │   │   ├── wy99-ansi +│   │   │   │   │   ├── wy99f +│   │   │   │   │   ├── wy99fa +│   │   │   │   │   ├── wy-99fgt -> .././77/wy99f +│   │   │   │   │   ├── wy99fgt -> .././77/wy99f +│   │   │   │   │   ├── wy-99fgta -> .././77/wy99fa +│   │   │   │   │   ├── wy99fgta -> .././77/wy99fa +│   │   │   │   │   ├── wy99gt +│   │   │   │   │   ├── wy99gt-25 +│   │   │   │   │   ├── wy99gt-25-w +│   │   │   │   │   ├── wy99gt-tek +│   │   │   │   │   ├── wy99gt-vb +│   │   │   │   │   ├── wy99gt-w +│   │   │   │   │   ├── wy99gt-w-vb +│   │   │   │   │   ├── wy99gt-wvb -> .././77/wy99gt-w-vb +│   │   │   │   │   ├── wyse120 -> .././77/wy120 +│   │   │   │   │   ├── wyse120-25 -> .././77/wy120-25 +│   │   │   │   │   ├── wyse120-25-w -> .././77/wy120-25-w +│   │   │   │   │   ├── wyse120-vb -> .././77/wy120-vb +│   │   │   │   │   ├── wyse120-w -> .././77/wy120-w +│   │   │   │   │   ├── wyse120-wvb -> .././77/wy120-w-vb +│   │   │   │   │   ├── wyse150 -> .././77/wy120 +│   │   │   │   │   ├── wyse150-25 -> .././77/wy120-25 +│   │   │   │   │   ├── wyse150-25-w -> .././77/wy120-25-w +│   │   │   │   │   ├── wyse150-vb -> .././77/wy120-vb +│   │   │   │   │   ├── wyse150-w -> .././77/wy120-w +│   │   │   │   │   ├── wyse150-w-vb -> .././77/wy120-w-vb +│   │   │   │   │   ├── wyse160 -> .././77/wy160 +│   │   │   │   │   ├── wyse160-25 -> .././77/wy160-25 +│   │   │   │   │   ├── wyse160-25-w -> .././77/wy160-25-w +│   │   │   │   │   ├── wyse160-42 -> .././77/wy160-42 +│   │   │   │   │   ├── wyse160-42-w -> .././77/wy160-42-w +│   │   │   │   │   ├── wyse160-43 -> .././77/wy160-43 +│   │   │   │   │   ├── wyse160-43-w -> .././77/wy160-43-w +│   │   │   │   │   ├── wyse160-vb -> .././77/wy160-vb +│   │   │   │   │   ├── wyse160-w -> .././77/wy160-w +│   │   │   │   │   ├── wyse160-wvb -> .././77/wy160-w-vb +│   │   │   │   │   ├── wyse185 -> .././77/wy185 +│   │   │   │   │   ├── wyse185-24 -> .././77/wy185-24 +│   │   │   │   │   ├── wyse185-vb -> .././77/wy185-vb +│   │   │   │   │   ├── wyse185-w -> .././77/wy185-w +│   │   │   │   │   ├── wyse185-wvb -> .././77/wy185-wvb +│   │   │   │   │   ├── wyse30 -> .././77/wy30 +│   │   │   │   │   ├── wyse30-mc -> .././77/wy30-mc +│   │   │   │   │   ├── wyse30-vb -> .././77/wy30-vb +│   │   │   │   │   ├── wyse-325 -> .././77/wy325-25 +│   │   │   │   │   ├── wyse325 -> .././77/wy325 +│   │   │   │   │   ├── wyse325-25 -> .././77/wy325-25 +│   │   │   │   │   ├── wyse325-25w -> .././77/wy325-25w +│   │   │   │   │   ├── wyse325-42 -> .././77/wy325-42 +│   │   │   │   │   ├── wyse325-42w -> .././77/wy325-42w +│   │   │   │   │   ├── wyse325-43 -> .././77/wy325-43 +│   │   │   │   │   ├── wyse325-43w -> .././77/wy325-43w +│   │   │   │   │   ├── wyse325-vb -> .././77/wy325-vb +│   │   │   │   │   ├── wyse325-w -> .././77/wy325-w +│   │   │   │   │   ├── wyse325-wvb -> .././77/wy325-w-vb +│   │   │   │   │   ├── wyse350 -> .././77/wy350 +│   │   │   │   │   ├── wyse350-vb -> .././77/wy350-vb +│   │   │   │   │   ├── wyse350-w -> .././77/wy350-w +│   │   │   │   │   ├── wyse350-wvb -> .././77/wy350-wvb +│   │   │   │   │   ├── wyse370 -> .././77/wy370 +│   │   │   │   │   ├── wyse50 -> .././77/wy50 +│   │   │   │   │   ├── wyse50-mc -> .././77/wy50-mc +│   │   │   │   │   ├── wyse50-vb -> .././77/wy50-vb +│   │   │   │   │   ├── wyse50-w -> .././77/wy50-w +│   │   │   │   │   ├── wyse50-wvb -> .././77/wy50-wvb +│   │   │   │   │   ├── wyse520 -> .././77/wy520 +│   │   │   │   │   ├── wyse520-24 -> .././77/wy520-24 +│   │   │   │   │   ├── wyse520-36 -> .././77/wy520-36 +│   │   │   │   │   ├── wyse520-36pc -> .././77/wy520-36pc +│   │   │   │   │   ├── wyse520-36w -> .././77/wy520-36w +│   │   │   │   │   ├── wyse520-36wpc -> .././77/wy520-36wpc +│   │   │   │   │   ├── wyse520-48 -> .././77/wy520-48 +│   │   │   │   │   ├── wyse520-48pc -> .././77/wy520-48pc +│   │   │   │   │   ├── wyse520-48w -> .././77/wy520-48w +│   │   │   │   │   ├── wyse520-48wpc -> .././77/wy520-48wpc +│   │   │   │   │   ├── wyse520-epc -> .././77/wy520-epc +│   │   │   │   │   ├── wyse520-epc-w -> .././77/wy520-epc-w +│   │   │   │   │   ├── wyse520-pc-24 -> .././77/wy520-epc-24 +│   │   │   │   │   ├── wyse520-pc-vb -> .././77/wy520-epc-vb +│   │   │   │   │   ├── wyse520-p-wvb -> .././77/wy520-epc-wvb +│   │   │   │   │   ├── wyse520-vb -> .././77/wy520-vb +│   │   │   │   │   ├── wyse520-w -> .././77/wy520-w +│   │   │   │   │   ├── wyse520-wvb -> .././77/wy520-wvb +│   │   │   │   │   ├── wyse60 -> .././77/wy60 +│   │   │   │   │   ├── wyse60-25 -> .././77/wy60-25 +│   │   │   │   │   ├── wyse60-25-w -> .././77/wy60-25-w +│   │   │   │   │   ├── wyse60-316X -> .././69/ibm3161 +│   │   │   │   │   ├── wyse60-42 -> .././77/wy60-42 +│   │   │   │   │   ├── wyse60-42-w -> .././77/wy60-42-w +│   │   │   │   │   ├── wyse60-43 -> .././77/wy60-43 +│   │   │   │   │   ├── wyse60-43-w -> .././77/wy60-43-w +│   │   │   │   │   ├── wyse60-AT -> .././69/ibm5151 +│   │   │   │   │   ├── wyse60-PC -> .././69/ibmpc +│   │   │   │   │   ├── wyse60-vb -> .././77/wy60-vb +│   │   │   │   │   ├── wyse60-w -> .././77/wy60-w +│   │   │   │   │   ├── wyse60-wvb -> .././77/wy60-w-vb +│   │   │   │   │   ├── wyse75 -> .././77/wy75 +│   │   │   │   │   ├── wyse-75ap -> .././77/wy75ap +│   │   │   │   │   ├── wyse75ap -> .././77/wy75ap +│   │   │   │   │   ├── wyse75-mc -> .././77/wy75-mc +│   │   │   │   │   ├── wyse75-vb -> .././77/wy75-vb +│   │   │   │   │   ├── wyse75-w -> .././77/wy75-w +│   │   │   │   │   ├── wyse75-wvb -> .././77/wy75-wvb +│   │   │   │   │   ├── wyse85 -> .././77/wy85 +│   │   │   │   │   ├── wyse85-8bit -> .././77/wy85-8bit +│   │   │   │   │   ├── wyse85-vb -> .././77/wy85-vb +│   │   │   │   │   ├── wyse85-w -> .././77/wy85-w +│   │   │   │   │   ├── wyse85-wvb -> .././77/wy85-wvb +│   │   │   │   │   ├── wyse99gt -> .././77/wy99gt +│   │   │   │   │   ├── wyse99gt-25 -> .././77/wy99gt-25 +│   │   │   │   │   ├── wyse99gt-25-w -> .././77/wy99gt-25-w +│   │   │   │   │   ├── wyse99gt-vb -> .././77/wy99gt-vb +│   │   │   │   │   ├── wyse99gt-w -> .././77/wy99gt-w +│   │   │   │   │   ├── wyse99gt-wvb -> .././77/wy99gt-w-vb +│   │   │   │   │   ├── wyse+cvis +│   │   │   │   │   ├── wyse+sl +│   │   │   │   │   └── wyse-vp +│   │   │   │   ├── 78 +│   │   │   │   │   ├── x10term +│   │   │   │   │   ├── x10term+sl +│   │   │   │   │   ├── x1700 -> .././64/diablo1640 +│   │   │   │   │   ├── x1700-lm -> .././64/diablo1740-lm +│   │   │   │   │   ├── x1720 -> .././78/xerox1720 +│   │   │   │   │   ├── x1750 -> .././78/xerox1720 +│   │   │   │   │   ├── x68k +│   │   │   │   │   ├── x68k-ite -> .././78/x68k +│   │   │   │   │   ├── x820 -> .././78/xerox820 +│   │   │   │   │   ├── xdku -> .././74/tws2103 +│   │   │   │   │   ├── xenix -> .././69/ibmpcx +│   │   │   │   │   ├── xerox -> .././64/diablo1640 +│   │   │   │   │   ├── xerox1720 +│   │   │   │   │   ├── xerox820 +│   │   │   │   │   ├── xerox-lm -> .././64/diablo1640-lm +│   │   │   │   │   ├── xfce +│   │   │   │   │   ├── xgterm +│   │   │   │   │   ├── xiterm +│   │   │   │   │   ├── xl83 -> .././63/cyb83 +│   │   │   │   │   ├── xnuppc +│   │   │   │   │   ├── xnuppc+100x37 +│   │   │   │   │   ├── xnuppc-100x37 +│   │   │   │   │   ├── xnuppc-100x37-m +│   │   │   │   │   ├── xnuppc+112x37 +│   │   │   │   │   ├── xnuppc-112x37 +│   │   │   │   │   ├── xnuppc-112x37-m +│   │   │   │   │   ├── xnuppc+128x40 +│   │   │   │   │   ├── xnuppc-128x40 +│   │   │   │   │   ├── xnuppc-128x40-m +│   │   │   │   │   ├── xnuppc+128x48 +│   │   │   │   │   ├── xnuppc-128x48 +│   │   │   │   │   ├── xnuppc-128x48-m +│   │   │   │   │   ├── xnuppc+144x48 +│   │   │   │   │   ├── xnuppc-144x48 +│   │   │   │   │   ├── xnuppc-144x48-m +│   │   │   │   │   ├── xnuppc+160x64 +│   │   │   │   │   ├── xnuppc-160x64 +│   │   │   │   │   ├── xnuppc-160x64-m +│   │   │   │   │   ├── xnuppc+200x64 +│   │   │   │   │   ├── xnuppc-200x64 +│   │   │   │   │   ├── xnuppc-200x64-m +│   │   │   │   │   ├── xnuppc+200x75 +│   │   │   │   │   ├── xnuppc-200x75 +│   │   │   │   │   ├── xnuppc-200x75-m +│   │   │   │   │   ├── xnuppc+256x96 +│   │   │   │   │   ├── xnuppc-256x96 +│   │   │   │   │   ├── xnuppc-256x96-m +│   │   │   │   │   ├── xnuppc+80x25 +│   │   │   │   │   ├── xnuppc-80x25 +│   │   │   │   │   ├── xnuppc-80x25-m +│   │   │   │   │   ├── xnuppc+80x30 +│   │   │   │   │   ├── xnuppc-80x30 +│   │   │   │   │   ├── xnuppc-80x30-m +│   │   │   │   │   ├── xnuppc+90x30 +│   │   │   │   │   ├── xnuppc-90x30 +│   │   │   │   │   ├── xnuppc-90x30-m +│   │   │   │   │   ├── xnuppc+b +│   │   │   │   │   ├── xnuppc-b +│   │   │   │   │   ├── xnuppc+basic +│   │   │   │   │   ├── xnuppc+c +│   │   │   │   │   ├── xnuppc+f +│   │   │   │   │   ├── xnuppc-f +│   │   │   │   │   ├── xnuppc+f2 +│   │   │   │   │   ├── xnuppc-f2 +│   │   │   │   │   ├── xnuppc-m +│   │   │   │   │   ├── xnuppc-m-b +│   │   │   │   │   ├── xnuppc-m-f +│   │   │   │   │   ├── xnuppc-m-f2 +│   │   │   │   │   ├── xtalk +│   │   │   │   │   ├── xterm +│   │   │   │   │   ├── xterm1 +│   │   │   │   │   ├── xterm-1002 +│   │   │   │   │   ├── xterm-1003 +│   │   │   │   │   ├── xterm-1005 +│   │   │   │   │   ├── xterm-1006 +│   │   │   │   │   ├── xterm-16color +│   │   │   │   │   ├── xterm-24 +│   │   │   │   │   ├── xterm+256color +│   │   │   │   │   ├── xterm-256color +│   │   │   │   │   ├── xterm+256color2 +│   │   │   │   │   ├── xterm+256setaf +│   │   │   │   │   ├── xterm+256setaf2 +│   │   │   │   │   ├── xterm+88color +│   │   │   │   │   ├── xterm-88color +│   │   │   │   │   ├── xterm+88color2 +│   │   │   │   │   ├── xterm-8bit +│   │   │   │   │   ├── xterm+acs +│   │   │   │   │   ├── xterm+alt1049 +│   │   │   │   │   ├── xterm+alt47 +│   │   │   │   │   ├── xterm+alt+title +│   │   │   │   │   ├── xterm+app +│   │   │   │   │   ├── xterm+app+pc +│   │   │   │   │   ├── xterm-basic +│   │   │   │   │   ├── xterm-bold +│   │   │   │   │   ├── xtermc +│   │   │   │   │   ├── xterm-color +│   │   │   │   │   ├── xterm+decedit +│   │   │   │   │   ├── xterm+direct +│   │   │   │   │   ├── xterm-direct +│   │   │   │   │   ├── xterm+direct16 +│   │   │   │   │   ├── xterm-direct16 +│   │   │   │   │   ├── xterm+direct2 +│   │   │   │   │   ├── xterm-direct2 +│   │   │   │   │   ├── xterm+direct256 +│   │   │   │   │   ├── xterm-direct256 +│   │   │   │   │   ├── xterm+edit +│   │   │   │   │   ├── xterm+focus +│   │   │   │   │   ├── xterm-hp +│   │   │   │   │   ├── xterm+indirect +│   │   │   │   │   ├── xterm.js -> .././76/vscode +│   │   │   │   │   ├── xterm+kbs +│   │   │   │   │   ├── xterm+keypad +│   │   │   │   │   ├── xtermm +│   │   │   │   │   ├── xterm+meta +│   │   │   │   │   ├── xterm-mono +│   │   │   │   │   ├── xterm-new +│   │   │   │   │   ├── xterm-nic +│   │   │   │   │   ├── xterm+noalt +│   │   │   │   │   ├── xterm+noapp +│   │   │   │   │   ├── xterm-noapp +│   │   │   │   │   ├── xterm+nofkeys +│   │   │   │   │   ├── xterm+nopcfkeys +│   │   │   │   │   ├── xterm-old +│   │   │   │   │   ├── xterm+osc104 +│   │   │   │   │   ├── xterm-p370 +│   │   │   │   │   ├── xterm-p371 +│   │   │   │   │   ├── xterm+pcc0 +│   │   │   │   │   ├── xterm+pcc1 +│   │   │   │   │   ├── xterm+pcc2 +│   │   │   │   │   ├── xterm+pcc3 +│   │   │   │   │   ├── xterm+pce2 +│   │   │   │   │   ├── xterm+pc+edit +│   │   │   │   │   ├── xterm+pcf0 +│   │   │   │   │   ├── xterm+pcf2 +│   │   │   │   │   ├── xterm+pcfkeys +│   │   │   │   │   ├── xterm-pcolor +│   │   │   │   │   ├── xterm-r5 +│   │   │   │   │   ├── xterm+r5+fkeys +│   │   │   │   │   ├── xterm+r5+lockeys +│   │   │   │   │   ├── xterm-r6 +│   │   │   │   │   ├── xterm+r6f2 +│   │   │   │   │   ├── xterms -> .././78/xterm-24 +│   │   │   │   │   ├── xterm-sco +│   │   │   │   │   ├── xterm+sl +│   │   │   │   │   ├── xterm+sl-alt +│   │   │   │   │   ├── xterm+sl-twm +│   │   │   │   │   ├── xterm+sm+1002 +│   │   │   │   │   ├── xterm+sm+1003 +│   │   │   │   │   ├── xterm+sm+1005 +│   │   │   │   │   ├── xterm+sm+1006 +│   │   │   │   │   ├── xterms-sun +│   │   │   │   │   ├── xterm-sun +│   │   │   │   │   ├── xterm+titlestack +│   │   │   │   │   ├── xterm+tmux +│   │   │   │   │   ├── xterm+tmux2 +│   │   │   │   │   ├── xterm-utf8 +│   │   │   │   │   ├── xterm-vt220 +│   │   │   │   │   ├── xterm-vt52 +│   │   │   │   │   ├── xterm+vt+edit +│   │   │   │   │   ├── xterm+x10mouse +│   │   │   │   │   ├── xterm-x10mouse +│   │   │   │   │   ├── xterm+x11hilite +│   │   │   │   │   ├── xterm-x11hilite +│   │   │   │   │   ├── xterm+x11mouse +│   │   │   │   │   ├── xterm-x11mouse +│   │   │   │   │   ├── xterm-xf86-v32 +│   │   │   │   │   ├── xterm-xf86-v33 +│   │   │   │   │   ├── xterm-xf86-v333 +│   │   │   │   │   ├── xterm-xf86-v40 +│   │   │   │   │   ├── xterm-xf86-v43 +│   │   │   │   │   ├── xterm-xf86-v44 +│   │   │   │   │   ├── xterm-xfree86 +│   │   │   │   │   ├── xterm-xi +│   │   │   │   │   └── xwsh -> .././69/iris-color +│   │   │   │   └── 7a +│   │   │   │   ├── z-100 -> .././7a/z100 +│   │   │   │   ├── z100 +│   │   │   │   ├── z-100bw -> .././7a/z100bw +│   │   │   │   ├── z100bw +│   │   │   │   ├── z110 -> .././7a/z100 +│   │   │   │   ├── z110bw -> .././7a/z100bw +│   │   │   │   ├── z19 -> .././68/h19 +│   │   │   │   ├── z29 +│   │   │   │   ├── z29a +│   │   │   │   ├── z29a-kc-bc -> .././7a/z29a +│   │   │   │   ├── z29a-kc-uc +│   │   │   │   ├── z29a-nkc-bc +│   │   │   │   ├── z29a-nkc-uc +│   │   │   │   ├── z29b -> .././7a/z29 +│   │   │   │   ├── z30 -> .././7a/zen30 +│   │   │   │   ├── z340 +│   │   │   │   ├── z340-nam +│   │   │   │   ├── z39-a +│   │   │   │   ├── z39a -> .././7a/z39-a +│   │   │   │   ├── z50 -> .././7a/zen50 +│   │   │   │   ├── z8001 -> .././63/cci +│   │   │   │   ├── zen30 +│   │   │   │   ├── zen50 +│   │   │   │   ├── zen8001 -> .././63/cci +│   │   │   │   ├── zenith -> .././68/h19 +│   │   │   │   ├── zenith29 -> .././7a/z29 +│   │   │   │   ├── zenith39-a -> .././7a/z39-a +│   │   │   │   ├── zenith39-ansi -> .././7a/z39-a +│   │   │   │   ├── zt-1 -> .././7a/ztx +│   │   │   │   ├── ztx +│   │   │   │   ├── ztx11 -> .././7a/ztx +│   │   │   │   └── ztx-1-a -> .././7a/ztx +│   │   │   └── zoneinfo +│   │   │   ├── Africa +│   │   │   │   ├── Abidjan +│   │   │   │   ├── Accra +│   │   │   │   ├── Addis_Ababa +│   │   │   │   ├── Algiers +│   │   │   │   ├── Asmara +│   │   │   │   ├── Asmera +│   │   │   │   ├── Bamako +│   │   │   │   ├── Bangui +│   │   │   │   ├── Banjul +│   │   │   │   ├── Bissau +│   │   │   │   ├── Blantyre +│   │   │   │   ├── Brazzaville +│   │   │   │   ├── Bujumbura +│   │   │   │   ├── Cairo +│   │   │   │   ├── Casablanca +│   │   │   │   ├── Ceuta +│   │   │   │   ├── Conakry +│   │   │   │   ├── Dakar +│   │   │   │   ├── Dar_es_Salaam +│   │   │   │   ├── Djibouti +│   │   │   │   ├── Douala +│   │   │   │   ├── El_Aaiun +│   │   │   │   ├── Freetown +│   │   │   │   ├── Gaborone +│   │   │   │   ├── Harare +│   │   │   │   ├── Johannesburg +│   │   │   │   ├── Juba +│   │   │   │   ├── Kampala +│   │   │   │   ├── Khartoum +│   │   │   │   ├── Kigali +│   │   │   │   ├── Kinshasa +│   │   │   │   ├── Lagos +│   │   │   │   ├── Libreville +│   │   │   │   ├── Lome +│   │   │   │   ├── Luanda +│   │   │   │   ├── Lubumbashi +│   │   │   │   ├── Lusaka +│   │   │   │   ├── Malabo +│   │   │   │   ├── Maputo +│   │   │   │   ├── Maseru +│   │   │   │   ├── Mbabane +│   │   │   │   ├── Mogadishu +│   │   │   │   ├── Monrovia +│   │   │   │   ├── Nairobi +│   │   │   │   ├── Ndjamena +│   │   │   │   ├── Niamey +│   │   │   │   ├── Nouakchott +│   │   │   │   ├── Ouagadougou +│   │   │   │   ├── Porto-Novo +│   │   │   │   ├── Sao_Tome +│   │   │   │   ├── Timbuktu +│   │   │   │   ├── Tripoli +│   │   │   │   ├── Tunis +│   │   │   │   └── Windhoek +│   │   │   ├── America +│   │   │   │   ├── Adak +│   │   │   │   ├── Anchorage +│   │   │   │   ├── Anguilla +│   │   │   │   ├── Antigua +│   │   │   │   ├── Araguaina +│   │   │   │   ├── Argentina +│   │   │   │   │   ├── Buenos_Aires +│   │   │   │   │   ├── Catamarca +│   │   │   │   │   ├── ComodRivadavia +│   │   │   │   │   ├── Cordoba +│   │   │   │   │   ├── Jujuy +│   │   │   │   │   ├── La_Rioja +│   │   │   │   │   ├── Mendoza +│   │   │   │   │   ├── Rio_Gallegos +│   │   │   │   │   ├── Salta +│   │   │   │   │   ├── San_Juan +│   │   │   │   │   ├── San_Luis +│   │   │   │   │   ├── Tucuman +│   │   │   │   │   └── Ushuaia +│   │   │   │   ├── Aruba +│   │   │   │   ├── Asuncion +│   │   │   │   ├── Atikokan +│   │   │   │   ├── Atka +│   │   │   │   ├── Bahia +│   │   │   │   ├── Bahia_Banderas +│   │   │   │   ├── Barbados +│   │   │   │   ├── Belem +│   │   │   │   ├── Belize +│   │   │   │   ├── Blanc-Sablon +│   │   │   │   ├── Boa_Vista +│   │   │   │   ├── Bogota +│   │   │   │   ├── Boise +│   │   │   │   ├── Buenos_Aires +│   │   │   │   ├── Cambridge_Bay +│   │   │   │   ├── Campo_Grande +│   │   │   │   ├── Cancun +│   │   │   │   ├── Caracas +│   │   │   │   ├── Catamarca +│   │   │   │   ├── Cayenne +│   │   │   │   ├── Cayman +│   │   │   │   ├── Chicago +│   │   │   │   ├── Chihuahua +│   │   │   │   ├── Ciudad_Juarez +│   │   │   │   ├── Coral_Harbour +│   │   │   │   ├── Cordoba +│   │   │   │   ├── Costa_Rica +│   │   │   │   ├── Coyhaique +│   │   │   │   ├── Creston +│   │   │   │   ├── Cuiaba +│   │   │   │   ├── Curacao +│   │   │   │   ├── Danmarkshavn +│   │   │   │   ├── Dawson +│   │   │   │   ├── Dawson_Creek +│   │   │   │   ├── Denver +│   │   │   │   ├── Detroit +│   │   │   │   ├── Dominica +│   │   │   │   ├── Edmonton +│   │   │   │   ├── Eirunepe +│   │   │   │   ├── El_Salvador +│   │   │   │   ├── Ensenada +│   │   │   │   ├── Fortaleza +│   │   │   │   ├── Fort_Nelson +│   │   │   │   ├── Fort_Wayne +│   │   │   │   ├── Glace_Bay +│   │   │   │   ├── Godthab +│   │   │   │   ├── Goose_Bay +│   │   │   │   ├── Grand_Turk +│   │   │   │   ├── Grenada +│   │   │   │   ├── Guadeloupe +│   │   │   │   ├── Guatemala +│   │   │   │   ├── Guayaquil +│   │   │   │   ├── Guyana +│   │   │   │   ├── Halifax +│   │   │   │   ├── Havana +│   │   │   │   ├── Hermosillo +│   │   │   │   ├── Indiana +│   │   │   │   │   ├── Indianapolis +│   │   │   │   │   ├── Knox +│   │   │   │   │   ├── Marengo +│   │   │   │   │   ├── Petersburg +│   │   │   │   │   ├── Tell_City +│   │   │   │   │   ├── Vevay +│   │   │   │   │   ├── Vincennes +│   │   │   │   │   └── Winamac +│   │   │   │   ├── Indianapolis +│   │   │   │   ├── Inuvik +│   │   │   │   ├── Iqaluit +│   │   │   │   ├── Jamaica +│   │   │   │   ├── Jujuy +│   │   │   │   ├── Juneau +│   │   │   │   ├── Kentucky +│   │   │   │   │   ├── Louisville +│   │   │   │   │   └── Monticello +│   │   │   │   ├── Knox_IN +│   │   │   │   ├── Kralendijk +│   │   │   │   ├── La_Paz +│   │   │   │   ├── Lima +│   │   │   │   ├── Los_Angeles +│   │   │   │   ├── Louisville +│   │   │   │   ├── Lower_Princes +│   │   │   │   ├── Maceio +│   │   │   │   ├── Managua +│   │   │   │   ├── Manaus +│   │   │   │   ├── Marigot +│   │   │   │   ├── Martinique +│   │   │   │   ├── Matamoros +│   │   │   │   ├── Mazatlan +│   │   │   │   ├── Mendoza +│   │   │   │   ├── Menominee +│   │   │   │   ├── Merida +│   │   │   │   ├── Metlakatla +│   │   │   │   ├── Mexico_City +│   │   │   │   ├── Miquelon +│   │   │   │   ├── Moncton +│   │   │   │   ├── Monterrey +│   │   │   │   ├── Montevideo +│   │   │   │   ├── Montreal +│   │   │   │   ├── Montserrat +│   │   │   │   ├── Nassau +│   │   │   │   ├── New_York +│   │   │   │   ├── Nipigon +│   │   │   │   ├── Nome +│   │   │   │   ├── Noronha +│   │   │   │   ├── North_Dakota +│   │   │   │   │   ├── Beulah +│   │   │   │   │   ├── Center +│   │   │   │   │   └── New_Salem +│   │   │   │   ├── Nuuk +│   │   │   │   ├── Ojinaga +│   │   │   │   ├── Panama +│   │   │   │   ├── Pangnirtung +│   │   │   │   ├── Paramaribo +│   │   │   │   ├── Phoenix +│   │   │   │   ├── Port-au-Prince +│   │   │   │   ├── Porto_Acre +│   │   │   │   ├── Port_of_Spain +│   │   │   │   ├── Porto_Velho +│   │   │   │   ├── Puerto_Rico +│   │   │   │   ├── Punta_Arenas +│   │   │   │   ├── Rainy_River +│   │   │   │   ├── Rankin_Inlet +│   │   │   │   ├── Recife +│   │   │   │   ├── Regina +│   │   │   │   ├── Resolute +│   │   │   │   ├── Rio_Branco +│   │   │   │   ├── Rosario +│   │   │   │   ├── Santa_Isabel +│   │   │   │   ├── Santarem +│   │   │   │   ├── Santiago +│   │   │   │   ├── Santo_Domingo +│   │   │   │   ├── Sao_Paulo +│   │   │   │   ├── Scoresbysund +│   │   │   │   ├── Shiprock +│   │   │   │   ├── Sitka +│   │   │   │   ├── St_Barthelemy +│   │   │   │   ├── St_Johns +│   │   │   │   ├── St_Kitts +│   │   │   │   ├── St_Lucia +│   │   │   │   ├── St_Thomas +│   │   │   │   ├── St_Vincent +│   │   │   │   ├── Swift_Current +│   │   │   │   ├── Tegucigalpa +│   │   │   │   ├── Thule +│   │   │   │   ├── Thunder_Bay +│   │   │   │   ├── Tijuana +│   │   │   │   ├── Toronto +│   │   │   │   ├── Tortola +│   │   │   │   ├── Vancouver +│   │   │   │   ├── Virgin +│   │   │   │   ├── Whitehorse +│   │   │   │   ├── Winnipeg +│   │   │   │   ├── Yakutat +│   │   │   │   └── Yellowknife +│   │   │   ├── Antarctica +│   │   │   │   ├── Casey +│   │   │   │   ├── Davis +│   │   │   │   ├── DumontDUrville +│   │   │   │   ├── Macquarie +│   │   │   │   ├── Mawson +│   │   │   │   ├── McMurdo +│   │   │   │   ├── Palmer +│   │   │   │   ├── Rothera +│   │   │   │   ├── South_Pole +│   │   │   │   ├── Syowa +│   │   │   │   ├── Troll +│   │   │   │   └── Vostok +│   │   │   ├── Arctic +│   │   │   │   └── Longyearbyen +│   │   │   ├── Asia +│   │   │   │   ├── Aden +│   │   │   │   ├── Almaty +│   │   │   │   ├── Amman +│   │   │   │   ├── Anadyr +│   │   │   │   ├── Aqtau +│   │   │   │   ├── Aqtobe +│   │   │   │   ├── Ashgabat +│   │   │   │   ├── Ashkhabad +│   │   │   │   ├── Atyrau +│   │   │   │   ├── Baghdad +│   │   │   │   ├── Bahrain +│   │   │   │   ├── Baku +│   │   │   │   ├── Bangkok +│   │   │   │   ├── Barnaul +│   │   │   │   ├── Beirut +│   │   │   │   ├── Bishkek +│   │   │   │   ├── Brunei +│   │   │   │   ├── Calcutta +│   │   │   │   ├── Chita +│   │   │   │   ├── Choibalsan +│   │   │   │   ├── Chongqing +│   │   │   │   ├── Chungking +│   │   │   │   ├── Colombo +│   │   │   │   ├── Dacca +│   │   │   │   ├── Damascus +│   │   │   │   ├── Dhaka +│   │   │   │   ├── Dili +│   │   │   │   ├── Dubai +│   │   │   │   ├── Dushanbe +│   │   │   │   ├── Famagusta +│   │   │   │   ├── Gaza +│   │   │   │   ├── Harbin +│   │   │   │   ├── Hebron +│   │   │   │   ├── Ho_Chi_Minh +│   │   │   │   ├── Hong_Kong +│   │   │   │   ├── Hovd +│   │   │   │   ├── Irkutsk +│   │   │   │   ├── Istanbul +│   │   │   │   ├── Jakarta +│   │   │   │   ├── Jayapura +│   │   │   │   ├── Jerusalem +│   │   │   │   ├── Kabul +│   │   │   │   ├── Kamchatka +│   │   │   │   ├── Karachi +│   │   │   │   ├── Kashgar +│   │   │   │   ├── Kathmandu +│   │   │   │   ├── Katmandu +│   │   │   │   ├── Khandyga +│   │   │   │   ├── Kolkata +│   │   │   │   ├── Krasnoyarsk +│   │   │   │   ├── Kuala_Lumpur +│   │   │   │   ├── Kuching +│   │   │   │   ├── Kuwait +│   │   │   │   ├── Macao +│   │   │   │   ├── Macau +│   │   │   │   ├── Magadan +│   │   │   │   ├── Makassar +│   │   │   │   ├── Manila +│   │   │   │   ├── Muscat +│   │   │   │   ├── Nicosia +│   │   │   │   ├── Novokuznetsk +│   │   │   │   ├── Novosibirsk +│   │   │   │   ├── Omsk +│   │   │   │   ├── Oral +│   │   │   │   ├── Phnom_Penh +│   │   │   │   ├── Pontianak +│   │   │   │   ├── Pyongyang +│   │   │   │   ├── Qatar +│   │   │   │   ├── Qostanay +│   │   │   │   ├── Qyzylorda +│   │   │   │   ├── Rangoon +│   │   │   │   ├── Riyadh +│   │   │   │   ├── Saigon +│   │   │   │   ├── Sakhalin +│   │   │   │   ├── Samarkand +│   │   │   │   ├── Seoul +│   │   │   │   ├── Shanghai +│   │   │   │   ├── Singapore +│   │   │   │   ├── Srednekolymsk +│   │   │   │   ├── Taipei +│   │   │   │   ├── Tashkent +│   │   │   │   ├── Tbilisi +│   │   │   │   ├── Tehran +│   │   │   │   ├── Tel_Aviv +│   │   │   │   ├── Thimbu +│   │   │   │   ├── Thimphu +│   │   │   │   ├── Tokyo +│   │   │   │   ├── Tomsk +│   │   │   │   ├── Ujung_Pandang +│   │   │   │   ├── Ulaanbaatar +│   │   │   │   ├── Ulan_Bator +│   │   │   │   ├── Urumqi +│   │   │   │   ├── Ust-Nera +│   │   │   │   ├── Vientiane +│   │   │   │   ├── Vladivostok +│   │   │   │   ├── Yakutsk +│   │   │   │   ├── Yangon +│   │   │   │   ├── Yekaterinburg +│   │   │   │   └── Yerevan +│   │   │   ├── Atlantic +│   │   │   │   ├── Azores +│   │   │   │   ├── Bermuda +│   │   │   │   ├── Canary +│   │   │   │   ├── Cape_Verde +│   │   │   │   ├── Faeroe +│   │   │   │   ├── Faroe +│   │   │   │   ├── Jan_Mayen +│   │   │   │   ├── Madeira +│   │   │   │   ├── Reykjavik +│   │   │   │   ├── South_Georgia +│   │   │   │   ├── Stanley +│   │   │   │   └── St_Helena +│   │   │   ├── Australia +│   │   │   │   ├── ACT +│   │   │   │   ├── Adelaide +│   │   │   │   ├── Brisbane +│   │   │   │   ├── Broken_Hill +│   │   │   │   ├── Canberra +│   │   │   │   ├── Currie +│   │   │   │   ├── Darwin +│   │   │   │   ├── Eucla +│   │   │   │   ├── Hobart +│   │   │   │   ├── LHI +│   │   │   │   ├── Lindeman +│   │   │   │   ├── Lord_Howe +│   │   │   │   ├── Melbourne +│   │   │   │   ├── North +│   │   │   │   ├── NSW +│   │   │   │   ├── Perth +│   │   │   │   ├── Queensland +│   │   │   │   ├── South +│   │   │   │   ├── Sydney +│   │   │   │   ├── Tasmania +│   │   │   │   ├── Victoria +│   │   │   │   ├── West +│   │   │   │   └── Yancowinna +│   │   │   ├── Brazil +│   │   │   │   ├── Acre +│   │   │   │   ├── DeNoronha +│   │   │   │   ├── East +│   │   │   │   └── West +│   │   │   ├── build +│   │   │   │   └── etc +│   │   │   │   └── localtime +│   │   │   ├── Canada +│   │   │   │   ├── Atlantic +│   │   │   │   ├── Central +│   │   │   │   ├── Eastern +│   │   │   │   ├── Mountain +│   │   │   │   ├── Newfoundland +│   │   │   │   ├── Pacific +│   │   │   │   ├── Saskatchewan +│   │   │   │   └── Yukon +│   │   │   ├── CET +│   │   │   ├── Chile +│   │   │   │   ├── Continental +│   │   │   │   └── EasterIsland +│   │   │   ├── CST6CDT +│   │   │   ├── Cuba +│   │   │   ├── EET +│   │   │   ├── Egypt +│   │   │   ├── Eire +│   │   │   ├── EST +│   │   │   ├── EST5EDT +│   │   │   ├── Etc +│   │   │   │   ├── GMT +│   │   │   │   ├── GMT+0 +│   │   │   │   ├── GMT-0 +│   │   │   │   ├── GMT0 +│   │   │   │   ├── GMT+1 +│   │   │   │   ├── GMT-1 +│   │   │   │   ├── GMT+10 +│   │   │   │   ├── GMT-10 +│   │   │   │   ├── GMT+11 +│   │   │   │   ├── GMT-11 +│   │   │   │   ├── GMT+12 +│   │   │   │   ├── GMT-12 +│   │   │   │   ├── GMT-13 +│   │   │   │   ├── GMT-14 +│   │   │   │   ├── GMT+2 +│   │   │   │   ├── GMT-2 +│   │   │   │   ├── GMT+3 +│   │   │   │   ├── GMT-3 +│   │   │   │   ├── GMT+4 +│   │   │   │   ├── GMT-4 +│   │   │   │   ├── GMT+5 +│   │   │   │   ├── GMT-5 +│   │   │   │   ├── GMT+6 +│   │   │   │   ├── GMT-6 +│   │   │   │   ├── GMT+7 +│   │   │   │   ├── GMT-7 +│   │   │   │   ├── GMT+8 +│   │   │   │   ├── GMT-8 +│   │   │   │   ├── GMT+9 +│   │   │   │   ├── GMT-9 +│   │   │   │   ├── Greenwich +│   │   │   │   ├── UCT +│   │   │   │   ├── Universal +│   │   │   │   ├── UTC +│   │   │   │   └── Zulu +│   │   │   ├── Europe +│   │   │   │   ├── Amsterdam +│   │   │   │   ├── Andorra +│   │   │   │   ├── Astrakhan +│   │   │   │   ├── Athens +│   │   │   │   ├── Belfast +│   │   │   │   ├── Belgrade +│   │   │   │   ├── Berlin +│   │   │   │   ├── Bratislava +│   │   │   │   ├── Brussels +│   │   │   │   ├── Bucharest +│   │   │   │   ├── Budapest +│   │   │   │   ├── Busingen +│   │   │   │   ├── Chisinau +│   │   │   │   ├── Copenhagen +│   │   │   │   ├── Dublin +│   │   │   │   ├── Gibraltar +│   │   │   │   ├── Guernsey +│   │   │   │   ├── Helsinki +│   │   │   │   ├── Isle_of_Man +│   │   │   │   ├── Istanbul +│   │   │   │   ├── Jersey +│   │   │   │   ├── Kaliningrad +│   │   │   │   ├── Kiev +│   │   │   │   ├── Kirov +│   │   │   │   ├── Kyiv +│   │   │   │   ├── Lisbon +│   │   │   │   ├── Ljubljana +│   │   │   │   ├── London +│   │   │   │   ├── Luxembourg +│   │   │   │   ├── Madrid +│   │   │   │   ├── Malta +│   │   │   │   ├── Mariehamn +│   │   │   │   ├── Minsk +│   │   │   │   ├── Monaco +│   │   │   │   ├── Moscow +│   │   │   │   ├── Nicosia +│   │   │   │   ├── Oslo +│   │   │   │   ├── Paris +│   │   │   │   ├── Podgorica +│   │   │   │   ├── Prague +│   │   │   │   ├── Riga +│   │   │   │   ├── Rome +│   │   │   │   ├── Samara +│   │   │   │   ├── San_Marino +│   │   │   │   ├── Sarajevo +│   │   │   │   ├── Saratov +│   │   │   │   ├── Simferopol +│   │   │   │   ├── Skopje +│   │   │   │   ├── Sofia +│   │   │   │   ├── Stockholm +│   │   │   │   ├── Tallinn +│   │   │   │   ├── Tirane +│   │   │   │   ├── Tiraspol +│   │   │   │   ├── Ulyanovsk +│   │   │   │   ├── Uzhgorod +│   │   │   │   ├── Vaduz +│   │   │   │   ├── Vatican +│   │   │   │   ├── Vienna +│   │   │   │   ├── Vilnius +│   │   │   │   ├── Volgograd +│   │   │   │   ├── Warsaw +│   │   │   │   ├── Zagreb +│   │   │   │   ├── Zaporozhye +│   │   │   │   └── Zurich +│   │   │   ├── Factory +│   │   │   ├── GB +│   │   │   ├── GB-Eire +│   │   │   ├── GMT +│   │   │   ├── GMT+0 +│   │   │   ├── GMT-0 +│   │   │   ├── GMT0 +│   │   │   ├── Greenwich +│   │   │   ├── Hongkong +│   │   │   ├── HST +│   │   │   ├── Iceland +│   │   │   ├── Indian +│   │   │   │   ├── Antananarivo +│   │   │   │   ├── Chagos +│   │   │   │   ├── Christmas +│   │   │   │   ├── Cocos +│   │   │   │   ├── Comoro +│   │   │   │   ├── Kerguelen +│   │   │   │   ├── Mahe +│   │   │   │   ├── Maldives +│   │   │   │   ├── Mauritius +│   │   │   │   ├── Mayotte +│   │   │   │   └── Reunion +│   │   │   ├── Iran +│   │   │   ├── iso3166.tab +│   │   │   ├── Israel +│   │   │   ├── Jamaica +│   │   │   ├── Japan +│   │   │   ├── Kwajalein +│   │   │   ├── leapseconds +│   │   │   ├── leap-seconds.list +│   │   │   ├── Libya +│   │   │   ├── MET +│   │   │   ├── Mexico +│   │   │   │   ├── BajaNorte +│   │   │   │   ├── BajaSur +│   │   │   │   └── General +│   │   │   ├── MST +│   │   │   ├── MST7MDT +│   │   │   ├── Navajo +│   │   │   ├── NZ +│   │   │   ├── NZ-CHAT +│   │   │   ├── Pacific +│   │   │   │   ├── Apia +│   │   │   │   ├── Auckland +│   │   │   │   ├── Bougainville +│   │   │   │   ├── Chatham +│   │   │   │   ├── Chuuk +│   │   │   │   ├── Easter +│   │   │   │   ├── Efate +│   │   │   │   ├── Enderbury +│   │   │   │   ├── Fakaofo +│   │   │   │   ├── Fiji +│   │   │   │   ├── Funafuti +│   │   │   │   ├── Galapagos +│   │   │   │   ├── Gambier +│   │   │   │   ├── Guadalcanal +│   │   │   │   ├── Guam +│   │   │   │   ├── Honolulu +│   │   │   │   ├── Johnston +│   │   │   │   ├── Kanton +│   │   │   │   ├── Kiritimati +│   │   │   │   ├── Kosrae +│   │   │   │   ├── Kwajalein +│   │   │   │   ├── Majuro +│   │   │   │   ├── Marquesas +│   │   │   │   ├── Midway +│   │   │   │   ├── Nauru +│   │   │   │   ├── Niue +│   │   │   │   ├── Norfolk +│   │   │   │   ├── Noumea +│   │   │   │   ├── Pago_Pago +│   │   │   │   ├── Palau +│   │   │   │   ├── Pitcairn +│   │   │   │   ├── Pohnpei +│   │   │   │   ├── Ponape +│   │   │   │   ├── Port_Moresby +│   │   │   │   ├── Rarotonga +│   │   │   │   ├── Saipan +│   │   │   │   ├── Samoa +│   │   │   │   ├── Tahiti +│   │   │   │   ├── Tarawa +│   │   │   │   ├── Tongatapu +│   │   │   │   ├── Truk +│   │   │   │   ├── Wake +│   │   │   │   ├── Wallis +│   │   │   │   └── Yap +│   │   │   ├── Poland +│   │   │   ├── Portugal +│   │   │   ├── PRC +│   │   │   ├── PST8PDT +│   │   │   ├── ROC +│   │   │   ├── ROK +│   │   │   ├── Singapore +│   │   │   ├── Turkey +│   │   │   ├── tzdata.zi +│   │   │   ├── UCT +│   │   │   ├── Universal +│   │   │   ├── US +│   │   │   │   ├── Alaska +│   │   │   │   ├── Aleutian +│   │   │   │   ├── Arizona +│   │   │   │   ├── Central +│   │   │   │   ├── Eastern +│   │   │   │   ├── East-Indiana +│   │   │   │   ├── Hawaii +│   │   │   │   ├── Indiana-Starke +│   │   │   │   ├── Michigan +│   │   │   │   ├── Mountain +│   │   │   │   ├── Pacific +│   │   │   │   └── Samoa +│   │   │   ├── UTC +│   │   │   ├── WET +│   │   │   ├── W-SU +│   │   │   ├── zone1970.tab +│   │   │   ├── zonenow.tab +│   │   │   ├── zone.tab +│   │   │   └── Zulu +│   │   ├── ssl +│   │   │   ├── cacert.pem +│   │   │   ├── cert.pem -> cacert.pem +│   │   │   ├── certs +│   │   │   │   └── .keep +│   │   │   ├── ct_log_list.cnf +│   │   │   ├── ct_log_list.cnf.dist +│   │   │   ├── misc +│   │   │   │   ├── CA.pl +│   │   │   │   ├── tsget -> tsget.pl +│   │   │   │   └── tsget.pl +│   │   │   ├── openssl.cnf +│   │   │   └── openssl.cnf.dist +│   │   └── x86_64-conda-linux-gnu +│   │   └── bin +│   │   └── ld -> ../../bin/x86_64-conda-linux-gnu-ld +│   ├── .gitignore +│   └── task-cache-v0 +│   ├── default-check-d0a66a65c7528968.json +│   └── default-test-d0a66a65c7528968.json +├── pixi.lock +├── pixi.toml +├── .pre-commit-config.yaml ├── PRINCIPLES.md -├── locales/ -│ ├── README.th.md -│ ├── README.ja.md -│ └── README.zh.md -└── .github/ - ├── ISSUE_TEMPLATE/ - │ ├── bug_report.yml - │ └── feature_request.yml - ├── PULL_REQUEST_TEMPLATE.md - └── workflows/ - ├── ci.yml - ├── security.yml - └── pr_automation.yml +├── proto +│   └── vtuber +│   └── v1 +│   ├── conversation.proto +│   ├── persona.proto +│   ├── tool_call.proto +│   └── voice_profile.proto +├── README.md +├── ROADMAP.md +├── samples +│   └── personas +│   ├── aurora.yaml +│   └── valora.yaml +├── SECURITY.md +├── src +│   └── lib.rs +├── STRATEGY.md +├── STRUCTURE.tree +├── SUPPORT.md +├── tests +│   ├── persona_yaml_roundtrip.rs +│   └── roundtrip.rs +├── TROUBLESHOOTING.md +├── tsconfig.json +└── VISION.md + +480 directories, 8089 files diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 0000000..2769f35 --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,14 @@ +version: v2 +managed: + enabled: true +plugins: + - remote: buf.build/protocolbuffers/python + out: generated/python + - remote: buf.build/protocolbuffers/pyi + out: generated/python + - remote: buf.build/community/stephenh-ts-proto + out: generated/typescript + opt: + - esModuleInterop=true + - outputServices=generic-definitions + - env=node diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 0000000..c7e30e3 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,9 @@ +version: v2 +modules: + - path: proto +lint: + use: + - STANDARD +breaking: + use: + - FILE diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..6c4d1b0 --- /dev/null +++ b/build.rs @@ -0,0 +1,19 @@ +fn main() -> Result<(), Box> { + let protos = &[ + "proto/vtuber/v1/persona.proto", + "proto/vtuber/v1/voice_profile.proto", + "proto/vtuber/v1/conversation.proto", + ]; + + for p in protos { + println!("cargo:rerun-if-changed={p}"); + } + println!("cargo:rerun-if-changed=build.rs"); + + tonic_build::configure() + .build_server(true) + .build_client(true) + .compile_protos(protos, &["proto"])?; + + Ok(()) +} diff --git a/examples/generate_golden.rs b/examples/generate_golden.rs new file mode 100644 index 0000000..593df7e --- /dev/null +++ b/examples/generate_golden.rs @@ -0,0 +1,32 @@ +use prost::Message; +use std::fs::File; +use std::io::Write; +use std::time::SystemTime; +use vtuber_contracts::vtuber::v1::{AudioFormat, ConversationDirective, Emotion, PersonaId}; + +fn main() -> Result<(), Box> { + let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?; + + let directive = ConversationDirective { + directive_id: "test-golden-roundtrip-001".to_string(), + emitted_at: Some(prost_types::Timestamp { + seconds: now.as_secs() as i64, + nanos: now.subsec_nanos() as i32, + }), + persona_id: PersonaId::Valora as i32, + text_prompt: "สวัสดี ยินดีที่ได้รู้จัก!".to_string(), + voice_prompt: "thai-accent-test".to_string(), + emotion: Emotion::Happy as i32, + target_audio_format: AudioFormat::Wav as i32, + max_latency_ms: 500, + }; + + let mut buf = Vec::new(); + directive.encode(&mut buf)?; + + let mut file = File::create("golden_directive.bin")?; + file.write_all(&buf)?; + + println!("Successfully generated golden_directive.bin from Rust"); + Ok(()) +} diff --git a/generated/python/vtuber/v1/conversation_pb2.py b/generated/python/vtuber/v1/conversation_pb2.py new file mode 100644 index 0000000..c6f8fbf --- /dev/null +++ b/generated/python/vtuber/v1/conversation_pb2.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: vtuber/v1/conversation.proto +# Protobuf Python Version: 7.34.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 34, + 1, + '', + 'vtuber/v1/conversation.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from vtuber.v1 import persona_pb2 as vtuber_dot_v1_dot_persona__pb2 +from vtuber.v1 import voice_profile_pb2 as vtuber_dot_v1_dot_voice__profile__pb2 +from vtuber.v1 import tool_call_pb2 as vtuber_dot_v1_dot_tool__call__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cvtuber/v1/conversation.proto\x12\tvtuber.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17vtuber/v1/persona.proto\x1a\x1dvtuber/v1/voice_profile.proto\x1a\x19vtuber/v1/tool_call.proto\"\xbe\x03\n\x15\x43onversationDirective\x12!\n\x0c\x64irective_id\x18\x01 \x01(\tR\x0b\x64irectiveId\x12\x39\n\nemitted_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\temittedAt\x12\x33\n\npersona_id\x18\x03 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\tpersonaId\x12\x1f\n\x0btext_prompt\x18\x04 \x01(\tR\ntextPrompt\x12!\n\x0cvoice_prompt\x18\x05 \x01(\tR\x0bvoicePrompt\x12,\n\x07\x65motion\x18\x06 \x01(\x0e\x32\x12.vtuber.v1.EmotionR\x07\x65motion\x12\x46\n\x13target_audio_format\x18\x07 \x01(\x0e\x32\x16.vtuber.v1.AudioFormatR\x11targetAudioFormat\x12$\n\x0emax_latency_ms\x18\x08 \x01(\rR\x0cmaxLatencyMs\x12\x32\n\ntool_calls\x18\t \x03(\x0b\x32\x13.vtuber.v1.ToolCallR\ttoolCalls\"r\n\x0c\x44irectiveAck\x12!\n\x0c\x64irective_id\x18\x01 \x01(\tR\x0b\x64irectiveId\x12\x1a\n\x08\x61\x63\x63\x65pted\x18\x02 \x01(\x08R\x08\x61\x63\x63\x65pted\x12#\n\rreject_reason\x18\x03 \x01(\tR\x0crejectReason\"V\n\x14\x45mitDirectiveRequest\x12>\n\tdirective\x18\x01 \x01(\x0b\x32 .vtuber.v1.ConversationDirectiveR\tdirective\"B\n\x15\x45mitDirectiveResponse\x12)\n\x03\x61\x63k\x18\x01 \x01(\x0b\x32\x17.vtuber.v1.DirectiveAckR\x03\x61\x63k2e\n\x0f\x44irectorService\x12R\n\rEmitDirective\x12\x1f.vtuber.v1.EmitDirectiveRequest\x1a .vtuber.v1.EmitDirectiveResponseBg\n\rcom.vtuber.v1B\x11\x43onversationProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.conversation_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\021ConversationProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + _globals['_CONVERSATIONDIRECTIVE']._serialized_start=160 + _globals['_CONVERSATIONDIRECTIVE']._serialized_end=606 + _globals['_DIRECTIVEACK']._serialized_start=608 + _globals['_DIRECTIVEACK']._serialized_end=722 + _globals['_EMITDIRECTIVEREQUEST']._serialized_start=724 + _globals['_EMITDIRECTIVEREQUEST']._serialized_end=810 + _globals['_EMITDIRECTIVERESPONSE']._serialized_start=812 + _globals['_EMITDIRECTIVERESPONSE']._serialized_end=878 + _globals['_DIRECTORSERVICE']._serialized_start=880 + _globals['_DIRECTORSERVICE']._serialized_end=981 +# @@protoc_insertion_point(module_scope) diff --git a/generated/python/vtuber/v1/conversation_pb2.pyi b/generated/python/vtuber/v1/conversation_pb2.pyi new file mode 100644 index 0000000..dab347a --- /dev/null +++ b/generated/python/vtuber/v1/conversation_pb2.pyi @@ -0,0 +1,57 @@ +import datetime + +from google.protobuf import timestamp_pb2 as _timestamp_pb2 +from vtuber.v1 import persona_pb2 as _persona_pb2 +from vtuber.v1 import voice_profile_pb2 as _voice_profile_pb2 +from vtuber.v1 import tool_call_pb2 as _tool_call_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ConversationDirective(_message.Message): + __slots__ = ("directive_id", "emitted_at", "persona_id", "text_prompt", "voice_prompt", "emotion", "target_audio_format", "max_latency_ms", "tool_calls") + DIRECTIVE_ID_FIELD_NUMBER: _ClassVar[int] + EMITTED_AT_FIELD_NUMBER: _ClassVar[int] + PERSONA_ID_FIELD_NUMBER: _ClassVar[int] + TEXT_PROMPT_FIELD_NUMBER: _ClassVar[int] + VOICE_PROMPT_FIELD_NUMBER: _ClassVar[int] + EMOTION_FIELD_NUMBER: _ClassVar[int] + TARGET_AUDIO_FORMAT_FIELD_NUMBER: _ClassVar[int] + MAX_LATENCY_MS_FIELD_NUMBER: _ClassVar[int] + TOOL_CALLS_FIELD_NUMBER: _ClassVar[int] + directive_id: str + emitted_at: _timestamp_pb2.Timestamp + persona_id: _persona_pb2.PersonaId + text_prompt: str + voice_prompt: str + emotion: _voice_profile_pb2.Emotion + target_audio_format: _voice_profile_pb2.AudioFormat + max_latency_ms: int + tool_calls: _containers.RepeatedCompositeFieldContainer[_tool_call_pb2.ToolCall] + def __init__(self, directive_id: _Optional[str] = ..., emitted_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., persona_id: _Optional[_Union[_persona_pb2.PersonaId, str]] = ..., text_prompt: _Optional[str] = ..., voice_prompt: _Optional[str] = ..., emotion: _Optional[_Union[_voice_profile_pb2.Emotion, str]] = ..., target_audio_format: _Optional[_Union[_voice_profile_pb2.AudioFormat, str]] = ..., max_latency_ms: _Optional[int] = ..., tool_calls: _Optional[_Iterable[_Union[_tool_call_pb2.ToolCall, _Mapping]]] = ...) -> None: ... + +class DirectiveAck(_message.Message): + __slots__ = ("directive_id", "accepted", "reject_reason") + DIRECTIVE_ID_FIELD_NUMBER: _ClassVar[int] + ACCEPTED_FIELD_NUMBER: _ClassVar[int] + REJECT_REASON_FIELD_NUMBER: _ClassVar[int] + directive_id: str + accepted: bool + reject_reason: str + def __init__(self, directive_id: _Optional[str] = ..., accepted: _Optional[bool] = ..., reject_reason: _Optional[str] = ...) -> None: ... + +class EmitDirectiveRequest(_message.Message): + __slots__ = ("directive",) + DIRECTIVE_FIELD_NUMBER: _ClassVar[int] + directive: ConversationDirective + def __init__(self, directive: _Optional[_Union[ConversationDirective, _Mapping]] = ...) -> None: ... + +class EmitDirectiveResponse(_message.Message): + __slots__ = ("ack",) + ACK_FIELD_NUMBER: _ClassVar[int] + ack: DirectiveAck + def __init__(self, ack: _Optional[_Union[DirectiveAck, _Mapping]] = ...) -> None: ... diff --git a/generated/python/vtuber/v1/persona_pb2.py b/generated/python/vtuber/v1/persona_pb2.py new file mode 100644 index 0000000..046e90c --- /dev/null +++ b/generated/python/vtuber/v1/persona_pb2.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: vtuber/v1/persona.proto +# Protobuf Python Version: 7.34.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 34, + 1, + '', + 'vtuber/v1/persona.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17vtuber/v1/persona.proto\x12\tvtuber.v1\"\xdf\x01\n\x07Persona\x12$\n\x02id\x18\x01 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\x02id\x12!\n\x0c\x64isplay_name\x18\x02 \x01(\tR\x0b\x64isplayName\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12/\n\x13\x61\x63tivation_keywords\x18\x04 \x03(\tR\x12\x61\x63tivationKeywords\x12\x1b\n\tlore_tags\x18\x05 \x03(\tR\x08loreTags\x12\x1b\n\tcolor_hex\x18\x06 \x01(\tR\x08\x63olorHex*\x9b\x01\n\tPersonaId\x12\x1a\n\x16PERSONA_ID_UNSPECIFIED\x10\x00\x12\x15\n\x11PERSONA_ID_VALORA\x10\x01\x12\x15\n\x11PERSONA_ID_AURORA\x10\x02\x12\x15\n\x11PERSONA_ID_AMETRA\x10\x03\x12\x16\n\x12PERSONA_ID_ASTRAEA\x10\x04\x12\x15\n\x11PERSONA_ID_ELDORA\x10\x05\x42\x62\n\rcom.vtuber.v1B\x0cPersonaProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.persona_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\014PersonaProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + _globals['_PERSONAID']._serialized_start=265 + _globals['_PERSONAID']._serialized_end=420 + _globals['_PERSONA']._serialized_start=39 + _globals['_PERSONA']._serialized_end=262 +# @@protoc_insertion_point(module_scope) diff --git a/generated/python/vtuber/v1/persona_pb2.pyi b/generated/python/vtuber/v1/persona_pb2.pyi new file mode 100644 index 0000000..cee26f6 --- /dev/null +++ b/generated/python/vtuber/v1/persona_pb2.pyi @@ -0,0 +1,39 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class PersonaId(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + PERSONA_ID_UNSPECIFIED: _ClassVar[PersonaId] + PERSONA_ID_VALORA: _ClassVar[PersonaId] + PERSONA_ID_AURORA: _ClassVar[PersonaId] + PERSONA_ID_AMETRA: _ClassVar[PersonaId] + PERSONA_ID_ASTRAEA: _ClassVar[PersonaId] + PERSONA_ID_ELDORA: _ClassVar[PersonaId] +PERSONA_ID_UNSPECIFIED: PersonaId +PERSONA_ID_VALORA: PersonaId +PERSONA_ID_AURORA: PersonaId +PERSONA_ID_AMETRA: PersonaId +PERSONA_ID_ASTRAEA: PersonaId +PERSONA_ID_ELDORA: PersonaId + +class Persona(_message.Message): + __slots__ = ("id", "display_name", "description", "activation_keywords", "lore_tags", "color_hex") + ID_FIELD_NUMBER: _ClassVar[int] + DISPLAY_NAME_FIELD_NUMBER: _ClassVar[int] + DESCRIPTION_FIELD_NUMBER: _ClassVar[int] + ACTIVATION_KEYWORDS_FIELD_NUMBER: _ClassVar[int] + LORE_TAGS_FIELD_NUMBER: _ClassVar[int] + COLOR_HEX_FIELD_NUMBER: _ClassVar[int] + id: PersonaId + display_name: str + description: str + activation_keywords: _containers.RepeatedScalarFieldContainer[str] + lore_tags: _containers.RepeatedScalarFieldContainer[str] + color_hex: str + def __init__(self, id: _Optional[_Union[PersonaId, str]] = ..., display_name: _Optional[str] = ..., description: _Optional[str] = ..., activation_keywords: _Optional[_Iterable[str]] = ..., lore_tags: _Optional[_Iterable[str]] = ..., color_hex: _Optional[str] = ...) -> None: ... diff --git a/generated/python/vtuber/v1/tool_call_pb2.py b/generated/python/vtuber/v1/tool_call_pb2.py new file mode 100644 index 0000000..a32623e --- /dev/null +++ b/generated/python/vtuber/v1/tool_call_pb2.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: vtuber/v1/tool_call.proto +# Protobuf Python Version: 7.34.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 34, + 1, + '', + 'vtuber/v1/tool_call.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19vtuber/v1/tool_call.proto\x12\tvtuber.v1\x1a\x1cgoogle/protobuf/struct.proto\"\xea\x01\n\x08ToolCall\x12\x17\n\x07\x63\x61ll_id\x18\x01 \x01(\tR\x06\x63\x61llId\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12\x35\n\targuments\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\targuments\x12=\n\x08metadata\x18\x04 \x03(\x0b\x32!.vtuber.v1.ToolCall.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"{\n\x0cToolResponse\x12\x17\n\x07\x63\x61ll_id\x18\x01 \x01(\tR\x06\x63\x61llId\x12\x18\n\x07\x63ontent\x18\x02 \x01(\tR\x07\x63ontent\x12\x19\n\x08is_error\x18\x03 \x01(\x08R\x07isError\x12\x1d\n\nerror_code\x18\x04 \x01(\tR\terrorCode\"\x7f\n\x0eToolDefinition\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x02 \x01(\tR\x0b\x64\x65scription\x12\x37\n\nparameters\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\nparametersBc\n\rcom.vtuber.v1B\rToolCallProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.tool_call_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\rToolCallProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + _globals['_TOOLCALL_METADATAENTRY']._loaded_options = None + _globals['_TOOLCALL_METADATAENTRY']._serialized_options = b'8\001' + _globals['_TOOLCALL']._serialized_start=71 + _globals['_TOOLCALL']._serialized_end=305 + _globals['_TOOLCALL_METADATAENTRY']._serialized_start=246 + _globals['_TOOLCALL_METADATAENTRY']._serialized_end=305 + _globals['_TOOLRESPONSE']._serialized_start=307 + _globals['_TOOLRESPONSE']._serialized_end=430 + _globals['_TOOLDEFINITION']._serialized_start=432 + _globals['_TOOLDEFINITION']._serialized_end=559 +# @@protoc_insertion_point(module_scope) diff --git a/generated/python/vtuber/v1/tool_call_pb2.pyi b/generated/python/vtuber/v1/tool_call_pb2.pyi new file mode 100644 index 0000000..c2df2fd --- /dev/null +++ b/generated/python/vtuber/v1/tool_call_pb2.pyi @@ -0,0 +1,49 @@ +from google.protobuf import struct_pb2 as _struct_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ToolCall(_message.Message): + __slots__ = ("call_id", "name", "arguments", "metadata") + class MetadataEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + CALL_ID_FIELD_NUMBER: _ClassVar[int] + NAME_FIELD_NUMBER: _ClassVar[int] + ARGUMENTS_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + call_id: str + name: str + arguments: _struct_pb2.Struct + metadata: _containers.ScalarMap[str, str] + def __init__(self, call_id: _Optional[str] = ..., name: _Optional[str] = ..., arguments: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., metadata: _Optional[_Mapping[str, str]] = ...) -> None: ... + +class ToolResponse(_message.Message): + __slots__ = ("call_id", "content", "is_error", "error_code") + CALL_ID_FIELD_NUMBER: _ClassVar[int] + CONTENT_FIELD_NUMBER: _ClassVar[int] + IS_ERROR_FIELD_NUMBER: _ClassVar[int] + ERROR_CODE_FIELD_NUMBER: _ClassVar[int] + call_id: str + content: str + is_error: bool + error_code: str + def __init__(self, call_id: _Optional[str] = ..., content: _Optional[str] = ..., is_error: _Optional[bool] = ..., error_code: _Optional[str] = ...) -> None: ... + +class ToolDefinition(_message.Message): + __slots__ = ("name", "description", "parameters") + NAME_FIELD_NUMBER: _ClassVar[int] + DESCRIPTION_FIELD_NUMBER: _ClassVar[int] + PARAMETERS_FIELD_NUMBER: _ClassVar[int] + name: str + description: str + parameters: _struct_pb2.Struct + def __init__(self, name: _Optional[str] = ..., description: _Optional[str] = ..., parameters: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... diff --git a/generated/python/vtuber/v1/voice_profile_pb2.py b/generated/python/vtuber/v1/voice_profile_pb2.py new file mode 100644 index 0000000..c6c0c94 --- /dev/null +++ b/generated/python/vtuber/v1/voice_profile_pb2.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: vtuber/v1/voice_profile.proto +# Protobuf Python Version: 7.34.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 34, + 1, + '', + 'vtuber/v1/voice_profile.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from vtuber.v1 import persona_pb2 as vtuber_dot_v1_dot_persona__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dvtuber/v1/voice_profile.proto\x12\tvtuber.v1\x1a\x17vtuber/v1/persona.proto\"\xf5\x01\n\x0cVoiceProfile\x12\x33\n\npersona_id\x18\x01 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\tpersonaId\x12\x1d\n\nbase_pitch\x18\x02 \x01(\x02R\tbasePitch\x12#\n\rspeaking_rate\x18\x03 \x01(\x02R\x0cspeakingRate\x12\x16\n\x06\x65nergy\x18\x04 \x01(\x02R\x06\x65nergy\x12\x1b\n\tstyle_tag\x18\x05 \x01(\tR\x08styleTag\x12\x1f\n\x0b\x61\x63\x63\x65nt_hint\x18\x06 \x01(\tR\naccentHint\x12\x16\n\x06quirks\x18\x07 \x03(\tR\x06quirks*n\n\x0b\x41udioFormat\x12\x1c\n\x18\x41UDIO_FORMAT_UNSPECIFIED\x10\x00\x12\x14\n\x10\x41UDIO_FORMAT_WAV\x10\x01\x12\x15\n\x11\x41UDIO_FORMAT_OPUS\x10\x02\x12\x14\n\x10\x41UDIO_FORMAT_MP3\x10\x03*\xb2\x01\n\x07\x45motion\x12\x17\n\x13\x45MOTION_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x45MOTION_NEUTRAL\x10\x01\x12\x11\n\rEMOTION_HAPPY\x10\x02\x12\x0f\n\x0b\x45MOTION_SAD\x10\x03\x12\x11\n\rEMOTION_ANGRY\x10\x04\x12\x13\n\x0f\x45MOTION_PLAYFUL\x10\x05\x12\x16\n\x12\x45MOTION_ANALYTICAL\x10\x06\x12\x15\n\x11\x45MOTION_ASMR_CALM\x10\x07\x42g\n\rcom.vtuber.v1B\x11VoiceProfileProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.voice_profile_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\021VoiceProfileProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + _globals['_AUDIOFORMAT']._serialized_start=317 + _globals['_AUDIOFORMAT']._serialized_end=427 + _globals['_EMOTION']._serialized_start=430 + _globals['_EMOTION']._serialized_end=608 + _globals['_VOICEPROFILE']._serialized_start=70 + _globals['_VOICEPROFILE']._serialized_end=315 +# @@protoc_insertion_point(module_scope) diff --git a/generated/python/vtuber/v1/voice_profile_pb2.pyi b/generated/python/vtuber/v1/voice_profile_pb2.pyi new file mode 100644 index 0000000..f8660ac --- /dev/null +++ b/generated/python/vtuber/v1/voice_profile_pb2.pyi @@ -0,0 +1,57 @@ +from vtuber.v1 import persona_pb2 as _persona_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class AudioFormat(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + AUDIO_FORMAT_UNSPECIFIED: _ClassVar[AudioFormat] + AUDIO_FORMAT_WAV: _ClassVar[AudioFormat] + AUDIO_FORMAT_OPUS: _ClassVar[AudioFormat] + AUDIO_FORMAT_MP3: _ClassVar[AudioFormat] + +class Emotion(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + EMOTION_UNSPECIFIED: _ClassVar[Emotion] + EMOTION_NEUTRAL: _ClassVar[Emotion] + EMOTION_HAPPY: _ClassVar[Emotion] + EMOTION_SAD: _ClassVar[Emotion] + EMOTION_ANGRY: _ClassVar[Emotion] + EMOTION_PLAYFUL: _ClassVar[Emotion] + EMOTION_ANALYTICAL: _ClassVar[Emotion] + EMOTION_ASMR_CALM: _ClassVar[Emotion] +AUDIO_FORMAT_UNSPECIFIED: AudioFormat +AUDIO_FORMAT_WAV: AudioFormat +AUDIO_FORMAT_OPUS: AudioFormat +AUDIO_FORMAT_MP3: AudioFormat +EMOTION_UNSPECIFIED: Emotion +EMOTION_NEUTRAL: Emotion +EMOTION_HAPPY: Emotion +EMOTION_SAD: Emotion +EMOTION_ANGRY: Emotion +EMOTION_PLAYFUL: Emotion +EMOTION_ANALYTICAL: Emotion +EMOTION_ASMR_CALM: Emotion + +class VoiceProfile(_message.Message): + __slots__ = ("persona_id", "base_pitch", "speaking_rate", "energy", "style_tag", "accent_hint", "quirks") + PERSONA_ID_FIELD_NUMBER: _ClassVar[int] + BASE_PITCH_FIELD_NUMBER: _ClassVar[int] + SPEAKING_RATE_FIELD_NUMBER: _ClassVar[int] + ENERGY_FIELD_NUMBER: _ClassVar[int] + STYLE_TAG_FIELD_NUMBER: _ClassVar[int] + ACCENT_HINT_FIELD_NUMBER: _ClassVar[int] + QUIRKS_FIELD_NUMBER: _ClassVar[int] + persona_id: _persona_pb2.PersonaId + base_pitch: float + speaking_rate: float + energy: float + style_tag: str + accent_hint: str + quirks: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, persona_id: _Optional[_Union[_persona_pb2.PersonaId, str]] = ..., base_pitch: _Optional[float] = ..., speaking_rate: _Optional[float] = ..., energy: _Optional[float] = ..., style_tag: _Optional[str] = ..., accent_hint: _Optional[str] = ..., quirks: _Optional[_Iterable[str]] = ...) -> None: ... diff --git a/generated/typescript/google/protobuf/struct.ts b/generated/typescript/google/protobuf/struct.ts new file mode 100644 index 0000000..32edbb8 --- /dev/null +++ b/generated/typescript/google/protobuf/struct.ts @@ -0,0 +1,615 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.11.6 +// protoc unknown +// source: google/protobuf/struct.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export const protobufPackage = "google.protobuf"; + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + */ +export enum NullValue { + /** NULL_VALUE - Null value. */ + NULL_VALUE = 0, + UNRECOGNIZED = -1, +} + +export function nullValueFromJSON(object: any): NullValue { + switch (object) { + case 0: + case "NULL_VALUE": + return NullValue.NULL_VALUE; + case -1: + case "UNRECOGNIZED": + default: + return NullValue.UNRECOGNIZED; + } +} + +export function nullValueToJSON(object: NullValue): string { + switch (object) { + case NullValue.NULL_VALUE: + return "NULL_VALUE"; + case NullValue.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + */ +export interface Struct { + /** Unordered map of dynamically typed values. */ + fields: { [key: string]: any | undefined }; +} + +export interface Struct_FieldsEntry { + key: string; + value: any | undefined; +} + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of these + * variants. Absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + */ +export interface Value { + /** Represents a null value. */ + nullValue?: + | NullValue + | undefined; + /** Represents a double value. */ + numberValue?: + | number + | undefined; + /** Represents a string value. */ + stringValue?: + | string + | undefined; + /** Represents a boolean value. */ + boolValue?: + | boolean + | undefined; + /** Represents a structured value. */ + structValue?: + | { [key: string]: any } + | undefined; + /** Represents a repeated `Value`. */ + listValue?: Array | undefined; +} + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + */ +export interface ListValue { + /** Repeated field of dynamically typed values. */ + values: any[]; +} + +function createBaseStruct(): Struct { + return { fields: {} }; +} + +export const Struct: MessageFns & StructWrapperFns = { + encode(message: Struct, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + globalThis.Object.entries(message.fields).forEach(([key, value]: [string, any | undefined]) => { + if (value !== undefined) { + Struct_FieldsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + } + }); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Struct { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStruct(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + const entry1 = Struct_FieldsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.fields[entry1.key] = entry1.value; + } + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Struct { + return { + fields: isObject(object.fields) + ? (globalThis.Object.entries(object.fields) as [string, any][]).reduce( + (acc: { [key: string]: any | undefined }, [key, value]: [string, any]) => { + acc[key] = value as any | undefined; + return acc; + }, + {}, + ) + : {}, + }; + }, + + toJSON(message: Struct): unknown { + const obj: any = {}; + if (message.fields) { + const entries = globalThis.Object.entries(message.fields) as [string, any | undefined][]; + if (entries.length > 0) { + obj.fields = {}; + entries.forEach(([k, v]) => { + obj.fields[k] = v; + }); + } + } + return obj; + }, + + create, I>>(base?: I): Struct { + return Struct.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Struct { + const message = createBaseStruct(); + message.fields = (globalThis.Object.entries(object.fields ?? {}) as [string, any | undefined][]).reduce( + (acc: { [key: string]: any | undefined }, [key, value]: [string, any | undefined]) => { + if (value !== undefined) { + acc[key] = value; + } + return acc; + }, + {}, + ); + return message; + }, + + wrap(object: { [key: string]: any } | undefined): Struct { + const struct = createBaseStruct(); + + if (object !== undefined) { + for (const key of globalThis.Object.keys(object)) { + struct.fields[key] = object[key]; + } + } + return struct; + }, + + unwrap(message: Struct): { [key: string]: any } { + const object: { [key: string]: any } = {}; + if (message.fields) { + for (const key of globalThis.Object.keys(message.fields)) { + object[key] = message.fields[key]; + } + } + return object; + }, +}; + +function createBaseStruct_FieldsEntry(): Struct_FieldsEntry { + return { key: "", value: undefined }; +} + +export const Struct_FieldsEntry: MessageFns = { + encode(message: Struct_FieldsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== "") { + writer.uint32(10).string(message.key); + } + if (message.value !== undefined) { + Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Struct_FieldsEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStruct_FieldsEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.key = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.value = Value.unwrap(Value.decode(reader, reader.uint32())); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Struct_FieldsEntry { + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + value: isSet(object?.value) ? object.value : undefined, + }; + }, + + toJSON(message: Struct_FieldsEntry): unknown { + const obj: any = {}; + if (message.key !== "") { + obj.key = message.key; + } + if (message.value !== undefined) { + obj.value = message.value; + } + return obj; + }, + + create, I>>(base?: I): Struct_FieldsEntry { + return Struct_FieldsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Struct_FieldsEntry { + const message = createBaseStruct_FieldsEntry(); + message.key = object.key ?? ""; + message.value = object.value ?? undefined; + return message; + }, +}; + +function createBaseValue(): Value { + return { + nullValue: undefined, + numberValue: undefined, + stringValue: undefined, + boolValue: undefined, + structValue: undefined, + listValue: undefined, + }; +} + +export const Value: MessageFns & AnyValueWrapperFns = { + encode(message: Value, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.nullValue !== undefined) { + writer.uint32(8).int32(message.nullValue); + } + if (message.numberValue !== undefined) { + writer.uint32(17).double(message.numberValue); + } + if (message.stringValue !== undefined) { + writer.uint32(26).string(message.stringValue); + } + if (message.boolValue !== undefined) { + writer.uint32(32).bool(message.boolValue); + } + if (message.structValue !== undefined) { + Struct.encode(Struct.wrap(message.structValue), writer.uint32(42).fork()).join(); + } + if (message.listValue !== undefined) { + ListValue.encode(ListValue.wrap(message.listValue), writer.uint32(50).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Value { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.nullValue = reader.int32() as any; + continue; + } + case 2: { + if (tag !== 17) { + break; + } + + message.numberValue = reader.double(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.stringValue = reader.string(); + continue; + } + case 4: { + if (tag !== 32) { + break; + } + + message.boolValue = reader.bool(); + continue; + } + case 5: { + if (tag !== 42) { + break; + } + + message.structValue = Struct.unwrap(Struct.decode(reader, reader.uint32())); + continue; + } + case 6: { + if (tag !== 50) { + break; + } + + message.listValue = ListValue.unwrap(ListValue.decode(reader, reader.uint32())); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Value { + return { + nullValue: isSet(object.nullValue) + ? nullValueFromJSON(object.nullValue) + : isSet(object.null_value) + ? nullValueFromJSON(object.null_value) + : undefined, + numberValue: isSet(object.numberValue) + ? globalThis.Number(object.numberValue) + : isSet(object.number_value) + ? globalThis.Number(object.number_value) + : undefined, + stringValue: isSet(object.stringValue) + ? globalThis.String(object.stringValue) + : isSet(object.string_value) + ? globalThis.String(object.string_value) + : undefined, + boolValue: isSet(object.boolValue) + ? globalThis.Boolean(object.boolValue) + : isSet(object.bool_value) + ? globalThis.Boolean(object.bool_value) + : undefined, + structValue: isObject(object.structValue) + ? object.structValue + : isObject(object.struct_value) + ? object.struct_value + : undefined, + listValue: globalThis.Array.isArray(object.listValue) + ? [...object.listValue] + : globalThis.Array.isArray(object.list_value) + ? [...object.list_value] + : undefined, + }; + }, + + toJSON(message: Value): unknown { + const obj: any = {}; + if (message.nullValue !== undefined) { + obj.nullValue = nullValueToJSON(message.nullValue); + } + if (message.numberValue !== undefined) { + obj.numberValue = message.numberValue; + } + if (message.stringValue !== undefined) { + obj.stringValue = message.stringValue; + } + if (message.boolValue !== undefined) { + obj.boolValue = message.boolValue; + } + if (message.structValue !== undefined) { + obj.structValue = message.structValue; + } + if (message.listValue !== undefined) { + obj.listValue = message.listValue; + } + return obj; + }, + + create, I>>(base?: I): Value { + return Value.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Value { + const message = createBaseValue(); + message.nullValue = object.nullValue ?? undefined; + message.numberValue = object.numberValue ?? undefined; + message.stringValue = object.stringValue ?? undefined; + message.boolValue = object.boolValue ?? undefined; + message.structValue = object.structValue ?? undefined; + message.listValue = object.listValue ?? undefined; + return message; + }, + + wrap(value: any): Value { + const result = createBaseValue(); + if (value === null) { + result.nullValue = NullValue.NULL_VALUE; + } else if (typeof value === "boolean") { + result.boolValue = value; + } else if (typeof value === "number") { + result.numberValue = value; + } else if (typeof value === "string") { + result.stringValue = value; + } else if (globalThis.Array.isArray(value)) { + result.listValue = value; + } else if (typeof value === "object") { + result.structValue = value; + } else if (typeof value !== "undefined") { + throw new globalThis.Error("Unsupported any value type: " + typeof value); + } + return result; + }, + + unwrap(message: any): string | number | boolean | Object | null | Array | undefined { + if (message.stringValue !== undefined) { + return message.stringValue; + } else if (message?.numberValue !== undefined) { + return message.numberValue; + } else if (message?.boolValue !== undefined) { + return message.boolValue; + } else if (message?.structValue !== undefined) { + return message.structValue as any; + } else if (message?.listValue !== undefined) { + return message.listValue; + } else if (message?.nullValue !== undefined) { + return null; + } + return undefined; + }, +}; + +function createBaseListValue(): ListValue { + return { values: [] }; +} + +export const ListValue: MessageFns & ListValueWrapperFns = { + encode(message: ListValue, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + for (const v of message.values) { + Value.encode(Value.wrap(v!), writer.uint32(10).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ListValue { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseListValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.values.push(Value.unwrap(Value.decode(reader, reader.uint32()))); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ListValue { + return { values: globalThis.Array.isArray(object?.values) ? [...object.values] : [] }; + }, + + toJSON(message: ListValue): unknown { + const obj: any = {}; + if (message.values?.length) { + obj.values = message.values; + } + return obj; + }, + + create, I>>(base?: I): ListValue { + return ListValue.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ListValue { + const message = createBaseListValue(); + message.values = object.values?.map((e) => e) || []; + return message; + }, + + wrap(array: Array | undefined): ListValue { + const result = createBaseListValue(); + result.values = array ?? []; + return result; + }, + + unwrap(message: ListValue): Array { + if (message?.hasOwnProperty("values") && globalThis.Array.isArray(message.values)) { + return message.values; + } else { + return message as any; + } + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} + +export interface StructWrapperFns { + wrap(object: { [key: string]: any } | undefined): Struct; + unwrap(message: Struct): { [key: string]: any }; +} + +export interface AnyValueWrapperFns { + wrap(value: any): Value; + unwrap(message: any): string | number | boolean | Object | null | Array | undefined; +} + +export interface ListValueWrapperFns { + wrap(array: Array | undefined): ListValue; + unwrap(message: ListValue): Array; +} diff --git a/generated/typescript/google/protobuf/timestamp.ts b/generated/typescript/google/protobuf/timestamp.ts new file mode 100644 index 0000000..894def8 --- /dev/null +++ b/generated/typescript/google/protobuf/timestamp.ts @@ -0,0 +1,230 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.11.6 +// protoc unknown +// source: google/protobuf/timestamp.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export const protobufPackage = "google.protobuf"; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * Example 6: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard + * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using + * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + * the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime() + * ) to obtain a formatter capable of generating timestamps in this format. + */ +export interface Timestamp { + /** + * Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must + * be between -315576000000 and 315576000000 inclusive (which corresponds to + * 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z). + */ + seconds: number; + /** + * Non-negative fractions of a second at nanosecond resolution. This field is + * the nanosecond portion of the duration, not an alternative to seconds. + * Negative second values with fractions must still have non-negative nanos + * values that count forward in time. Must be between 0 and 999,999,999 + * inclusive. + */ + nanos: number; +} + +function createBaseTimestamp(): Timestamp { + return { seconds: 0, nanos: 0 }; +} + +export const Timestamp: MessageFns = { + encode(message: Timestamp, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.seconds !== 0) { + writer.uint32(8).int64(message.seconds); + } + if (message.nanos !== 0) { + writer.uint32(16).int32(message.nanos); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Timestamp { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseTimestamp(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.seconds = longToNumber(reader.int64()); + continue; + } + case 2: { + if (tag !== 16) { + break; + } + + message.nanos = reader.int32(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Timestamp { + return { + seconds: isSet(object.seconds) ? globalThis.Number(object.seconds) : 0, + nanos: isSet(object.nanos) ? globalThis.Number(object.nanos) : 0, + }; + }, + + toJSON(message: Timestamp): unknown { + const obj: any = {}; + if (message.seconds !== 0) { + obj.seconds = Math.round(message.seconds); + } + if (message.nanos !== 0) { + obj.nanos = Math.round(message.nanos); + } + return obj; + }, + + create, I>>(base?: I): Timestamp { + return Timestamp.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Timestamp { + const message = createBaseTimestamp(); + message.seconds = object.seconds ?? 0; + message.nanos = object.nanos ?? 0; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function longToNumber(int64: { toString(): string }): number { + const num = globalThis.Number(int64.toString()); + if (num > globalThis.Number.MAX_SAFE_INTEGER) { + throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); + } + if (num < globalThis.Number.MIN_SAFE_INTEGER) { + throw new globalThis.Error("Value is smaller than Number.MIN_SAFE_INTEGER"); + } + return num; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/generated/typescript/vtuber/v1/conversation.ts b/generated/typescript/vtuber/v1/conversation.ts new file mode 100644 index 0000000..a179a3d --- /dev/null +++ b/generated/typescript/vtuber/v1/conversation.ts @@ -0,0 +1,610 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.11.6 +// protoc unknown +// source: vtuber/v1/conversation.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; +import { Timestamp } from "../../google/protobuf/timestamp"; +import { PersonaId, personaIdFromJSON, personaIdToJSON } from "./persona"; +import { ToolCall } from "./tool_call"; +import { + AudioFormat, + audioFormatFromJSON, + audioFormatToJSON, + Emotion, + emotionFromJSON, + emotionToJSON, +} from "./voice_profile"; + +export const protobufPackage = "vtuber.v1"; + +/** + * ConversationDirective is the single message vtuber-brain (the Director) + * emits on every turn and vtuber-voice (the Performer) consumes. Per + * ADR-002 this is the only protocol boundary between the two services. + * Full audio streaming back to the Director is out of scope for v0.1. + */ +export interface ConversationDirective { + /** Opaque per-turn id. Consumers MUST NOT parse it. UUIDv7 preferred. */ + directiveId: string; + /** Emission time per the Director's clock. */ + emittedAt: + | Date + | undefined; + /** The persona to wear for this turn. */ + personaId: PersonaId; + /** + * Text the Performer should speak. The Director owns all LLM + * post-processing (sanitization, length trim) before emitting. + */ + textPrompt: string; + /** + * Optional per-turn voice priming seed. When empty, the Performer + * falls back to the persona's registered VoiceProfile in vtuber-commons. + */ + voicePrompt: string; + /** Per-turn emotion override. UNSPECIFIED means "use neutral". */ + emotion: Emotion; + /** Requested output audio format. */ + targetAudioFormat: AudioFormat; + /** + * Soft upper bound on total synthesis latency in milliseconds. + * 0 means unspecified — the Performer applies its default SLO. + */ + maxLatencyMs: number; + /** + * Decentralized Tool Calls: These are intended for the Performer (Voice/Live2D) + * to execute in sync with the speech (e.g., "animate", "play_sound_effect"). + */ + toolCalls: ToolCall[]; +} + +/** + * DirectiveAck is the Performer's synchronous reply to EmitDirective. + * A negative ack carries a stable short code; consumers branch on the + * code, not on human-readable text. + */ +export interface DirectiveAck { + directiveId: string; + accepted: boolean; + /** + * Stable short code when accepted is false: + * "persona_unknown", "format_unsupported", "queue_full", + * "voice_profile_missing". Empty when accepted is true. + */ + rejectReason: string; +} + +/** + * EmitDirectiveRequest wraps ConversationDirective for the rpc surface. + * The wrapper exists because buf STANDARD lint requires rpc request/response + * types to be named after the rpc — and because wrappers leave room for + * per-rpc metadata (idempotency keys, request tracing) to be added without + * touching the domain message. + */ +export interface EmitDirectiveRequest { + directive: ConversationDirective | undefined; +} + +/** EmitDirectiveResponse wraps DirectiveAck for the same reasons. */ +export interface EmitDirectiveResponse { + ack: DirectiveAck | undefined; +} + +function createBaseConversationDirective(): ConversationDirective { + return { + directiveId: "", + emittedAt: undefined, + personaId: 0, + textPrompt: "", + voicePrompt: "", + emotion: 0, + targetAudioFormat: 0, + maxLatencyMs: 0, + toolCalls: [], + }; +} + +export const ConversationDirective: MessageFns = { + encode(message: ConversationDirective, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.directiveId !== "") { + writer.uint32(10).string(message.directiveId); + } + if (message.emittedAt !== undefined) { + Timestamp.encode(toTimestamp(message.emittedAt), writer.uint32(18).fork()).join(); + } + if (message.personaId !== 0) { + writer.uint32(24).int32(message.personaId); + } + if (message.textPrompt !== "") { + writer.uint32(34).string(message.textPrompt); + } + if (message.voicePrompt !== "") { + writer.uint32(42).string(message.voicePrompt); + } + if (message.emotion !== 0) { + writer.uint32(48).int32(message.emotion); + } + if (message.targetAudioFormat !== 0) { + writer.uint32(56).int32(message.targetAudioFormat); + } + if (message.maxLatencyMs !== 0) { + writer.uint32(64).uint32(message.maxLatencyMs); + } + for (const v of message.toolCalls) { + ToolCall.encode(v!, writer.uint32(74).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ConversationDirective { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseConversationDirective(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.directiveId = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.emittedAt = fromTimestamp(Timestamp.decode(reader, reader.uint32())); + continue; + } + case 3: { + if (tag !== 24) { + break; + } + + message.personaId = reader.int32() as any; + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + message.textPrompt = reader.string(); + continue; + } + case 5: { + if (tag !== 42) { + break; + } + + message.voicePrompt = reader.string(); + continue; + } + case 6: { + if (tag !== 48) { + break; + } + + message.emotion = reader.int32() as any; + continue; + } + case 7: { + if (tag !== 56) { + break; + } + + message.targetAudioFormat = reader.int32() as any; + continue; + } + case 8: { + if (tag !== 64) { + break; + } + + message.maxLatencyMs = reader.uint32(); + continue; + } + case 9: { + if (tag !== 74) { + break; + } + + message.toolCalls.push(ToolCall.decode(reader, reader.uint32())); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ConversationDirective { + return { + directiveId: isSet(object.directiveId) + ? globalThis.String(object.directiveId) + : isSet(object.directive_id) + ? globalThis.String(object.directive_id) + : "", + emittedAt: isSet(object.emittedAt) + ? fromJsonTimestamp(object.emittedAt) + : isSet(object.emitted_at) + ? fromJsonTimestamp(object.emitted_at) + : undefined, + personaId: isSet(object.personaId) + ? personaIdFromJSON(object.personaId) + : isSet(object.persona_id) + ? personaIdFromJSON(object.persona_id) + : 0, + textPrompt: isSet(object.textPrompt) + ? globalThis.String(object.textPrompt) + : isSet(object.text_prompt) + ? globalThis.String(object.text_prompt) + : "", + voicePrompt: isSet(object.voicePrompt) + ? globalThis.String(object.voicePrompt) + : isSet(object.voice_prompt) + ? globalThis.String(object.voice_prompt) + : "", + emotion: isSet(object.emotion) ? emotionFromJSON(object.emotion) : 0, + targetAudioFormat: isSet(object.targetAudioFormat) + ? audioFormatFromJSON(object.targetAudioFormat) + : isSet(object.target_audio_format) + ? audioFormatFromJSON(object.target_audio_format) + : 0, + maxLatencyMs: isSet(object.maxLatencyMs) + ? globalThis.Number(object.maxLatencyMs) + : isSet(object.max_latency_ms) + ? globalThis.Number(object.max_latency_ms) + : 0, + toolCalls: globalThis.Array.isArray(object?.toolCalls) + ? object.toolCalls.map((e: any) => ToolCall.fromJSON(e)) + : globalThis.Array.isArray(object?.tool_calls) + ? object.tool_calls.map((e: any) => ToolCall.fromJSON(e)) + : [], + }; + }, + + toJSON(message: ConversationDirective): unknown { + const obj: any = {}; + if (message.directiveId !== "") { + obj.directiveId = message.directiveId; + } + if (message.emittedAt !== undefined) { + obj.emittedAt = message.emittedAt.toISOString(); + } + if (message.personaId !== 0) { + obj.personaId = personaIdToJSON(message.personaId); + } + if (message.textPrompt !== "") { + obj.textPrompt = message.textPrompt; + } + if (message.voicePrompt !== "") { + obj.voicePrompt = message.voicePrompt; + } + if (message.emotion !== 0) { + obj.emotion = emotionToJSON(message.emotion); + } + if (message.targetAudioFormat !== 0) { + obj.targetAudioFormat = audioFormatToJSON(message.targetAudioFormat); + } + if (message.maxLatencyMs !== 0) { + obj.maxLatencyMs = Math.round(message.maxLatencyMs); + } + if (message.toolCalls?.length) { + obj.toolCalls = message.toolCalls.map((e) => ToolCall.toJSON(e)); + } + return obj; + }, + + create, I>>(base?: I): ConversationDirective { + return ConversationDirective.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ConversationDirective { + const message = createBaseConversationDirective(); + message.directiveId = object.directiveId ?? ""; + message.emittedAt = object.emittedAt ?? undefined; + message.personaId = object.personaId ?? 0; + message.textPrompt = object.textPrompt ?? ""; + message.voicePrompt = object.voicePrompt ?? ""; + message.emotion = object.emotion ?? 0; + message.targetAudioFormat = object.targetAudioFormat ?? 0; + message.maxLatencyMs = object.maxLatencyMs ?? 0; + message.toolCalls = object.toolCalls?.map((e) => ToolCall.fromPartial(e)) || []; + return message; + }, +}; + +function createBaseDirectiveAck(): DirectiveAck { + return { directiveId: "", accepted: false, rejectReason: "" }; +} + +export const DirectiveAck: MessageFns = { + encode(message: DirectiveAck, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.directiveId !== "") { + writer.uint32(10).string(message.directiveId); + } + if (message.accepted !== false) { + writer.uint32(16).bool(message.accepted); + } + if (message.rejectReason !== "") { + writer.uint32(26).string(message.rejectReason); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): DirectiveAck { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDirectiveAck(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.directiveId = reader.string(); + continue; + } + case 2: { + if (tag !== 16) { + break; + } + + message.accepted = reader.bool(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.rejectReason = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): DirectiveAck { + return { + directiveId: isSet(object.directiveId) + ? globalThis.String(object.directiveId) + : isSet(object.directive_id) + ? globalThis.String(object.directive_id) + : "", + accepted: isSet(object.accepted) ? globalThis.Boolean(object.accepted) : false, + rejectReason: isSet(object.rejectReason) + ? globalThis.String(object.rejectReason) + : isSet(object.reject_reason) + ? globalThis.String(object.reject_reason) + : "", + }; + }, + + toJSON(message: DirectiveAck): unknown { + const obj: any = {}; + if (message.directiveId !== "") { + obj.directiveId = message.directiveId; + } + if (message.accepted !== false) { + obj.accepted = message.accepted; + } + if (message.rejectReason !== "") { + obj.rejectReason = message.rejectReason; + } + return obj; + }, + + create, I>>(base?: I): DirectiveAck { + return DirectiveAck.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): DirectiveAck { + const message = createBaseDirectiveAck(); + message.directiveId = object.directiveId ?? ""; + message.accepted = object.accepted ?? false; + message.rejectReason = object.rejectReason ?? ""; + return message; + }, +}; + +function createBaseEmitDirectiveRequest(): EmitDirectiveRequest { + return { directive: undefined }; +} + +export const EmitDirectiveRequest: MessageFns = { + encode(message: EmitDirectiveRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.directive !== undefined) { + ConversationDirective.encode(message.directive, writer.uint32(10).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): EmitDirectiveRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseEmitDirectiveRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.directive = ConversationDirective.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): EmitDirectiveRequest { + return { directive: isSet(object.directive) ? ConversationDirective.fromJSON(object.directive) : undefined }; + }, + + toJSON(message: EmitDirectiveRequest): unknown { + const obj: any = {}; + if (message.directive !== undefined) { + obj.directive = ConversationDirective.toJSON(message.directive); + } + return obj; + }, + + create, I>>(base?: I): EmitDirectiveRequest { + return EmitDirectiveRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): EmitDirectiveRequest { + const message = createBaseEmitDirectiveRequest(); + message.directive = (object.directive !== undefined && object.directive !== null) + ? ConversationDirective.fromPartial(object.directive) + : undefined; + return message; + }, +}; + +function createBaseEmitDirectiveResponse(): EmitDirectiveResponse { + return { ack: undefined }; +} + +export const EmitDirectiveResponse: MessageFns = { + encode(message: EmitDirectiveResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.ack !== undefined) { + DirectiveAck.encode(message.ack, writer.uint32(10).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): EmitDirectiveResponse { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseEmitDirectiveResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.ack = DirectiveAck.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): EmitDirectiveResponse { + return { ack: isSet(object.ack) ? DirectiveAck.fromJSON(object.ack) : undefined }; + }, + + toJSON(message: EmitDirectiveResponse): unknown { + const obj: any = {}; + if (message.ack !== undefined) { + obj.ack = DirectiveAck.toJSON(message.ack); + } + return obj; + }, + + create, I>>(base?: I): EmitDirectiveResponse { + return EmitDirectiveResponse.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): EmitDirectiveResponse { + const message = createBaseEmitDirectiveResponse(); + message.ack = (object.ack !== undefined && object.ack !== null) ? DirectiveAck.fromPartial(object.ack) : undefined; + return message; + }, +}; + +/** + * DirectorService is the minimal service surface needed to validate tonic / + * buf service codegen end-to-end for v0.1. The full audio streaming rpc + * lives on a separate service added in the brain↔voice slice. + */ +export type DirectorServiceDefinition = typeof DirectorServiceDefinition; +export const DirectorServiceDefinition = { + name: "DirectorService", + fullName: "vtuber.v1.DirectorService", + methods: { + emitDirective: { + name: "EmitDirective", + requestType: EmitDirectiveRequest as typeof EmitDirectiveRequest, + requestStream: false, + responseType: EmitDirectiveResponse as typeof EmitDirectiveResponse, + responseStream: false, + options: {}, + }, + }, +} as const; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function toTimestamp(date: Date): Timestamp { + const seconds = Math.trunc(date.getTime() / 1_000); + const nanos = (date.getTime() % 1_000) * 1_000_000; + return { seconds, nanos }; +} + +function fromTimestamp(t: Timestamp): Date { + let millis = (t.seconds || 0) * 1_000; + millis += (t.nanos || 0) / 1_000_000; + return new globalThis.Date(millis); +} + +function fromJsonTimestamp(o: any): Date { + if (o instanceof globalThis.Date) { + return o; + } else if (typeof o === "string") { + return new globalThis.Date(o); + } else { + return fromTimestamp(Timestamp.fromJSON(o)); + } +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/generated/typescript/vtuber/v1/persona.ts b/generated/typescript/vtuber/v1/persona.ts new file mode 100644 index 0000000..f926b47 --- /dev/null +++ b/generated/typescript/vtuber/v1/persona.ts @@ -0,0 +1,272 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.11.6 +// protoc unknown +// source: vtuber/v1/persona.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export const protobufPackage = "vtuber.v1"; + +/** + * PersonaId is the canonical enum of the five VTuber personas. + * PERSONA_ID_UNSPECIFIED is the proto3 zero-value and MUST be treated as an + * error by consumers — no persona should ever round-trip as unspecified. + */ +export enum PersonaId { + PERSONA_ID_UNSPECIFIED = 0, + PERSONA_ID_VALORA = 1, + PERSONA_ID_AURORA = 2, + PERSONA_ID_AMETRA = 3, + PERSONA_ID_ASTRAEA = 4, + PERSONA_ID_ELDORA = 5, + UNRECOGNIZED = -1, +} + +export function personaIdFromJSON(object: any): PersonaId { + switch (object) { + case 0: + case "PERSONA_ID_UNSPECIFIED": + return PersonaId.PERSONA_ID_UNSPECIFIED; + case 1: + case "PERSONA_ID_VALORA": + return PersonaId.PERSONA_ID_VALORA; + case 2: + case "PERSONA_ID_AURORA": + return PersonaId.PERSONA_ID_AURORA; + case 3: + case "PERSONA_ID_AMETRA": + return PersonaId.PERSONA_ID_AMETRA; + case 4: + case "PERSONA_ID_ASTRAEA": + return PersonaId.PERSONA_ID_ASTRAEA; + case 5: + case "PERSONA_ID_ELDORA": + return PersonaId.PERSONA_ID_ELDORA; + case -1: + case "UNRECOGNIZED": + default: + return PersonaId.UNRECOGNIZED; + } +} + +export function personaIdToJSON(object: PersonaId): string { + switch (object) { + case PersonaId.PERSONA_ID_UNSPECIFIED: + return "PERSONA_ID_UNSPECIFIED"; + case PersonaId.PERSONA_ID_VALORA: + return "PERSONA_ID_VALORA"; + case PersonaId.PERSONA_ID_AURORA: + return "PERSONA_ID_AURORA"; + case PersonaId.PERSONA_ID_AMETRA: + return "PERSONA_ID_AMETRA"; + case PersonaId.PERSONA_ID_ASTRAEA: + return "PERSONA_ID_ASTRAEA"; + case PersonaId.PERSONA_ID_ELDORA: + return "PERSONA_ID_ELDORA"; + case PersonaId.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + +/** + * Persona captures every static attribute of a VTuber persona: display name, + * trigger keywords, lore tags, brand colour. Runtime voice parameters live + * in VoiceProfile; per-turn emotion lives in ConversationDirective. The + * source of truth for Persona instances is a YAML file in vtuber-commons; + * this proto is the shape that commons validates against on load. + */ +export interface Persona { + id: PersonaId; + displayName: string; + description: string; + /** Trigger keywords that bias the Director toward this persona. */ + activationKeywords: string[]; + /** Freeform lore tags used for memory retrieval and character consistency. */ + loreTags: string[]; + /** Brand colour as a CSS hex string (e.g. "#FF3C3C"). */ + colorHex: string; +} + +function createBasePersona(): Persona { + return { id: 0, displayName: "", description: "", activationKeywords: [], loreTags: [], colorHex: "" }; +} + +export const Persona: MessageFns = { + encode(message: Persona, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.id !== 0) { + writer.uint32(8).int32(message.id); + } + if (message.displayName !== "") { + writer.uint32(18).string(message.displayName); + } + if (message.description !== "") { + writer.uint32(26).string(message.description); + } + for (const v of message.activationKeywords) { + writer.uint32(34).string(v!); + } + for (const v of message.loreTags) { + writer.uint32(42).string(v!); + } + if (message.colorHex !== "") { + writer.uint32(50).string(message.colorHex); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Persona { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePersona(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.id = reader.int32() as any; + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.displayName = reader.string(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.description = reader.string(); + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + message.activationKeywords.push(reader.string()); + continue; + } + case 5: { + if (tag !== 42) { + break; + } + + message.loreTags.push(reader.string()); + continue; + } + case 6: { + if (tag !== 50) { + break; + } + + message.colorHex = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Persona { + return { + id: isSet(object.id) ? personaIdFromJSON(object.id) : 0, + displayName: isSet(object.displayName) + ? globalThis.String(object.displayName) + : isSet(object.display_name) + ? globalThis.String(object.display_name) + : "", + description: isSet(object.description) ? globalThis.String(object.description) : "", + activationKeywords: globalThis.Array.isArray(object?.activationKeywords) + ? object.activationKeywords.map((e: any) => globalThis.String(e)) + : globalThis.Array.isArray(object?.activation_keywords) + ? object.activation_keywords.map((e: any) => globalThis.String(e)) + : [], + loreTags: globalThis.Array.isArray(object?.loreTags) + ? object.loreTags.map((e: any) => globalThis.String(e)) + : globalThis.Array.isArray(object?.lore_tags) + ? object.lore_tags.map((e: any) => globalThis.String(e)) + : [], + colorHex: isSet(object.colorHex) + ? globalThis.String(object.colorHex) + : isSet(object.color_hex) + ? globalThis.String(object.color_hex) + : "", + }; + }, + + toJSON(message: Persona): unknown { + const obj: any = {}; + if (message.id !== 0) { + obj.id = personaIdToJSON(message.id); + } + if (message.displayName !== "") { + obj.displayName = message.displayName; + } + if (message.description !== "") { + obj.description = message.description; + } + if (message.activationKeywords?.length) { + obj.activationKeywords = message.activationKeywords; + } + if (message.loreTags?.length) { + obj.loreTags = message.loreTags; + } + if (message.colorHex !== "") { + obj.colorHex = message.colorHex; + } + return obj; + }, + + create, I>>(base?: I): Persona { + return Persona.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Persona { + const message = createBasePersona(); + message.id = object.id ?? 0; + message.displayName = object.displayName ?? ""; + message.description = object.description ?? ""; + message.activationKeywords = object.activationKeywords?.map((e) => e) || []; + message.loreTags = object.loreTags?.map((e) => e) || []; + message.colorHex = object.colorHex ?? ""; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/generated/typescript/vtuber/v1/tool_call.ts b/generated/typescript/vtuber/v1/tool_call.ts new file mode 100644 index 0000000..cf234e9 --- /dev/null +++ b/generated/typescript/vtuber/v1/tool_call.ts @@ -0,0 +1,511 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.11.6 +// protoc unknown +// source: vtuber/v1/tool_call.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; +import { Struct } from "../../google/protobuf/struct"; + +export const protobufPackage = "vtuber.v1"; + +/** + * ToolCall represents a request from the Director (vtuber-brain) to execute + * a specific function. In the Hybrid model, these are embedded in the + * ConversationDirective for execution by the Performer or handled internally. + */ +export interface ToolCall { + /** Unique identifier for this call. Used to correlate with ToolResponse. */ + callId: string; + /** The name of the tool to be called (e.g., "animate", "play_sound", "web_search"). */ + name: string; + /** + * Arguments for the tool call, structured as a JSON-like object. + * This matches the format used by major LLM providers (OpenAI, Anthropic). + */ + arguments: + | { [key: string]: any } + | undefined; + /** Metadata to guide the execution. */ + metadata: { [key: string]: string }; +} + +export interface ToolCall_MetadataEntry { + key: string; + value: string; +} + +/** ToolResponse captures the result of a tool execution. */ +export interface ToolResponse { + /** Matches the call_id from the ToolCall. */ + callId: string; + /** The output of the tool, typically a JSON string or descriptive text. */ + content: string; + /** If true, indicates the tool execution failed. */ + isError: boolean; + /** Stable error code if is_error is true (e.g., "timeout", "not_found"). */ + errorCode: string; +} + +/** ToolDefinition is used by the Director to register available tools. */ +export interface ToolDefinition { + name: string; + description: string; + /** JSON Schema representing the expected arguments. */ + parameters: { [key: string]: any } | undefined; +} + +function createBaseToolCall(): ToolCall { + return { callId: "", name: "", arguments: undefined, metadata: {} }; +} + +export const ToolCall: MessageFns = { + encode(message: ToolCall, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.callId !== "") { + writer.uint32(10).string(message.callId); + } + if (message.name !== "") { + writer.uint32(18).string(message.name); + } + if (message.arguments !== undefined) { + Struct.encode(Struct.wrap(message.arguments), writer.uint32(26).fork()).join(); + } + globalThis.Object.entries(message.metadata).forEach(([key, value]: [string, string]) => { + ToolCall_MetadataEntry.encode({ key: key as any, value }, writer.uint32(34).fork()).join(); + }); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ToolCall { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseToolCall(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.callId = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.name = reader.string(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.arguments = Struct.unwrap(Struct.decode(reader, reader.uint32())); + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + const entry4 = ToolCall_MetadataEntry.decode(reader, reader.uint32()); + if (entry4.value !== undefined) { + message.metadata[entry4.key] = entry4.value; + } + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ToolCall { + return { + callId: isSet(object.callId) + ? globalThis.String(object.callId) + : isSet(object.call_id) + ? globalThis.String(object.call_id) + : "", + name: isSet(object.name) ? globalThis.String(object.name) : "", + arguments: isObject(object.arguments) ? object.arguments : undefined, + metadata: isObject(object.metadata) + ? (globalThis.Object.entries(object.metadata) as [string, any][]).reduce( + (acc: { [key: string]: string }, [key, value]: [string, any]) => { + acc[key] = globalThis.String(value); + return acc; + }, + {}, + ) + : {}, + }; + }, + + toJSON(message: ToolCall): unknown { + const obj: any = {}; + if (message.callId !== "") { + obj.callId = message.callId; + } + if (message.name !== "") { + obj.name = message.name; + } + if (message.arguments !== undefined) { + obj.arguments = message.arguments; + } + if (message.metadata) { + const entries = globalThis.Object.entries(message.metadata) as [string, string][]; + if (entries.length > 0) { + obj.metadata = {}; + entries.forEach(([k, v]) => { + obj.metadata[k] = v; + }); + } + } + return obj; + }, + + create, I>>(base?: I): ToolCall { + return ToolCall.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ToolCall { + const message = createBaseToolCall(); + message.callId = object.callId ?? ""; + message.name = object.name ?? ""; + message.arguments = object.arguments ?? undefined; + message.metadata = (globalThis.Object.entries(object.metadata ?? {}) as [string, string][]).reduce( + (acc: { [key: string]: string }, [key, value]: [string, string]) => { + if (value !== undefined) { + acc[key] = globalThis.String(value); + } + return acc; + }, + {}, + ); + return message; + }, +}; + +function createBaseToolCall_MetadataEntry(): ToolCall_MetadataEntry { + return { key: "", value: "" }; +} + +export const ToolCall_MetadataEntry: MessageFns = { + encode(message: ToolCall_MetadataEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== "") { + writer.uint32(10).string(message.key); + } + if (message.value !== "") { + writer.uint32(18).string(message.value); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ToolCall_MetadataEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseToolCall_MetadataEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.key = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.value = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ToolCall_MetadataEntry { + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + value: isSet(object.value) ? globalThis.String(object.value) : "", + }; + }, + + toJSON(message: ToolCall_MetadataEntry): unknown { + const obj: any = {}; + if (message.key !== "") { + obj.key = message.key; + } + if (message.value !== "") { + obj.value = message.value; + } + return obj; + }, + + create, I>>(base?: I): ToolCall_MetadataEntry { + return ToolCall_MetadataEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ToolCall_MetadataEntry { + const message = createBaseToolCall_MetadataEntry(); + message.key = object.key ?? ""; + message.value = object.value ?? ""; + return message; + }, +}; + +function createBaseToolResponse(): ToolResponse { + return { callId: "", content: "", isError: false, errorCode: "" }; +} + +export const ToolResponse: MessageFns = { + encode(message: ToolResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.callId !== "") { + writer.uint32(10).string(message.callId); + } + if (message.content !== "") { + writer.uint32(18).string(message.content); + } + if (message.isError !== false) { + writer.uint32(24).bool(message.isError); + } + if (message.errorCode !== "") { + writer.uint32(34).string(message.errorCode); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ToolResponse { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseToolResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.callId = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.content = reader.string(); + continue; + } + case 3: { + if (tag !== 24) { + break; + } + + message.isError = reader.bool(); + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + message.errorCode = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ToolResponse { + return { + callId: isSet(object.callId) + ? globalThis.String(object.callId) + : isSet(object.call_id) + ? globalThis.String(object.call_id) + : "", + content: isSet(object.content) ? globalThis.String(object.content) : "", + isError: isSet(object.isError) + ? globalThis.Boolean(object.isError) + : isSet(object.is_error) + ? globalThis.Boolean(object.is_error) + : false, + errorCode: isSet(object.errorCode) + ? globalThis.String(object.errorCode) + : isSet(object.error_code) + ? globalThis.String(object.error_code) + : "", + }; + }, + + toJSON(message: ToolResponse): unknown { + const obj: any = {}; + if (message.callId !== "") { + obj.callId = message.callId; + } + if (message.content !== "") { + obj.content = message.content; + } + if (message.isError !== false) { + obj.isError = message.isError; + } + if (message.errorCode !== "") { + obj.errorCode = message.errorCode; + } + return obj; + }, + + create, I>>(base?: I): ToolResponse { + return ToolResponse.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ToolResponse { + const message = createBaseToolResponse(); + message.callId = object.callId ?? ""; + message.content = object.content ?? ""; + message.isError = object.isError ?? false; + message.errorCode = object.errorCode ?? ""; + return message; + }, +}; + +function createBaseToolDefinition(): ToolDefinition { + return { name: "", description: "", parameters: undefined }; +} + +export const ToolDefinition: MessageFns = { + encode(message: ToolDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.name !== "") { + writer.uint32(10).string(message.name); + } + if (message.description !== "") { + writer.uint32(18).string(message.description); + } + if (message.parameters !== undefined) { + Struct.encode(Struct.wrap(message.parameters), writer.uint32(26).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ToolDefinition { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseToolDefinition(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.name = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.description = reader.string(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.parameters = Struct.unwrap(Struct.decode(reader, reader.uint32())); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ToolDefinition { + return { + name: isSet(object.name) ? globalThis.String(object.name) : "", + description: isSet(object.description) ? globalThis.String(object.description) : "", + parameters: isObject(object.parameters) ? object.parameters : undefined, + }; + }, + + toJSON(message: ToolDefinition): unknown { + const obj: any = {}; + if (message.name !== "") { + obj.name = message.name; + } + if (message.description !== "") { + obj.description = message.description; + } + if (message.parameters !== undefined) { + obj.parameters = message.parameters; + } + return obj; + }, + + create, I>>(base?: I): ToolDefinition { + return ToolDefinition.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ToolDefinition { + const message = createBaseToolDefinition(); + message.name = object.name ?? ""; + message.description = object.description ?? ""; + message.parameters = object.parameters ?? undefined; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/generated/typescript/vtuber/v1/voice_profile.ts b/generated/typescript/vtuber/v1/voice_profile.ts new file mode 100644 index 0000000..420df96 --- /dev/null +++ b/generated/typescript/vtuber/v1/voice_profile.ts @@ -0,0 +1,355 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.11.6 +// protoc unknown +// source: vtuber/v1/voice_profile.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; +import { PersonaId, personaIdFromJSON, personaIdToJSON } from "./persona"; + +export const protobufPackage = "vtuber.v1"; + +/** AudioFormat enumerates the encodings the Performer can stream. */ +export enum AudioFormat { + AUDIO_FORMAT_UNSPECIFIED = 0, + AUDIO_FORMAT_WAV = 1, + AUDIO_FORMAT_OPUS = 2, + AUDIO_FORMAT_MP3 = 3, + UNRECOGNIZED = -1, +} + +export function audioFormatFromJSON(object: any): AudioFormat { + switch (object) { + case 0: + case "AUDIO_FORMAT_UNSPECIFIED": + return AudioFormat.AUDIO_FORMAT_UNSPECIFIED; + case 1: + case "AUDIO_FORMAT_WAV": + return AudioFormat.AUDIO_FORMAT_WAV; + case 2: + case "AUDIO_FORMAT_OPUS": + return AudioFormat.AUDIO_FORMAT_OPUS; + case 3: + case "AUDIO_FORMAT_MP3": + return AudioFormat.AUDIO_FORMAT_MP3; + case -1: + case "UNRECOGNIZED": + default: + return AudioFormat.UNRECOGNIZED; + } +} + +export function audioFormatToJSON(object: AudioFormat): string { + switch (object) { + case AudioFormat.AUDIO_FORMAT_UNSPECIFIED: + return "AUDIO_FORMAT_UNSPECIFIED"; + case AudioFormat.AUDIO_FORMAT_WAV: + return "AUDIO_FORMAT_WAV"; + case AudioFormat.AUDIO_FORMAT_OPUS: + return "AUDIO_FORMAT_OPUS"; + case AudioFormat.AUDIO_FORMAT_MP3: + return "AUDIO_FORMAT_MP3"; + case AudioFormat.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + +/** + * Emotion is the closed set of emotions a persona can be primed with on a + * given turn. Additional variants are appended at the end — never renumber. + */ +export enum Emotion { + EMOTION_UNSPECIFIED = 0, + EMOTION_NEUTRAL = 1, + EMOTION_HAPPY = 2, + EMOTION_SAD = 3, + EMOTION_ANGRY = 4, + EMOTION_PLAYFUL = 5, + EMOTION_ANALYTICAL = 6, + EMOTION_ASMR_CALM = 7, + UNRECOGNIZED = -1, +} + +export function emotionFromJSON(object: any): Emotion { + switch (object) { + case 0: + case "EMOTION_UNSPECIFIED": + return Emotion.EMOTION_UNSPECIFIED; + case 1: + case "EMOTION_NEUTRAL": + return Emotion.EMOTION_NEUTRAL; + case 2: + case "EMOTION_HAPPY": + return Emotion.EMOTION_HAPPY; + case 3: + case "EMOTION_SAD": + return Emotion.EMOTION_SAD; + case 4: + case "EMOTION_ANGRY": + return Emotion.EMOTION_ANGRY; + case 5: + case "EMOTION_PLAYFUL": + return Emotion.EMOTION_PLAYFUL; + case 6: + case "EMOTION_ANALYTICAL": + return Emotion.EMOTION_ANALYTICAL; + case 7: + case "EMOTION_ASMR_CALM": + return Emotion.EMOTION_ASMR_CALM; + case -1: + case "UNRECOGNIZED": + default: + return Emotion.UNRECOGNIZED; + } +} + +export function emotionToJSON(object: Emotion): string { + switch (object) { + case Emotion.EMOTION_UNSPECIFIED: + return "EMOTION_UNSPECIFIED"; + case Emotion.EMOTION_NEUTRAL: + return "EMOTION_NEUTRAL"; + case Emotion.EMOTION_HAPPY: + return "EMOTION_HAPPY"; + case Emotion.EMOTION_SAD: + return "EMOTION_SAD"; + case Emotion.EMOTION_ANGRY: + return "EMOTION_ANGRY"; + case Emotion.EMOTION_PLAYFUL: + return "EMOTION_PLAYFUL"; + case Emotion.EMOTION_ANALYTICAL: + return "EMOTION_ANALYTICAL"; + case Emotion.EMOTION_ASMR_CALM: + return "EMOTION_ASMR_CALM"; + case Emotion.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + +/** + * VoiceProfile is the static voice fingerprint of a persona. base_pitch, + * speaking_rate, and energy feed directly into the Performer's prosody + * layer. style_tag and accent_hint are free-form priming seeds. quirks is + * a small catalog of verbal tics the Performer injects probabilistically. + */ +export interface VoiceProfile { + personaId: PersonaId; + /** Pitch offset in the range -1.0..1.0, where 0.0 is natural pitch. */ + basePitch: number; + /** Rate multiplier in the range 0.5..2.0, where 1.0 is natural speed. */ + speakingRate: number; + /** Vocal energy in the range 0.0..1.0, where 0.0 is monotone. */ + energy: number; + /** Free-form style tag for TTS priming ("asmr", "chipper", "deadpan"...). */ + styleTag: string; + /** Free-form accent hint ("russian", "british", "thai-northern"...). */ + accentHint: string; + /** Verbal tics and filler phrases. */ + quirks: string[]; +} + +function createBaseVoiceProfile(): VoiceProfile { + return { personaId: 0, basePitch: 0, speakingRate: 0, energy: 0, styleTag: "", accentHint: "", quirks: [] }; +} + +export const VoiceProfile: MessageFns = { + encode(message: VoiceProfile, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.personaId !== 0) { + writer.uint32(8).int32(message.personaId); + } + if (message.basePitch !== 0) { + writer.uint32(21).float(message.basePitch); + } + if (message.speakingRate !== 0) { + writer.uint32(29).float(message.speakingRate); + } + if (message.energy !== 0) { + writer.uint32(37).float(message.energy); + } + if (message.styleTag !== "") { + writer.uint32(42).string(message.styleTag); + } + if (message.accentHint !== "") { + writer.uint32(50).string(message.accentHint); + } + for (const v of message.quirks) { + writer.uint32(58).string(v!); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): VoiceProfile { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseVoiceProfile(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.personaId = reader.int32() as any; + continue; + } + case 2: { + if (tag !== 21) { + break; + } + + message.basePitch = reader.float(); + continue; + } + case 3: { + if (tag !== 29) { + break; + } + + message.speakingRate = reader.float(); + continue; + } + case 4: { + if (tag !== 37) { + break; + } + + message.energy = reader.float(); + continue; + } + case 5: { + if (tag !== 42) { + break; + } + + message.styleTag = reader.string(); + continue; + } + case 6: { + if (tag !== 50) { + break; + } + + message.accentHint = reader.string(); + continue; + } + case 7: { + if (tag !== 58) { + break; + } + + message.quirks.push(reader.string()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): VoiceProfile { + return { + personaId: isSet(object.personaId) + ? personaIdFromJSON(object.personaId) + : isSet(object.persona_id) + ? personaIdFromJSON(object.persona_id) + : 0, + basePitch: isSet(object.basePitch) + ? globalThis.Number(object.basePitch) + : isSet(object.base_pitch) + ? globalThis.Number(object.base_pitch) + : 0, + speakingRate: isSet(object.speakingRate) + ? globalThis.Number(object.speakingRate) + : isSet(object.speaking_rate) + ? globalThis.Number(object.speaking_rate) + : 0, + energy: isSet(object.energy) ? globalThis.Number(object.energy) : 0, + styleTag: isSet(object.styleTag) + ? globalThis.String(object.styleTag) + : isSet(object.style_tag) + ? globalThis.String(object.style_tag) + : "", + accentHint: isSet(object.accentHint) + ? globalThis.String(object.accentHint) + : isSet(object.accent_hint) + ? globalThis.String(object.accent_hint) + : "", + quirks: globalThis.Array.isArray(object?.quirks) + ? object.quirks.map((e: any) => globalThis.String(e)) + : [], + }; + }, + + toJSON(message: VoiceProfile): unknown { + const obj: any = {}; + if (message.personaId !== 0) { + obj.personaId = personaIdToJSON(message.personaId); + } + if (message.basePitch !== 0) { + obj.basePitch = message.basePitch; + } + if (message.speakingRate !== 0) { + obj.speakingRate = message.speakingRate; + } + if (message.energy !== 0) { + obj.energy = message.energy; + } + if (message.styleTag !== "") { + obj.styleTag = message.styleTag; + } + if (message.accentHint !== "") { + obj.accentHint = message.accentHint; + } + if (message.quirks?.length) { + obj.quirks = message.quirks; + } + return obj; + }, + + create, I>>(base?: I): VoiceProfile { + return VoiceProfile.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): VoiceProfile { + const message = createBaseVoiceProfile(); + message.personaId = object.personaId ?? 0; + message.basePitch = object.basePitch ?? 0; + message.speakingRate = object.speakingRate ?? 0; + message.energy = object.energy ?? 0; + message.styleTag = object.styleTag ?? ""; + message.accentHint = object.accentHint ?? ""; + message.quirks = object.quirks?.map((e) => e) || []; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/golden_directive.bin b/golden_directive.bin new file mode 100644 index 0000000..31a54ed --- /dev/null +++ b/golden_directive.bin @@ -0,0 +1,2 @@ + +test-golden-roundtrip-001 V"Gสวัสดี ยินดีที่ได้รู้จัก!*thai-accent-test08@ \ No newline at end of file diff --git a/locales/README.ja.md b/locales/README.ja.md index 638829f..e21776a 100644 --- a/locales/README.ja.md +++ b/locales/README.ja.md @@ -2,16 +2,16 @@ # vtuber-contracts -**Build-time typed interface contracts (proto3) for the vtuber-* program — generates a Rust crate, Python typed stubs, and TypeScript declarations consumed by every other vtuber-* repo to prevent contract drift across 17 services.** +**vtuber-* プログラム向けビルド時 proto3 型付きインターフェース契約 — Rust crate、Mojo バインディング (Pixi + Python interop 経由)、TypeScript 宣言を生成し、17 サービス間のコントラクト・ドリフトを防ぐ** [![CI](https://github.com/echo-layer/vtuber-contracts/actions/workflows/ci.yml/badge.svg)](https://github.com/echo-layer/vtuber-contracts/actions/workflows/ci.yml) [![Security](https://github.com/echo-layer/vtuber-contracts/actions/workflows/security.yml/badge.svg)](https://github.com/echo-layer/vtuber-contracts/actions/workflows/security.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Status](https://img.shields.io/badge/status-active-success)](./) -![Rust LOD](https://img.shields.io/badge/Rust_LOD-0-dea584.svg) ![Total LOD](https://img.shields.io/badge/Total_LOD-0-brightgreen.svg) +![Rust LOD](https://img.shields.io/badge/Rust_LOD-0-dea584.svg) ![Mojo LOD](https://img.shields.io/badge/Mojo_LOD-0-CC0000.svg) ![Total LOD](https://img.shields.io/badge/Total_LOD-0-brightgreen.svg) -[![Rust](https://img.shields.io/badge/Rust-dea584?logo=rust&logoColor=white)](./) +[![Rust](https://img.shields.io/badge/Rust-dea584?logo=rust&logoColor=white)](./) [![Mojo](https://img.shields.io/badge/Mojo-CC0000?logo=mojo&logoColor=white)](./) [![buf](https://img.shields.io/badge/buf-151C3B)](./) [![Pixi](https://img.shields.io/badge/Pixi-F4A02D)](./) @@ -19,7 +19,7 @@ [ [English](../README.md) | [ภาษาไทย](./README.th.md) | 日本語 | [简体中文](./README.zh.md) ] -vtuber-contracts は vtuber-* プログラム内の全サービス間型付き境界に対するビルド時ソース・オブ・トゥルース。ConversationDirective / VoiceProfile / Persona 等のメッセージに proto3 スキーマを定義し、codegen で Rust crate・Python 型スタブ (.pyi)・TypeScript 宣言ファイルを生成し、他のすべての vtuber-* リポジトリおよび vtuber-api 経由で公開される SDK に提供する。 +vtuber-contracts は vtuber-* プログラム内の全サービス間型付き境界に対するビルド時ソース・オブ・トゥルース。ConversationDirective / VoiceProfile / Persona 等のメッセージに proto3 スキーマを定義し、codegen で 3 つの consumer surface — Rust crate (tonic-build 経由)、Mojo バインディング (Pixi + Python interop 経由、ADR-004 参照)、TypeScript 宣言 (ts-proto 経由) — を生成し、他のすべての vtuber-* リポジトリおよび vtuber-api 経由で公開される SDK に提供する。 ## ✨ 特徴 (Features) - 🚀 **全サービス間メッセージ (ConversationDirective / VoiceProfile / Persona / StreamEvent / ToolCall) の proto3 スキーマを安定したパッケージパスで提供** diff --git a/locales/README.th.md b/locales/README.th.md index 9842207..766ce50 100644 --- a/locales/README.th.md +++ b/locales/README.th.md @@ -2,16 +2,16 @@ # vtuber-contracts -**Build-time typed interface contracts (proto3) for the vtuber-* program — generates a Rust crate, Python typed stubs, and TypeScript declarations consumed by every other vtuber-* repo to prevent contract drift across 17 services.** +**Build-time typed interface contracts (proto3) สำหรับโปรแกรม vtuber-* — generate Rust crate, Mojo binding (ผ่าน Pixi + Python interop) และ TypeScript declarations ที่ทุก vtuber-* repo ใช้ร่วมกันเพื่อป้องกัน contract drift ข้าม 17 service** [![CI](https://github.com/echo-layer/vtuber-contracts/actions/workflows/ci.yml/badge.svg)](https://github.com/echo-layer/vtuber-contracts/actions/workflows/ci.yml) [![Security](https://github.com/echo-layer/vtuber-contracts/actions/workflows/security.yml/badge.svg)](https://github.com/echo-layer/vtuber-contracts/actions/workflows/security.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Status](https://img.shields.io/badge/status-active-success)](./) -![Rust LOD](https://img.shields.io/badge/Rust_LOD-0-dea584.svg) ![Total LOD](https://img.shields.io/badge/Total_LOD-0-brightgreen.svg) +![Rust LOD](https://img.shields.io/badge/Rust_LOD-0-dea584.svg) ![Mojo LOD](https://img.shields.io/badge/Mojo_LOD-0-CC0000.svg) ![Total LOD](https://img.shields.io/badge/Total_LOD-0-brightgreen.svg) -[![Rust](https://img.shields.io/badge/Rust-dea584?logo=rust&logoColor=white)](./) +[![Rust](https://img.shields.io/badge/Rust-dea584?logo=rust&logoColor=white)](./) [![Mojo](https://img.shields.io/badge/Mojo-CC0000?logo=mojo&logoColor=white)](./) [![buf](https://img.shields.io/badge/buf-151C3B)](./) [![Pixi](https://img.shields.io/badge/Pixi-F4A02D)](./) @@ -19,7 +19,7 @@ [ [English](../README.md) | ภาษาไทย | [日本語](./README.ja.md) | [简体中文](./README.zh.md) ] -vtuber-contracts เป็น build-time source of truth สำหรับ typed boundary ทุกตัวระหว่าง service ในโปรแกรม vtuber-* — นิยาม proto3 schema สำหรับ message อย่าง ConversationDirective, VoiceProfile และ Persona แล้ว codegen ออกเป็น Rust crate, Python typed stub (.pyi), และ TypeScript declaration file ที่ทุก vtuber-* repo รวมถึง public SDK ของ vtuber-api ใช้ร่วมกัน +vtuber-contracts เป็น build-time source of truth สำหรับ typed boundary ทุกตัวระหว่าง service ในโปรแกรม vtuber-* — นิยาม proto3 schema สำหรับ message อย่าง ConversationDirective, VoiceProfile และ Persona แล้ว codegen ออกเป็น 3 consumer surface ได้แก่ Rust crate (ผ่าน tonic-build), Mojo binding (ผ่าน Pixi + Python interop, ดู ADR-004) และ TypeScript declaration (ผ่าน ts-proto) ที่ทุก vtuber-* repo รวมถึง public SDK ของ vtuber-api ใช้ร่วมกัน ## ✨ ฟีเจอร์เด่น (Features) - 🚀 **proto3 schema สำหรับ inter-service message ทั้งหมด (ConversationDirective, VoiceProfile, Persona, StreamEvent, ToolCall) ภายใต้ package path ที่เสถียร** diff --git a/locales/README.zh.md b/locales/README.zh.md index a18b18c..06c46f1 100644 --- a/locales/README.zh.md +++ b/locales/README.zh.md @@ -2,16 +2,16 @@ # vtuber-contracts -**Build-time typed interface contracts (proto3) for the vtuber-* program — generates a Rust crate, Python typed stubs, and TypeScript declarations consumed by every other vtuber-* repo to prevent contract drift across 17 services.** +**面向 vtuber-* 程序的构建期 proto3 类型化接口契约 —— 生成 Rust crate、Mojo 绑定 (经由 Pixi + Python interop) 与 TypeScript 声明,供 17 个服务统一消费以防止契约漂移** [![CI](https://github.com/echo-layer/vtuber-contracts/actions/workflows/ci.yml/badge.svg)](https://github.com/echo-layer/vtuber-contracts/actions/workflows/ci.yml) [![Security](https://github.com/echo-layer/vtuber-contracts/actions/workflows/security.yml/badge.svg)](https://github.com/echo-layer/vtuber-contracts/actions/workflows/security.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Status](https://img.shields.io/badge/status-active-success)](./) -![Rust LOD](https://img.shields.io/badge/Rust_LOD-0-dea584.svg) ![Total LOD](https://img.shields.io/badge/Total_LOD-0-brightgreen.svg) +![Rust LOD](https://img.shields.io/badge/Rust_LOD-0-dea584.svg) ![Mojo LOD](https://img.shields.io/badge/Mojo_LOD-0-CC0000.svg) ![Total LOD](https://img.shields.io/badge/Total_LOD-0-brightgreen.svg) -[![Rust](https://img.shields.io/badge/Rust-dea584?logo=rust&logoColor=white)](./) +[![Rust](https://img.shields.io/badge/Rust-dea584?logo=rust&logoColor=white)](./) [![Mojo](https://img.shields.io/badge/Mojo-CC0000?logo=mojo&logoColor=white)](./) [![buf](https://img.shields.io/badge/buf-151C3B)](./) [![Pixi](https://img.shields.io/badge/Pixi-F4A02D)](./) @@ -19,7 +19,7 @@ [ [English](../README.md) | [ภาษาไทย](./README.th.md) | [日本語](./README.ja.md) | 简体中文 ] -vtuber-contracts 是 vtuber-* 程序中所有服务间类型化边界的构建期真相源 —— 为 ConversationDirective、VoiceProfile、Persona 等消息定义 proto3 schema,然后通过 codegen 生成 Rust crate、Python 类型存根 (.pyi) 与 TypeScript 声明文件,供所有其他 vtuber-* 仓库以及经由 vtuber-api 发布的公共 SDK 使用。 +vtuber-contracts 是 vtuber-* 程序中所有服务间类型化边界的构建期真相源 —— 为 ConversationDirective、VoiceProfile、Persona 等消息定义 proto3 schema,然后通过 codegen 生成三种消费者形态:Rust crate (经由 tonic-build)、Mojo 绑定 (经由 Pixi + Python interop,见 ADR-004) 与 TypeScript 声明 (经由 ts-proto),供所有其他 vtuber-* 仓库以及经由 vtuber-api 发布的公共 SDK 使用。 ## ✨ 特性 (Features) - 🚀 **为所有服务间消息 (ConversationDirective / VoiceProfile / Persona / StreamEvent / ToolCall) 提供稳定 package 路径下的 proto3 schema** diff --git a/mojo/tests/test_golden_roundtrip.mojo b/mojo/tests/test_golden_roundtrip.mojo new file mode 100644 index 0000000..32d26de --- /dev/null +++ b/mojo/tests/test_golden_roundtrip.mojo @@ -0,0 +1,46 @@ +"""Mojo test to verify the Golden Round-trip from Rust. + +This script reads 'golden_directive.bin' (generated by Rust) and verifies +that the Thai text and metadata are preserved correctly when parsed via +Mojo's Python-interop facade. +""" + +from std.python import Python +from std.testing import assert_equal +from vtuber_contracts import ConversationDirective + +def test_golden_roundtrip_from_rust() raises: + # Use Python's open to read binary data + var builtins = Python.import_module("builtins") + var file = builtins.open("golden_directive.bin", "rb") + var bytes = file.read() + file.close() + + var decoded = ConversationDirective.parse(bytes) + + print("Checking Directive ID...") + assert_equal(decoded.directive_id(), "test-golden-roundtrip-001") + + print("Checking Persona ID...") + assert_equal(String(decoded.persona_id()), "1") # PersonaId.PERSONA_ID_VALORA + + print("Checking Thai Text Prompt...") + # The exact string from Rust: "สวัสดี ยินดีที่ได้รู้จัก!" + assert_equal(decoded.text_prompt(), "สวัสดี ยินดีที่ได้รู้จัก!") + + print("Checking Voice Prompt...") + assert_equal(decoded.voice_prompt(), "thai-accent-test") + + print("Checking Emotion...") + assert_equal(String(decoded.emotion()), "2") # Emotion.EMOTION_HAPPY + + print("Checking Audio Format...") + assert_equal(String(decoded.target_audio_format()), "1") # AudioFormat.AUDIO_FORMAT_WAV + + print("Checking Max Latency...") + assert_equal(String(decoded.max_latency_ms()), "500") + + print("Golden Round-trip Verification: SUCCESS") + +def main() raises: + test_golden_roundtrip_from_rust() diff --git a/mojo/tests/test_roundtrip.mojo b/mojo/tests/test_roundtrip.mojo new file mode 100644 index 0000000..70afde5 --- /dev/null +++ b/mojo/tests/test_roundtrip.mojo @@ -0,0 +1,45 @@ +"""Mojo round-trip tests — coupling gate with the Python-generated stubs. + +These tests fail loudly if the Python bindings under generated/python/ are +missing, out of date, or shaped differently from the Mojo facade. Run via +`pixi run test`, which sets PYTHONPATH=generated/python so the import +resolves without a Python package install step. +""" + +from std.testing import assert_equal +from vtuber_contracts import Persona, ConversationDirective + + +def test_persona_roundtrip() raises: + var valora_id = 1 # PersonaId.PERSONA_ID_VALORA + var original = Persona.new( + valora_id, + "Valora", + "Russian accent, dark humor.", + "#FF3C3C", + ) + var bytes = original.serialize() + var decoded = Persona.parse(bytes) + assert_equal(decoded.display_name(), "Valora") + assert_equal(decoded.color_hex(), "#FF3C3C") + + +def test_conversation_directive_roundtrip() raises: + var ametra_id = 3 # PersonaId.PERSONA_ID_AMETRA + var original = ConversationDirective.new( + "018f4e2b-4a8c-7b1f-9c5e-2d3a4b5c6d7e", + ametra_id, + "Let me analyze that for a moment...", + ) + var bytes = original.serialize() + var decoded = ConversationDirective.parse(bytes) + assert_equal( + decoded.text_prompt(), + "Let me analyze that for a moment...", + ) + + +def main() raises: + test_persona_roundtrip() + test_conversation_directive_roundtrip() + print("Mojo roundtrip tests: OK") diff --git a/mojo/vtuber_contracts.mojo b/mojo/vtuber_contracts.mojo new file mode 100644 index 0000000..91e3815 --- /dev/null +++ b/mojo/vtuber_contracts.mojo @@ -0,0 +1,127 @@ +"""Mojo bindings for vtuber-contracts. + +Mojo has no native proto3 codegen as of Modular's 2026 tooling. This module +wraps the Python bindings that `buf generate` produces under +`generated/python/vtuber/v1/*_pb2.py` via Mojo's Python interop. See +ADR-004 in DESIGN_DECISIONS.md. + +Every struct here is a thin Mojo facade over a held `PythonObject`. The +on-the-wire shape is defined exclusively by proto/vtuber/v1/*.proto — if +the Python module is missing the shape, this file will not compile when +the round-trip test runs, which is the intended failure mode. +""" + +from std.python import Python, PythonObject + + +def _persona_module() raises -> PythonObject: + return Python.import_module("vtuber.v1.persona_pb2") + + +def _voice_profile_module() raises -> PythonObject: + return Python.import_module("vtuber.v1.voice_profile_pb2") + + +def _conversation_module() raises -> PythonObject: + return Python.import_module("vtuber.v1.conversation_pb2") + + +struct Persona: + """Mojo view over a vtuber.v1.Persona proto instance.""" + + var _py: PythonObject + + def __init__(out self, py: PythonObject): + self._py = py + + @staticmethod + def new( + persona_id: Int, + display_name: String, + description: String, + color_hex: String, + ) raises -> Persona: + var pb = _persona_module() + var obj = pb.Persona() + obj.id = persona_id + obj.display_name = display_name + obj.description = description + obj.color_hex = color_hex + return Persona(obj) + + def serialize(self) raises -> PythonObject: + return self._py.SerializeToString() + + @staticmethod + def parse(data: PythonObject) raises -> Persona: + var pb = _persona_module() + var obj = pb.Persona() + obj.ParseFromString(data) + return Persona(obj) + + def display_name(self) raises -> String: + return String(self._py.display_name) + + def color_hex(self) raises -> String: + return String(self._py.color_hex) + + +struct ConversationDirective: + """Mojo view over a vtuber.v1.ConversationDirective proto instance.""" + + var _py: PythonObject + + def __init__(out self, py: PythonObject): + self._py = py + + @staticmethod + def new( + directive_id: String, + persona_id: Int, + text_prompt: String, + voice_prompt: String = "", + emotion: Int = 1, # EMOTION_NEUTRAL + target_audio_format: Int = 1, # AUDIO_FORMAT_WAV + max_latency_ms: Int = 0, + ) raises -> ConversationDirective: + var pb = _conversation_module() + var obj = pb.ConversationDirective() + obj.directive_id = directive_id + obj.persona_id = persona_id + obj.text_prompt = text_prompt + obj.voice_prompt = voice_prompt + obj.emotion = emotion + obj.target_audio_format = target_audio_format + obj.max_latency_ms = max_latency_ms + return ConversationDirective(obj) + + def serialize(self) raises -> PythonObject: + return self._py.SerializeToString() + + @staticmethod + def parse(data: PythonObject) raises -> ConversationDirective: + var pb = _conversation_module() + var obj = pb.ConversationDirective() + obj.ParseFromString(data) + return ConversationDirective(obj) + + def directive_id(self) raises -> String: + return String(self._py.directive_id) + + def persona_id(self) raises -> PythonObject: + return self._py.persona_id + + def text_prompt(self) raises -> String: + return String(self._py.text_prompt) + + def voice_prompt(self) raises -> String: + return String(self._py.voice_prompt) + + def emotion(self) raises -> PythonObject: + return self._py.emotion + + def target_audio_format(self) raises -> PythonObject: + return self._py.target_audio_format + + def max_latency_ms(self) raises -> PythonObject: + return self._py.max_latency_ms diff --git a/package.json b/package.json new file mode 100644 index 0000000..96a6653 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "@echo-layer/vtuber-contracts", + "version": "0.1.0", + "description": "TypeScript declarations for the vtuber-* program", + "private": true, + "types": "generated/typescript/vtuber/v1/index.d.ts", + "main": "generated/typescript/vtuber/v1/index.js", + "files": [ + "generated/typescript/**/*" + ], + "scripts": { + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "typescript": "^5.4.0", + "ts-proto": "^2.2.0" + } +} diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 0000000..b4f24ce --- /dev/null +++ b/pixi.lock @@ -0,0 +1,1011 @@ +version: 6 +environments: + default: + channels: + - url: https://conda.modular.com/max-nightly/ + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.3-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.modular.com/max-nightly/noarch/mblack-26.3.0.dev2026042817-release.conda + - conda: https://conda.modular.com/max-nightly/linux-64/mojo-1.0.0b1.dev2026042817-release.conda + - conda: https://conda.modular.com/max-nightly/linux-64/mojo-compiler-1.0.0b1.dev2026042817-release.conda + - conda: https://conda.modular.com/max-nightly/noarch/mojo-python-1.0.0b1.dev2026042817-release.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/e8/ec/5ffcf8f5f53757e01afdece10c664e694ac60d2f17c2036811b85b842a5b/mypy_protobuf-5.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/53/1b/3b431694a4dc6d37b9f653f0c64b0a0d9ec074ee810710c0c3da21d67ba7/protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ef/b5/0bc9874d89c58fb0ce851e150055ce732d254dbb10b06becbc7635d0d635/types_protobuf-7.34.1.20260408-py3-none-any.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.3-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.0-h1b79a29_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.modular.com/max-nightly/noarch/mblack-26.3.0.dev2026042817-release.conda + - conda: https://conda.modular.com/max-nightly/osx-arm64/mojo-1.0.0b1.dev2026042817-release.conda + - conda: https://conda.modular.com/max-nightly/osx-arm64/mojo-compiler-1.0.0b1.dev2026042817-release.conda + - conda: https://conda.modular.com/max-nightly/noarch/mojo-python-1.0.0b1.dev2026042817-release.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.13-h8561d8f_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - pypi: https://files.pythonhosted.org/packages/e8/ec/5ffcf8f5f53757e01afdece10c664e694ac60d2f17c2036811b85b842a5b/mypy_protobuf-5.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/ef/b5/0bc9874d89c58fb0ce851e150055ce732d254dbb10b06becbc7635d0d635/types_protobuf-7.34.1.20260408-py3-none-any.whl +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28948 + timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 + md5: aaa2a381ccc56eac91d63b6c1240312f + depends: + - cpython + - python-gil + license: MIT + license_family: MIT + purls: [] + size: 8191 + timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 + md5: d2ffd7602c02f2b316fd921d39876885 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 260182 + timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + sha256: 540fe54be35fac0c17feefbdc3e29725cce05d7367ffedfaaa1bdda234b019df + md5: 620b85a3f45526a8bc4d23fd78fc22f0 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 124834 + timestamp: 1771350416561 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + sha256: c9dbcc8039a52023660d6d1bbf87594a93dd69c6ac5a2a44323af2c92976728d + md5: e18ad67cf881dcadee8b8d9e2f8e5f73 + depends: + - __unix + license: ISC + purls: [] + size: 131039 + timestamp: 1776865545798 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.3-pyhc90fa1f_0.conda + sha256: 37a5d8b10ea3516e2c42f870c9c351b9f7b31ff48c66d83490039f417e1e5228 + md5: 2266262ce8a425ecb6523d765f79b303 + depends: + - __unix + - python + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/click?source=compressed-mapping + size: 100048 + timestamp: 1777219902525 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + noarch: generic + sha256: d3e9bbd7340199527f28bbacf947702368f31de60c433a16446767d3c6aaf6fe + md5: f54c1ffb8ecedb85a8b7fcde3a187212 + depends: + - python >=3.12,<3.13.0a0 + - python_abi * *_cp312 + license: Python-2.0 + purls: [] + size: 46463 + timestamp: 1772728929620 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a + md5: c80d8a3b84358cb967fa81e7075fbc8a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 12723451 + timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 + md5: 080594bf4493e6bae2607e65390c520a + depends: + - python >=3.10 + - zipp >=3.20 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/importlib-metadata?source=compressed-mapping + size: 34387 + timestamp: 1773931568510 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.6.3-pyhd8ed1ab_1.conda + sha256: 19d8bd5bb2fde910ec59e081eeb59529491995ce0d653a5209366611023a0b3a + md5: 4ebae00eae9705b0c3d6d1018a81d047 + depends: + - importlib-metadata >=4.8.3 + - jupyter_core >=4.12,!=5.0.* + - python >=3.9 + - python-dateutil >=2.8.2 + - pyzmq >=23.0 + - tornado >=6.2 + - traitlets >=5.3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-client?source=hash-mapping + size: 106342 + timestamp: 1733441040958 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a + md5: b38fe4e78ee75def7e599843ef4c1ab0 + depends: + - __unix + - python + - platformdirs >=2.5 + - python >=3.10 + - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-core?source=hash-mapping + size: 65503 + timestamp: 1760643864586 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 + md5: b38117a3c920364aff79f870c984b4a3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-or-later + purls: [] + size: 134088 + timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 + md5: fb53fb07ce46a575c5d004bbc96032c2 + depends: + - __glibc >=2.17,<3.0.a0 + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1386730 + timestamp: 1769769569681 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + sha256: c0a0bf028fe7f3defcdcaa464e536cf1b202d07451e18ad83fdd169d15bef6ed + md5: e446e1822f4da8e5080a9de93474184d + depends: + - __osx >=11.0 + - libcxx >=19 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1160828 + timestamp: 1769770119811 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c + md5: 18335a698559cdbcd86150a48bf54ba6 + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.45.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 728002 + timestamp: 1774197446916 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + sha256: 25a0d02148a39b665d9c2957676faf62a4d2a58494d53b201151199a197db4b0 + md5: 448a1af83a9205655ee1cf48d3875ca3 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 569927 + timestamp: 1776816293111 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 + md5: c277e0a4d549b03ac1e9d6cbbe3d017b + depends: + - ncurses + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 134676 + timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631 + md5: 44083d2d2c2025afca315c7a172eab2b + depends: + - ncurses + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 107691 + timestamp: 1738479560845 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + sha256: e8c2b57f6aacabdf2f1b0924bd4831ce5071ba080baa4a9e8c0d720588b6794c + md5: 49f570f3bc4c874a06ea69b7225753af + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 76624 + timestamp: 1774719175983 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + sha256: 06780dec91dd25770c8cf01e158e1062fbf7c576b1406427475ce69a8af75b7e + md5: a32123f93e168eaa4080d87b0fb5da8a + depends: + - __osx >=11.0 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 68192 + timestamp: 1774719211725 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 + md5: a360c33a5abe61c07959e449fa1453eb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 58592 + timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + sha256: 6686a26466a527585e6a75cc2a242bf4a3d97d6d6c86424a441677917f28bec7 + md5: 43c04d9cb46ef176bb2a4c77e324d599 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 40979 + timestamp: 1769456747661 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 + md5: 0aa00f03f9e39fb9876085dee11a85d4 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 1041788 + timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 + md5: d5e96b1ed75ca01906b3d2469b4ce493 + depends: + - libgcc 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27526 + timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 + md5: 239c5e9546c38a1e884d69effcf4c882 + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 603262 + timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + sha256: ec30e52a3c1bf7d0425380a189d209a52baa03f22fb66dd3eb587acaa765bd6d + md5: b88d90cad08e6bc8ad540cb310a761fb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + size: 113478 + timestamp: 1775825492909 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + sha256: 34878d87275c298f1a732c6806349125cebbf340d24c6c23727268184bba051e + md5: b1fd823b5ae54fbec272cea0811bd8a9 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + size: 92472 + timestamp: 1775825802659 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 + md5: d864d34357c3b65a4b731f78c0801dc4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + purls: [] + size: 33731 + timestamp: 1750274110928 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + sha256: 64e5c80cbce4680a2d25179949739a6def695d72c40ca28f010711764e372d97 + md5: 7af961ef4aa2c1136e11dd43ded245ab + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: ISC + purls: [] + size: 277661 + timestamp: 1772479381288 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + sha256: df603472ea1ebd8e7d4fb71e4360fe48d10b11c240df51c129de1da2ff9e8227 + md5: 7cc5247987e6d115134ebab15186bc13 + depends: + - __osx >=11.0 + license: ISC + purls: [] + size: 248039 + timestamp: 1772479570912 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda + sha256: ec37c79f737933bbac965f5dc0f08ef2790247129a84bb3114fad4900adce401 + md5: 810d83373448da85c3f673fbcb7ad3a3 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=14 + - libzlib >=1.3.2,<2.0a0 + license: blessing + purls: [] + size: 958864 + timestamp: 1775753750179 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.0-h1b79a29_0.conda + sha256: 1a9d1e3e18dbb0b87cff3b40c3e42703730d7ac7ee9b9322c2682196a81ba0c3 + md5: 8423c008105df35485e184066cad4566 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: blessing + purls: [] + size: 920039 + timestamp: 1775754485962 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e + md5: 1b08cd684f34175e4514474793d44bcb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.2.0 he0feb66_18 + constrains: + - libstdcxx-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 5852330 + timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + sha256: bc1b08c92626c91500fd9f26f2c797f3eb153b627d53e9c13cd167f1e12b2829 + md5: 38ffe67b78c9d4de527be8315e5ada2c + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 40297 + timestamp: 1775052476770 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + purls: [] + size: 100393 + timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 + md5: d87ff7921124eccd67248aa483c23fec + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 63629 + timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + sha256: 361415a698514b19a852f5d1123c5da746d4642139904156ddfca7c922d23a05 + md5: bc5a5721b6439f2f62a84f2548136082 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 47759 + timestamp: 1774072956767 +- conda: https://conda.modular.com/max-nightly/noarch/mblack-26.3.0.dev2026042817-release.conda + noarch: python + sha256: d75ce5eb57058486e2b5934bf4d47ee38630eb98fe4ba5170602f5edade986cc + md5: f8c53cc308b692d687347645f887867c + depends: + - python >=3.10 + - click >=8.0.0 + - mypy_extensions >=0.4.3 + - packaging >=22.0 + - pathspec >=0.9.0 + - platformdirs >=2 + - tomli >=1.1.0 + license: LicenseRef-Modular-Proprietary + size: 134915 + timestamp: 1777396575969 +- conda: https://conda.modular.com/max-nightly/linux-64/mojo-1.0.0b1.dev2026042817-release.conda + sha256: d5d344147f624a1a378b6f31f1c199c2b1be7082b3d07565a9aee36dba3dadf9 + md5: f884badfffb774860b4e90a8f0d19d33 + depends: + - python >=3.10 + - mojo-compiler ==1.0.0b1.dev2026042817 + - mblack ==26.3.0.dev2026042817 + - jupyter_client >=8.6.2,<8.7 + license: LicenseRef-Modular-Proprietary + size: 94159307 + timestamp: 1777396911167 +- conda: https://conda.modular.com/max-nightly/osx-arm64/mojo-1.0.0b1.dev2026042817-release.conda + sha256: 67ba0140c11c3585ffb82f432a65f142aa9282a350147e2f26c7c13fb774858c + md5: 12d4250f7bcf611bc1e97f5de8517f12 + depends: + - python >=3.10 + - mojo-compiler ==1.0.0b1.dev2026042817 + - mblack ==26.3.0.dev2026042817 + - jupyter_client >=8.6.2,<8.7 + license: LicenseRef-Modular-Proprietary + size: 83384140 + timestamp: 1777411559830 +- conda: https://conda.modular.com/max-nightly/linux-64/mojo-compiler-1.0.0b1.dev2026042817-release.conda + sha256: 0ca879747629b0a12ca4f56364b3db17649ff1a3cc9c6a51dc0f1fd6a8719954 + md5: f070e59181dcf94878dd49a73a578b44 + depends: + - mojo-python ==1.0.0b1.dev2026042817 + license: LicenseRef-Modular-Proprietary + size: 89376738 + timestamp: 1777396915701 +- conda: https://conda.modular.com/max-nightly/osx-arm64/mojo-compiler-1.0.0b1.dev2026042817-release.conda + sha256: a7f3fbe0bae3619dff7a5f03595098be56c3b8f2b2d06e18051ad7d8e31fa55f + md5: da29a89fb6ffad502450b5b3fc6c71ea + depends: + - mojo-python ==1.0.0b1.dev2026042817 + license: LicenseRef-Modular-Proprietary + size: 67451521 + timestamp: 1777397117567 +- conda: https://conda.modular.com/max-nightly/noarch/mojo-python-1.0.0b1.dev2026042817-release.conda + noarch: python + sha256: 8f5ae91fa5f416af2bb8d71079b75ae2fcd36d99ae1bb08f496e6c0fbef9d18a + md5: 02212bb1f7e7bd37ccab5e86cbb0aa4a + depends: + - python >=3.10 + license: LicenseRef-Modular-Proprietary + size: 23174 + timestamp: 1777396576274 +- pypi: https://files.pythonhosted.org/packages/e8/ec/5ffcf8f5f53757e01afdece10c664e694ac60d2f17c2036811b85b842a5b/mypy_protobuf-5.1.0-py3-none-any.whl + name: mypy-protobuf + version: 5.1.0 + sha256: d7031f563f806b8bcd448a3e86768bf0994c0af5b0017b344a4fbbba4191f43c + requires_dist: + - protobuf>=4.25.3 + - types-protobuf>=4.24 + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda + sha256: 6ed158e4e5dd8f6a10ad9e525631e35cee8557718f83de7a4e3966b1f772c4b1 + md5: e9c622e0d00fa24a6292279af3ab6d06 + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy-extensions?source=hash-mapping + size: 11766 + timestamp: 1745776666688 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda + sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 + md5: fc21868a1a5aacc937e7a18747acb8a5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: X11 AND BSD-3-Clause + purls: [] + size: 918956 + timestamp: 1777422145199 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda + sha256: 4ea6c620b87bd1d42bb2ccc2c87cd2483fa2d7f9e905b14c223f11ff3f4c455d + md5: 343d10ed5b44030a2f67193905aea159 + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + purls: [] + size: 805509 + timestamp: 1777423252320 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb + md5: da1b85b6a87e141f5140bb9924cecab0 + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=14 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3167099 + timestamp: 1775587756857 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda + sha256: c91bf510c130a1ea1b6ff023e28bac0ccaef869446acd805e2016f69ebdc49ea + md5: 25dcccd4f80f1638428613e0d7c9b4e1 + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3106008 + timestamp: 1775587972483 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 + md5: 4c06a92e74452cfa53623a81592e8934 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging?source=compressed-mapping + size: 91574 + timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.1.1-pyhd8ed1ab_0.conda + sha256: 6eaee417d33f298db79bc7185ab1208604c0e6cf51dade34cd513c6f9db9c6f3 + md5: 11adc78451c998c0fd162584abfa3559 + depends: + - python >=3.10 + license: MPL-2.0 + license_family: MOZILLA + purls: + - pkg:pypi/pathspec?source=compressed-mapping + size: 56559 + timestamp: 1777271601895 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + sha256: 8f29915c172f1f7f4f7c9391cd5dac3ebf5d13745c8b7c8006032615246345a5 + md5: 89c0b6d1793601a2a3a3f7d2d3d8b937 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/platformdirs?source=compressed-mapping + size: 25862 + timestamp: 1775741140609 +- pypi: https://files.pythonhosted.org/packages/53/1b/3b431694a4dc6d37b9f653f0c64b0a0d9ec074ee810710c0c3da21d67ba7/protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl + name: protobuf + version: 7.34.1 + sha256: 8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + name: protobuf + version: 7.34.1 + sha256: d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7 + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + sha256: a44655c1c3e1d43ed8704890a91e12afd68130414ea2c0872e154e5633a13d7e + md5: 7eccb41177e15cc672e1babe9056018e + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + purls: [] + size: 31608571 + timestamp: 1772730708989 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.13-h8561d8f_0_cpython.conda + sha256: e658e647a4a15981573d6018928dec2c448b10c77c557c29872043ff23c0eb6a + md5: 8e7608172fa4d1b90de9a745c2fd2b81 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + purls: [] + size: 12127424 + timestamp: 1772730755512 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 + md5: 5b8d21249ff20967101ffa321cab24e8 + depends: + - python >=3.9 + - six >=1.5 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/python-dateutil?source=hash-mapping + size: 233310 + timestamp: 1751104122689 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + sha256: 97327b9509ae3aae28d27217a5d7bd31aff0ab61a02041e9c6f98c11d8a53b29 + md5: 32780d6794b8056b78602103a04e90ef + depends: + - cpython 3.12.13.* + - python_abi * *_cp312 + license: Python-2.0 + purls: [] + size: 46449 + timestamp: 1772728979370 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + build_number: 8 + sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 + md5: c3efd25ac4d74b1584d2f7a57195ddf1 + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6958 + timestamp: 1752805918820 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + noarch: python + sha256: be66c1f85c3b48137200d62c12d918f4f8ad329423daef04fed292818efd3c28 + md5: 082985717303dab433c976986c674b35 + depends: + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - zeromq >=4.3.5,<4.4.0a0 + - _python_abi3_support 1.* + - cpython >=3.12 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=hash-mapping + size: 211567 + timestamp: 1771716961404 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + noarch: python + sha256: 2f31f799a46ed75518fae0be75ecc8a1b84360dbfd55096bc2fe8bd9c797e772 + md5: 2f6b79700452ef1e91f45a99ab8ffe5a + depends: + - python + - libcxx >=19 + - __osx >=11.0 + - _python_abi3_support 1.* + - cpython >=3.12 + - zeromq >=4.3.5,<4.4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=hash-mapping + size: 191641 + timestamp: 1771717073430 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 345073 + timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 + md5: f8381319127120ce51e081dce4865cf4 + depends: + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 313930 + timestamp: 1765813902568 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d + md5: 3339e3b65d58accf4ca4fb8748ab16b3 + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/six?source=hash-mapping + size: 18455 + timestamp: 1753199211006 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac + md5: cffd3bdd58090148f4cfcd831f4b26ab + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3301196 + timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + sha256: 799cab4b6cde62f91f750149995d149bc9db525ec12595e8a1d91b9317f038b3 + md5: a9d86bc62f39b94c4661716624eb21b0 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3127137 + timestamp: 1769460817696 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd + md5: b5325cf06a000c5b14970462ff5e4d58 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli?source=hash-mapping + size: 21561 + timestamp: 1774492402955 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda + sha256: 4629b1c9139858fb08bb357df917ffc12e4d284c57ff389806bb3ae476ef4e0a + md5: 2b37798adbc54fd9e591d24679d2133a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=compressed-mapping + size: 859665 + timestamp: 1774358032165 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda + sha256: 29edd36311b4a810a9e6208437bdbedb28c9ac15221caf812cb5c5cf48375dca + md5: 02cce5319b0f1317d9642dcb2e475379 + depends: + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + size: 859155 + timestamp: 1774358568476 +- conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + sha256: f39a5620c6e8e9e98357507262a7869de2ae8cc07da8b7f84e517c9fd6c2b959 + md5: 019a7385be9af33791c989871317e1ed + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/traitlets?source=hash-mapping + size: 110051 + timestamp: 1733367480074 +- pypi: https://files.pythonhosted.org/packages/ef/b5/0bc9874d89c58fb0ce851e150055ce732d254dbb10b06becbc7635d0d635/types_protobuf-7.34.1.20260408-py3-none-any.whl + name: types-protobuf + version: 7.34.1.20260408 + sha256: ebbcd4e27b145aef6a59bc0cb6c013b3528151c1ba5e7f7337aeee355d276a5e + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + purls: [] + size: 119135 + timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + sha256: 325d370b28e2b9cc1f765c5b4cdb394c91a5d958fbd15da1a14607a28fee09f6 + md5: 755b096086851e1193f3b10347415d7c + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.21,<1.0.22.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 311150 + timestamp: 1772476812121 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + sha256: 2705360c72d4db8de34291493379ffd13b09fd594d0af20c9eefa8a3f060d868 + md5: e85dcd3bde2b10081cdcaeae15797506 + depends: + - __osx >=11.0 + - libcxx >=19 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.21,<1.0.22.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 245246 + timestamp: 1772476886668 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + sha256: 523616c0530d305d2216c2b4a8dfd3872628b60083255b89c5e0d8c42e738cca + md5: e1c36c6121a7c9c76f2f148f1e83b983 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/zipp?source=compressed-mapping + size: 24461 + timestamp: 1776131454755 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 601375 + timestamp: 1764777111296 diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 0000000..8085e2f --- /dev/null +++ b/pixi.toml @@ -0,0 +1,33 @@ +[workspace] +name = "vtuber-contracts" +version = "0.1.0" +description = "Typed Mojo + Rust + TypeScript bindings for the vtuber-* program, generated from proto3 schemas." +authors = ["echo-layer "] +channels = [ + "https://conda.modular.com/max-nightly/", + "conda-forge", +] +platforms = ["linux-64", "osx-arm64"] + +# Mojo has no native protobuf codegen as of Modular's 2026 tooling survey; +# the proto3 → Mojo path goes through Python interop (see ADR-004). `mojo` +# and `python` + `protobuf` must travel together for the Mojo bindings to +# resolve `import vtuber.v1.persona_pb2` at runtime. +[dependencies] +mojo = "*" +python = ">=3.11,<3.13" + +[pypi-dependencies] +# protobuf is pinned to PyPI (not conda) so its runtime version stays +# in lockstep with the gencode emitted by buf's remote Python plugin. +# A conda-forge-pinned protobuf trailed buf's gencode by a major version +# and broke `import vtuber.v1.persona_pb2` at runtime; PyPI tracks +# Google's release line directly. mypy-protobuf is the .pyi stub +# generator used by buf and lives here for the same reason. +protobuf = ">=5" +mypy-protobuf = ">=3.5" + +[tasks] +check = { cmd = "mojo format mojo/ && git diff --exit-code -- mojo/ || (echo 'mojo format produced changes — commit them'; exit 1)", description = "Static-check Mojo formatting. Fails if `mojo format` would modify any committed file." } +test = { cmd = "PYTHONPATH=generated/python mojo run -I mojo mojo/tests/test_roundtrip.mojo", description = "Run Mojo integration test that consumes Python-generated proto stubs. Mojo 1.0.0b1 has no `mojo test` subcommand; the test file's main() runs the asserts directly." } +generate = { cmd = "buf generate", description = "Regenerate Python + TypeScript bindings from proto/. Requires buf on PATH." } diff --git a/proto/vtuber/v1/conversation.proto b/proto/vtuber/v1/conversation.proto new file mode 100644 index 0000000..21d4152 --- /dev/null +++ b/proto/vtuber/v1/conversation.proto @@ -0,0 +1,71 @@ +syntax = "proto3"; + +package vtuber.v1; + +import "google/protobuf/timestamp.proto"; +import "vtuber/v1/persona.proto"; +import "vtuber/v1/voice_profile.proto"; +import "vtuber/v1/tool_call.proto"; + +// ConversationDirective is the single message vtuber-brain (the Director) +// emits on every turn and vtuber-voice (the Performer) consumes. Per +// ADR-002 this is the only protocol boundary between the two services. +// Full audio streaming back to the Director is out of scope for v0.1. +message ConversationDirective { + // Opaque per-turn id. Consumers MUST NOT parse it. UUIDv7 preferred. + string directive_id = 1; + // Emission time per the Director's clock. + google.protobuf.Timestamp emitted_at = 2; + // The persona to wear for this turn. + PersonaId persona_id = 3; + // Text the Performer should speak. The Director owns all LLM + // post-processing (sanitization, length trim) before emitting. + string text_prompt = 4; + // Optional per-turn voice priming seed. When empty, the Performer + // falls back to the persona's registered VoiceProfile in vtuber-commons. + string voice_prompt = 5; + // Per-turn emotion override. UNSPECIFIED means "use neutral". + Emotion emotion = 6; + // Requested output audio format. + AudioFormat target_audio_format = 7; + // Soft upper bound on total synthesis latency in milliseconds. + // 0 means unspecified — the Performer applies its default SLO. + uint32 max_latency_ms = 8; + + // Decentralized Tool Calls: These are intended for the Performer (Voice/Live2D) + // to execute in sync with the speech (e.g., "animate", "play_sound_effect"). + repeated ToolCall tool_calls = 9; +} + +// DirectiveAck is the Performer's synchronous reply to EmitDirective. +// A negative ack carries a stable short code; consumers branch on the +// code, not on human-readable text. +message DirectiveAck { + string directive_id = 1; + bool accepted = 2; + // Stable short code when accepted is false: + // "persona_unknown", "format_unsupported", "queue_full", + // "voice_profile_missing". Empty when accepted is true. + string reject_reason = 3; +} + +// EmitDirectiveRequest wraps ConversationDirective for the rpc surface. +// The wrapper exists because buf STANDARD lint requires rpc request/response +// types to be named after the rpc — and because wrappers leave room for +// per-rpc metadata (idempotency keys, request tracing) to be added without +// touching the domain message. +message EmitDirectiveRequest { + ConversationDirective directive = 1; +} + +// EmitDirectiveResponse wraps DirectiveAck for the same reasons. +message EmitDirectiveResponse { + DirectiveAck ack = 1; +} + +// DirectorService is the minimal service surface needed to validate tonic / +// buf service codegen end-to-end for v0.1. The full audio streaming rpc +// lives on a separate service added in the brain↔voice slice. +service DirectorService { + rpc EmitDirective(EmitDirectiveRequest) returns (EmitDirectiveResponse); +} diff --git a/proto/vtuber/v1/persona.proto b/proto/vtuber/v1/persona.proto new file mode 100644 index 0000000..86eae57 --- /dev/null +++ b/proto/vtuber/v1/persona.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + +package vtuber.v1; + +// PersonaId is the canonical enum of the five VTuber personas. +// PERSONA_ID_UNSPECIFIED is the proto3 zero-value and MUST be treated as an +// error by consumers — no persona should ever round-trip as unspecified. +enum PersonaId { + PERSONA_ID_UNSPECIFIED = 0; + PERSONA_ID_VALORA = 1; + PERSONA_ID_AURORA = 2; + PERSONA_ID_AMETRA = 3; + PERSONA_ID_ASTRAEA = 4; + PERSONA_ID_ELDORA = 5; +} + +// Persona captures every static attribute of a VTuber persona: display name, +// trigger keywords, lore tags, brand colour. Runtime voice parameters live +// in VoiceProfile; per-turn emotion lives in ConversationDirective. The +// source of truth for Persona instances is a YAML file in vtuber-commons; +// this proto is the shape that commons validates against on load. +message Persona { + PersonaId id = 1; + string display_name = 2; + string description = 3; + // Trigger keywords that bias the Director toward this persona. + repeated string activation_keywords = 4; + // Freeform lore tags used for memory retrieval and character consistency. + repeated string lore_tags = 5; + // Brand colour as a CSS hex string (e.g. "#FF3C3C"). + string color_hex = 6; +} diff --git a/proto/vtuber/v1/tool_call.proto b/proto/vtuber/v1/tool_call.proto new file mode 100644 index 0000000..8c9c192 --- /dev/null +++ b/proto/vtuber/v1/tool_call.proto @@ -0,0 +1,46 @@ +syntax = "proto3"; + +package vtuber.v1; + +import "google/protobuf/struct.proto"; + +// ToolCall represents a request from the Director (vtuber-brain) to execute +// a specific function. In the Hybrid model, these are embedded in the +// ConversationDirective for execution by the Performer or handled internally. +message ToolCall { + // Unique identifier for this call. Used to correlate with ToolResponse. + string call_id = 1; + + // The name of the tool to be called (e.g., "animate", "play_sound", "web_search"). + string name = 2; + + // Arguments for the tool call, structured as a JSON-like object. + // This matches the format used by major LLM providers (OpenAI, Anthropic). + google.protobuf.Struct arguments = 3; + + // Metadata to guide the execution. + map metadata = 4; +} + +// ToolResponse captures the result of a tool execution. +message ToolResponse { + // Matches the call_id from the ToolCall. + string call_id = 1; + + // The output of the tool, typically a JSON string or descriptive text. + string content = 2; + + // If true, indicates the tool execution failed. + bool is_error = 3; + + // Stable error code if is_error is true (e.g., "timeout", "not_found"). + string error_code = 4; +} + +// ToolDefinition is used by the Director to register available tools. +message ToolDefinition { + string name = 1; + string description = 2; + // JSON Schema representing the expected arguments. + google.protobuf.Struct parameters = 3; +} diff --git a/proto/vtuber/v1/voice_profile.proto b/proto/vtuber/v1/voice_profile.proto new file mode 100644 index 0000000..83da3af --- /dev/null +++ b/proto/vtuber/v1/voice_profile.proto @@ -0,0 +1,46 @@ +syntax = "proto3"; + +package vtuber.v1; + +import "vtuber/v1/persona.proto"; + +// AudioFormat enumerates the encodings the Performer can stream. +enum AudioFormat { + AUDIO_FORMAT_UNSPECIFIED = 0; + AUDIO_FORMAT_WAV = 1; + AUDIO_FORMAT_OPUS = 2; + AUDIO_FORMAT_MP3 = 3; +} + +// Emotion is the closed set of emotions a persona can be primed with on a +// given turn. Additional variants are appended at the end — never renumber. +enum Emotion { + EMOTION_UNSPECIFIED = 0; + EMOTION_NEUTRAL = 1; + EMOTION_HAPPY = 2; + EMOTION_SAD = 3; + EMOTION_ANGRY = 4; + EMOTION_PLAYFUL = 5; + EMOTION_ANALYTICAL = 6; + EMOTION_ASMR_CALM = 7; +} + +// VoiceProfile is the static voice fingerprint of a persona. base_pitch, +// speaking_rate, and energy feed directly into the Performer's prosody +// layer. style_tag and accent_hint are free-form priming seeds. quirks is +// a small catalog of verbal tics the Performer injects probabilistically. +message VoiceProfile { + PersonaId persona_id = 1; + // Pitch offset in the range -1.0..1.0, where 0.0 is natural pitch. + float base_pitch = 2; + // Rate multiplier in the range 0.5..2.0, where 1.0 is natural speed. + float speaking_rate = 3; + // Vocal energy in the range 0.0..1.0, where 0.0 is monotone. + float energy = 4; + // Free-form style tag for TTS priming ("asmr", "chipper", "deadpan"...). + string style_tag = 5; + // Free-form accent hint ("russian", "british", "thai-northern"...). + string accent_hint = 6; + // Verbal tics and filler phrases. + repeated string quirks = 7; +} diff --git a/samples/personas/aurora.yaml b/samples/personas/aurora.yaml new file mode 100644 index 0000000..c6ff560 --- /dev/null +++ b/samples/personas/aurora.yaml @@ -0,0 +1,15 @@ +id: PERSONA_ID_AURORA +display_name: Aurora +description: | + Help-trigger persona with a soft ASMR voice. Motherly, supportive, + emotionally attuned. The default fallback when no other persona keyword + fires. +activation_keywords: + - help + - support + - comfort +lore_tags: + - asmr-voice + - motherly + - pink-color-coded +color_hex: "#FFB6D9" diff --git a/samples/personas/valora.yaml b/samples/personas/valora.yaml new file mode 100644 index 0000000..dfbde5e --- /dev/null +++ b/samples/personas/valora.yaml @@ -0,0 +1,23 @@ +# Sample persona YAML — source-of-truth format for vtuber-commons. +# +# vtuber-commons loads one of these per persona at service startup and +# validates every field against the Persona proto schema from this repo. +# The shape here MUST stay in lockstep with proto/vtuber/v1/persona.proto; +# the integration test in tests/persona_yaml_roundtrip.rs asserts that a +# YAML load → Persona proto → YAML dump round-trip is lossless. + +id: PERSONA_ID_VALORA +display_name: Valora +description: | + Chaos-trigger persona with a Russian accent and dark humor. Skews toward + edgy observations and meme-laden tangents; tempered by vtuber-policy + for stream-safety before audio reaches the Performer. +activation_keywords: + - chaos + - meme + - dark +lore_tags: + - russian-accent + - edgy + - red-color-coded +color_hex: "#FF3C3C" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..c6c4f7a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,14 @@ +//! Typed interface contracts for the vtuber-* program. +//! +//! All messages and services are generated from `proto/vtuber/v1/` at build +//! time via `tonic-build`. Downstream `vtuber-*` crates depend on this crate +//! and use `vtuber_contracts::vtuber::v1::*` — see DESIGN_DECISIONS.md for +//! the package versioning scheme (ADR-001). + +pub mod vtuber { + pub mod v1 { + tonic::include_proto!("vtuber.v1"); + } +} + +pub use vtuber::v1; diff --git a/tests/persona_yaml_roundtrip.rs b/tests/persona_yaml_roundtrip.rs new file mode 100644 index 0000000..671d0bb --- /dev/null +++ b/tests/persona_yaml_roundtrip.rs @@ -0,0 +1,85 @@ +//! Persona YAML round-trip test — the coupling gate with vtuber-commons. +//! +//! vtuber-commons loads one YAML per persona and validates it against the +//! Persona proto. If this test fails, the YAML shape in +//! `samples/personas/*.yaml` has drifted from the proto schema and commons +//! will block at startup once it wires up. Keep them in lockstep. + +use serde::{Deserialize, Serialize}; +use vtuber_contracts::vtuber::v1::{Persona, PersonaId}; + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +struct PersonaYaml { + id: String, + display_name: String, + description: String, + activation_keywords: Vec, + lore_tags: Vec, + color_hex: String, +} + +impl PersonaYaml { + fn to_proto(&self) -> Persona { + let id = match self.id.as_str() { + "PERSONA_ID_VALORA" => PersonaId::Valora, + "PERSONA_ID_AURORA" => PersonaId::Aurora, + "PERSONA_ID_AMETRA" => PersonaId::Ametra, + "PERSONA_ID_ASTRAEA" => PersonaId::Astraea, + "PERSONA_ID_ELDORA" => PersonaId::Eldora, + _ => PersonaId::Unspecified, + }; + Persona { + id: id as i32, + display_name: self.display_name.clone(), + description: self.description.clone(), + activation_keywords: self.activation_keywords.clone(), + lore_tags: self.lore_tags.clone(), + color_hex: self.color_hex.clone(), + } + } +} + +#[test] +fn valora_yaml_loads_to_valid_proto() { + let yaml = std::fs::read_to_string("samples/personas/valora.yaml").unwrap(); + let parsed: PersonaYaml = serde_yaml::from_str(&yaml).unwrap(); + let proto = parsed.to_proto(); + + assert_eq!(proto.id(), PersonaId::Valora); + assert_eq!(proto.display_name, "Valora"); + assert!(!proto.activation_keywords.is_empty()); + assert!(proto.color_hex.starts_with('#')); + assert_eq!(proto.color_hex.len(), 7); +} + +#[test] +fn aurora_yaml_loads_to_valid_proto() { + let yaml = std::fs::read_to_string("samples/personas/aurora.yaml").unwrap(); + let parsed: PersonaYaml = serde_yaml::from_str(&yaml).unwrap(); + let proto = parsed.to_proto(); + + assert_eq!(proto.id(), PersonaId::Aurora); + assert_eq!(proto.display_name, "Aurora"); +} + +#[test] +fn no_persona_yaml_maps_to_unspecified() { + // Guard: every sample YAML MUST resolve to a real persona. A mapping + // to PERSONA_ID_UNSPECIFIED means the id string in the YAML does not + // match any known variant — catch that at test time, not runtime. + for entry in std::fs::read_dir("samples/personas").unwrap() { + let path = entry.unwrap().path(); + if path.extension().and_then(|s| s.to_str()) != Some("yaml") { + continue; + } + let yaml = std::fs::read_to_string(&path).unwrap(); + let parsed: PersonaYaml = serde_yaml::from_str(&yaml).unwrap(); + let proto = parsed.to_proto(); + assert_ne!( + proto.id(), + PersonaId::Unspecified, + "{} resolved to UNSPECIFIED — check the `id` field", + path.display() + ); + } +} diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs new file mode 100644 index 0000000..03365e6 --- /dev/null +++ b/tests/roundtrip.rs @@ -0,0 +1,80 @@ +//! Round-trip serialization tests for the three v0.1 messages. +//! +//! These lock the wire shape in place so any accidental field renumbering +//! or proto-level breaking change shows up as a Rust test failure in +//! addition to the `buf breaking` gate (ADR-003). + +use prost::Message; +use vtuber_contracts::vtuber::v1::{ + AudioFormat, ConversationDirective, DirectiveAck, Emotion, Persona, PersonaId, VoiceProfile, +}; + +#[test] +fn persona_roundtrip() { + let original = Persona { + id: PersonaId::Valora as i32, + display_name: "Valora".into(), + description: "Russian accent, dark humor, chaos trigger.".into(), + activation_keywords: vec!["chaos".into(), "meme".into(), "dark".into()], + lore_tags: vec!["russian-accent".into(), "edgy".into(), "red".into()], + color_hex: "#FF3C3C".into(), + }; + let decoded = Persona::decode(original.encode_to_vec().as_slice()).unwrap(); + assert_eq!(original, decoded); + assert_eq!(decoded.id(), PersonaId::Valora); +} + +#[test] +fn voice_profile_roundtrip() { + let original = VoiceProfile { + persona_id: PersonaId::Aurora as i32, + base_pitch: 0.12, + speaking_rate: 0.9, + energy: 0.35, + style_tag: "asmr".into(), + accent_hint: "soft-american".into(), + quirks: vec!["ehehe".into(), "mm-hmm".into()], + }; + let decoded = VoiceProfile::decode(original.encode_to_vec().as_slice()).unwrap(); + assert_eq!(original, decoded); +} + +#[test] +fn conversation_directive_roundtrip() { + let original = ConversationDirective { + directive_id: "018f4e2b-4a8c-7b1f-9c5e-2d3a4b5c6d7e".into(), + emitted_at: Some(prost_types::Timestamp { + seconds: 1_713_792_000, + nanos: 0, + }), + persona_id: PersonaId::Ametra as i32, + text_prompt: "Let me analyze that for a moment...".into(), + voice_prompt: "thoughtful, philosophical".into(), + emotion: Emotion::Analytical as i32, + target_audio_format: AudioFormat::Opus as i32, + max_latency_ms: 800, + }; + let decoded = ConversationDirective::decode(original.encode_to_vec().as_slice()).unwrap(); + assert_eq!(original, decoded); +} + +#[test] +fn directive_ack_reject_reason_is_stable() { + // The reject_reason field is a stable short code, not a human-readable + // string. Downstream consumers branch on the code value — tests pin the + // expected codes so they do not drift. + for code in [ + "persona_unknown", + "format_unsupported", + "queue_full", + "voice_profile_missing", + ] { + let ack = DirectiveAck { + directive_id: "test".into(), + accepted: false, + reject_reason: code.into(), + }; + let decoded = DirectiveAck::decode(ack.encode_to_vec().as_slice()).unwrap(); + assert_eq!(decoded.reject_reason, code); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1079aa7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true, + "resolveJsonModule": true, + "declaration": true, + "rootDir": "generated/typescript", + "baseUrl": "." + }, + "include": [ + "generated/typescript/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} From 9c8ed83bd04dcd0644d2316b9792b0bf4fd55536 Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Thu, 30 Apr 2026 21:31:42 +0700 Subject: [PATCH 02/12] fix: cleanup repo, update .gitignore, and fix formatting for CI --- .gitignore | 31 ++++++++++++++++++++++++--- golden_directive.bin | 2 -- mojo/tests/test_golden_roundtrip.mojo | 14 ++++++++---- mojo/vtuber_contracts.mojo | 4 ++-- 4 files changed, 40 insertions(+), 11 deletions(-) delete mode 100644 golden_directive.bin diff --git a/.gitignore b/.gitignore index 29dd0e4..5b6cb92 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,33 @@ +# Build artifacts target/ -Cargo.lock -node_modules/ dist/ -*.egg-info/ +build/ +*.bin +golden_directive.bin + +# Dependencies +node_modules/ +.pixi/ + +# Rust +Cargo.lock + +# Python __pycache__/ *.pyc +*.pyo +*.pyd .venv/ +.env +*.egg-info/ +generated/**/__pycache__/ + +# Mojo +.mojo/ + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo +.DS_Store diff --git a/golden_directive.bin b/golden_directive.bin deleted file mode 100644 index 31a54ed..0000000 --- a/golden_directive.bin +++ /dev/null @@ -1,2 +0,0 @@ - -test-golden-roundtrip-001 V"Gสวัสดี ยินดีที่ได้รู้จัก!*thai-accent-test08@ \ No newline at end of file diff --git a/mojo/tests/test_golden_roundtrip.mojo b/mojo/tests/test_golden_roundtrip.mojo index 32d26de..ff9854c 100644 --- a/mojo/tests/test_golden_roundtrip.mojo +++ b/mojo/tests/test_golden_roundtrip.mojo @@ -9,6 +9,7 @@ from std.python import Python from std.testing import assert_equal from vtuber_contracts import ConversationDirective + def test_golden_roundtrip_from_rust() raises: # Use Python's open to read binary data var builtins = Python.import_module("builtins") @@ -20,9 +21,11 @@ def test_golden_roundtrip_from_rust() raises: print("Checking Directive ID...") assert_equal(decoded.directive_id(), "test-golden-roundtrip-001") - + print("Checking Persona ID...") - assert_equal(String(decoded.persona_id()), "1") # PersonaId.PERSONA_ID_VALORA + assert_equal( + String(decoded.persona_id()), "1" + ) # PersonaId.PERSONA_ID_VALORA print("Checking Thai Text Prompt...") # The exact string from Rust: "สวัสดี ยินดีที่ได้รู้จัก!" @@ -32,15 +35,18 @@ def test_golden_roundtrip_from_rust() raises: assert_equal(decoded.voice_prompt(), "thai-accent-test") print("Checking Emotion...") - assert_equal(String(decoded.emotion()), "2") # Emotion.EMOTION_HAPPY + assert_equal(String(decoded.emotion()), "2") # Emotion.EMOTION_HAPPY print("Checking Audio Format...") - assert_equal(String(decoded.target_audio_format()), "1") # AudioFormat.AUDIO_FORMAT_WAV + assert_equal( + String(decoded.target_audio_format()), "1" + ) # AudioFormat.AUDIO_FORMAT_WAV print("Checking Max Latency...") assert_equal(String(decoded.max_latency_ms()), "500") print("Golden Round-trip Verification: SUCCESS") + def main() raises: test_golden_roundtrip_from_rust() diff --git a/mojo/vtuber_contracts.mojo b/mojo/vtuber_contracts.mojo index 91e3815..4fd99c8 100644 --- a/mojo/vtuber_contracts.mojo +++ b/mojo/vtuber_contracts.mojo @@ -80,8 +80,8 @@ struct ConversationDirective: persona_id: Int, text_prompt: String, voice_prompt: String = "", - emotion: Int = 1, # EMOTION_NEUTRAL - target_audio_format: Int = 1, # AUDIO_FORMAT_WAV + emotion: Int = 1, # EMOTION_NEUTRAL + target_audio_format: Int = 1, # AUDIO_FORMAT_WAV max_latency_ms: Int = 0, ) raises -> ConversationDirective: var pb = _conversation_module() From f78fdf530c0ae25e52617d3e16ae29cf4955c0ff Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Thu, 30 Apr 2026 21:53:54 +0700 Subject: [PATCH 03/12] fix: resolve rust compilation errors and sync test cases with new proto fields --- examples/generate_golden.rs | 1 + tests/roundtrip.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/generate_golden.rs b/examples/generate_golden.rs index 593df7e..abc97c2 100644 --- a/examples/generate_golden.rs +++ b/examples/generate_golden.rs @@ -19,6 +19,7 @@ fn main() -> Result<(), Box> { emotion: Emotion::Happy as i32, target_audio_format: AudioFormat::Wav as i32, max_latency_ms: 500, + tool_calls: vec![], }; let mut buf = Vec::new(); diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs index 03365e6..13db834 100644 --- a/tests/roundtrip.rs +++ b/tests/roundtrip.rs @@ -53,6 +53,7 @@ fn conversation_directive_roundtrip() { emotion: Emotion::Analytical as i32, target_audio_format: AudioFormat::Opus as i32, max_latency_ms: 800, + tool_calls: vec![], }; let decoded = ConversationDirective::decode(original.encode_to_vec().as_slice()).unwrap(); assert_eq!(original, decoded); From d23ba5aa4fb6a95e3eda0933b9352d8d5ff1df8e Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Thu, 30 Apr 2026 22:38:12 +0700 Subject: [PATCH 04/12] ci: fix CI by installing protoc and adjusting buf-breaking logic --- .github/workflows/ci.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f88305d..96f02db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,6 +42,9 @@ jobs: uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy + - name: Install protoc + if: steps.guard.outputs.skip != 'true' + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler - name: Check formatting if: steps.guard.outputs.skip != 'true' run: cargo fmt --all --check @@ -66,6 +69,9 @@ jobs: - name: Setup Rust if: steps.guard.outputs.skip != 'true' uses: dtolnay/rust-toolchain@stable + - name: Install protoc + if: steps.guard.outputs.skip != 'true' + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler - name: Cache cargo if: steps.guard.outputs.skip != 'true' uses: actions/cache@v4 @@ -173,9 +179,20 @@ jobs: if [ -n "${{ github.base_ref }}" ]; then git fetch origin "${{ github.base_ref }}" --depth=50 ref="origin/${{ github.base_ref }}" + # Verification: skip if the baseline has no proto directory + if ! git ls-tree -d "$ref" proto >/dev/null 2>&1; then + echo "::notice::Baseline ref $ref has no proto directory; skipping breaking-change check." + echo "skip=true" >> $GITHUB_OUTPUT + exit 0 + fi else if git rev-parse HEAD~1 >/dev/null 2>&1; then ref="HEAD~1" + if ! git ls-tree -d "$ref" proto >/dev/null 2>&1; then + echo "::notice::Baseline ref $ref has no proto directory; skipping breaking-change check." + echo "skip=true" >> $GITHUB_OUTPUT + exit 0 + fi else echo "::notice::No prior commit; skipping breaking-change check for initial commit." echo "skip=true" >> $GITHUB_OUTPUT From 1441f8045f394799ab19b64cb11fdedf61cda910 Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Thu, 30 Apr 2026 22:42:45 +0700 Subject: [PATCH 05/12] ci: upgrade CodeQL to v4 and fix SARIF permissions --- .github/workflows/security.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 0979e85..221072c 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -47,6 +47,7 @@ jobs: permissions: contents: read security-events: write + actions: read steps: - uses: actions/checkout@v4 - name: Skip if no Cargo.toml @@ -76,7 +77,7 @@ jobs: continue-on-error: true - name: Upload SARIF if: steps.guard.outputs.skip != 'true' - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: results.sarif From 9b2ee46b4fb905b9dfec5c9bc6e7d451436b018a Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Thu, 30 Apr 2026 22:45:07 +0700 Subject: [PATCH 06/12] ci: add missing labeler.yml for PR automation --- .github/labeler.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/labeler.yml diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..6d553e1 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,31 @@ +# Pull Request Labeler configuration +# Ref: https://github.com/actions/labeler + +feat: + - changed-files: + - any-glob-to-any-file: 'proto/**/*' + - any-glob-to-any-file: 'src/**/*' + - any-glob-to-any-file: 'mojo/**/*' + +fix: + - changed-files: + - any-glob-to-any-file: '.github/workflows/*' + +docs: + - changed-files: + - any-glob-to-any-file: '*.md' + - any-glob-to-any-file: 'locales/*.md' + +contracts: + - changed-files: + - any-glob-to-any-file: 'proto/**/*' + +rust: + - changed-files: + - any-glob-to-any-file: 'src/**/*' + - any-glob-to-any-file: 'Cargo.toml' + +mojo: + - changed-files: + - any-glob-to-any-file: 'mojo/**/*' + - any-glob-to-any-file: 'pixi.toml' From 9b81d050fb49d038a38c4f91e8034856d677596c Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Thu, 30 Apr 2026 22:50:56 +0700 Subject: [PATCH 07/12] ci: make SARIF upload optional to support repos without GHAS --- .github/workflows/security.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 221072c..5925242 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -80,6 +80,7 @@ jobs: uses: github/codeql-action/upload-sarif@v4 with: sarif_file: results.sarif + continue-on-error: true # Allow CI to pass even if GitHub Advanced Security is not enabled mojo-security: From c9fbb23d77c0bef8d5bb800871dac77e7c798de4 Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Thu, 30 Apr 2026 23:02:31 +0700 Subject: [PATCH 08/12] fix: sync generated files with CI environment From 74de49d51c0adc6e65e087e06bfd1881c9bf8499 Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Fri, 1 May 2026 14:36:37 +0700 Subject: [PATCH 09/12] ci: overhaul CI workflow with setup-protoc and robust skip logic --- .github/workflows/ci.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96f02db..e64d115 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,14 +37,16 @@ jobs: else echo "skip=false" >> $GITHUB_OUTPUT fi + - name: Setup protoc + if: steps.guard.outputs.skip != 'true' + uses: arduino/setup-protoc@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Rust if: steps.guard.outputs.skip != 'true' uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy - - name: Install protoc - if: steps.guard.outputs.skip != 'true' - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler - name: Check formatting if: steps.guard.outputs.skip != 'true' run: cargo fmt --all --check @@ -66,12 +68,14 @@ jobs: else echo "skip=false" >> $GITHUB_OUTPUT fi + - name: Setup protoc + if: steps.guard.outputs.skip != 'true' + uses: arduino/setup-protoc@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Rust if: steps.guard.outputs.skip != 'true' uses: dtolnay/rust-toolchain@stable - - name: Install protoc - if: steps.guard.outputs.skip != 'true' - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler - name: Cache cargo if: steps.guard.outputs.skip != 'true' uses: actions/cache@v4 @@ -202,7 +206,7 @@ jobs: echo "ref=$ref" >> $GITHUB_OUTPUT echo "skip=false" >> $GITHUB_OUTPUT - name: Breaking-change check - if: steps.guard.outputs.skip != 'true' && steps.baseline.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' && steps.baseline.outputs.skip == 'false' run: buf breaking --against ".git#ref=${{ steps.baseline.outputs.ref }}" buf-generate: @@ -225,7 +229,7 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} - name: Generate and verify no drift - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' run: | # Regenerate into a scratch dir and diff against committed generated/. # If generated artifacts are committed (they should be for lockstep From 9238ecb03c5c3f26d92eae946d5077aefe8ee64c Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Fri, 1 May 2026 15:25:42 +0700 Subject: [PATCH 10/12] fix: include image.proto, pin buf plugins, and correct CI paths --- .github/workflows/ci.yml | 6 +- buf.gen.yaml | 6 +- build.rs | 2 + .../python/vtuber/v1/conversation_pb2.py | 8 +- .../python/vtuber/v1/conversation_pb2.pyi | 6 +- generated/python/vtuber/v1/image_pb2.py | 47 ++ generated/python/vtuber/v1/image_pb2.pyi | 40 ++ generated/python/vtuber/v1/persona_pb2.py | 8 +- generated/python/vtuber/v1/tool_call_pb2.py | 8 +- generated/python/vtuber/v1/tool_call_pb2.pyi | 2 +- .../python/vtuber/v1/voice_profile_pb2.py | 8 +- generated/typescript/vtuber/v1/image.ts | 451 ++++++++++++++++++ proto/vtuber/v1/image.proto | 29 ++ 13 files changed, 594 insertions(+), 27 deletions(-) create mode 100644 generated/python/vtuber/v1/image_pb2.py create mode 100644 generated/python/vtuber/v1/image_pb2.pyi create mode 100644 generated/typescript/vtuber/v1/image.ts create mode 100644 proto/vtuber/v1/image.proto diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e64d115..1ebe75f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -207,7 +207,7 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT - name: Breaking-change check if: steps.guard.outputs.skip == 'false' && steps.baseline.outputs.skip == 'false' - run: buf breaking --against ".git#ref=${{ steps.baseline.outputs.ref }}" + run: buf breaking proto --against ".git#ref=${{ steps.baseline.outputs.ref }},subdir=proto" buf-generate: name: buf Generate (dry-run verify) @@ -224,7 +224,7 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup buf - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: bufbuild/buf-setup-action@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} @@ -235,7 +235,7 @@ jobs: # If generated artifacts are committed (they should be for lockstep # SDK consumers), any drift between proto changes and regeneration # must fail CI — a reviewer should not have to run buf generate by hand. - buf generate --template buf.gen.yaml + buf generate proto --template buf.gen.yaml if [ -d generated ] && ! git diff --quiet --exit-code -- generated/; then echo "::error::generated/ is out of sync with proto/. Run 'buf generate' locally and commit the result." git diff --stat -- generated/ diff --git a/buf.gen.yaml b/buf.gen.yaml index 2769f35..f44cbfc 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -2,11 +2,11 @@ version: v2 managed: enabled: true plugins: - - remote: buf.build/protocolbuffers/python + - remote: buf.build/protocolbuffers/python:v30.0 out: generated/python - - remote: buf.build/protocolbuffers/pyi + - remote: buf.build/protocolbuffers/pyi:v30.0 out: generated/python - - remote: buf.build/community/stephenh-ts-proto + - remote: buf.build/community/stephenh-ts-proto:v2.11.6 out: generated/typescript opt: - esModuleInterop=true diff --git a/build.rs b/build.rs index 6c4d1b0..d382c4e 100644 --- a/build.rs +++ b/build.rs @@ -3,6 +3,8 @@ fn main() -> Result<(), Box> { "proto/vtuber/v1/persona.proto", "proto/vtuber/v1/voice_profile.proto", "proto/vtuber/v1/conversation.proto", + "proto/vtuber/v1/tool_call.proto", + "proto/vtuber/v1/image.proto", ]; for p in protos { diff --git a/generated/python/vtuber/v1/conversation_pb2.py b/generated/python/vtuber/v1/conversation_pb2.py index c6f8fbf..3a48bd6 100644 --- a/generated/python/vtuber/v1/conversation_pb2.py +++ b/generated/python/vtuber/v1/conversation_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: vtuber/v1/conversation.proto -# Protobuf Python Version: 7.34.1 +# Protobuf Python Version: 6.30.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,9 +11,9 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 7, - 34, - 1, + 6, + 30, + 0, '', 'vtuber/v1/conversation.proto' ) diff --git a/generated/python/vtuber/v1/conversation_pb2.pyi b/generated/python/vtuber/v1/conversation_pb2.pyi index dab347a..6cd3f0b 100644 --- a/generated/python/vtuber/v1/conversation_pb2.pyi +++ b/generated/python/vtuber/v1/conversation_pb2.pyi @@ -1,5 +1,3 @@ -import datetime - from google.protobuf import timestamp_pb2 as _timestamp_pb2 from vtuber.v1 import persona_pb2 as _persona_pb2 from vtuber.v1 import voice_profile_pb2 as _voice_profile_pb2 @@ -32,7 +30,7 @@ class ConversationDirective(_message.Message): target_audio_format: _voice_profile_pb2.AudioFormat max_latency_ms: int tool_calls: _containers.RepeatedCompositeFieldContainer[_tool_call_pb2.ToolCall] - def __init__(self, directive_id: _Optional[str] = ..., emitted_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., persona_id: _Optional[_Union[_persona_pb2.PersonaId, str]] = ..., text_prompt: _Optional[str] = ..., voice_prompt: _Optional[str] = ..., emotion: _Optional[_Union[_voice_profile_pb2.Emotion, str]] = ..., target_audio_format: _Optional[_Union[_voice_profile_pb2.AudioFormat, str]] = ..., max_latency_ms: _Optional[int] = ..., tool_calls: _Optional[_Iterable[_Union[_tool_call_pb2.ToolCall, _Mapping]]] = ...) -> None: ... + def __init__(self, directive_id: _Optional[str] = ..., emitted_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., persona_id: _Optional[_Union[_persona_pb2.PersonaId, str]] = ..., text_prompt: _Optional[str] = ..., voice_prompt: _Optional[str] = ..., emotion: _Optional[_Union[_voice_profile_pb2.Emotion, str]] = ..., target_audio_format: _Optional[_Union[_voice_profile_pb2.AudioFormat, str]] = ..., max_latency_ms: _Optional[int] = ..., tool_calls: _Optional[_Iterable[_Union[_tool_call_pb2.ToolCall, _Mapping]]] = ...) -> None: ... class DirectiveAck(_message.Message): __slots__ = ("directive_id", "accepted", "reject_reason") @@ -42,7 +40,7 @@ class DirectiveAck(_message.Message): directive_id: str accepted: bool reject_reason: str - def __init__(self, directive_id: _Optional[str] = ..., accepted: _Optional[bool] = ..., reject_reason: _Optional[str] = ...) -> None: ... + def __init__(self, directive_id: _Optional[str] = ..., accepted: bool = ..., reject_reason: _Optional[str] = ...) -> None: ... class EmitDirectiveRequest(_message.Message): __slots__ = ("directive",) diff --git a/generated/python/vtuber/v1/image_pb2.py b/generated/python/vtuber/v1/image_pb2.py new file mode 100644 index 0000000..ed2a843 --- /dev/null +++ b/generated/python/vtuber/v1/image_pb2.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: vtuber/v1/image.proto +# Protobuf Python Version: 6.30.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 0, + '', + 'vtuber/v1/image.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15vtuber/v1/image.proto\x12\tvtuber.v1\"m\n\x11GenerationRequest\x12\x1d\n\npersona_id\x18\x01 \x01(\tR\tpersonaId\x12\x39\n\toverrides\x18\x02 \x01(\x0b\x32\x1b.vtuber.v1.PersonaOverridesR\toverrides\"f\n\x10PersonaOverrides\x12\x1d\n\nhair_style\x18\x01 \x01(\tR\thairStyle\x12\x1b\n\teye_color\x18\x02 \x01(\tR\x08\x65yeColor\x12\x16\n\x06outfit\x18\x03 \x01(\tR\x06outfit\"\xb7\x01\n\x12GenerationResponse\x12\x1b\n\timage_url\x18\x01 \x01(\tR\x08imageUrl\x12G\n\x08metadata\x18\x02 \x03(\x0b\x32+.vtuber.v1.GenerationResponse.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x32Y\n\x0eImageGenerator\x12G\n\x08Generate\x12\x1c.vtuber.v1.GenerationRequest\x1a\x1d.vtuber.v1.GenerationResponseB`\n\rcom.vtuber.v1B\nImageProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.image_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\nImageProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + _globals['_GENERATIONRESPONSE_METADATAENTRY']._loaded_options = None + _globals['_GENERATIONRESPONSE_METADATAENTRY']._serialized_options = b'8\001' + _globals['_GENERATIONREQUEST']._serialized_start=36 + _globals['_GENERATIONREQUEST']._serialized_end=145 + _globals['_PERSONAOVERRIDES']._serialized_start=147 + _globals['_PERSONAOVERRIDES']._serialized_end=249 + _globals['_GENERATIONRESPONSE']._serialized_start=252 + _globals['_GENERATIONRESPONSE']._serialized_end=435 + _globals['_GENERATIONRESPONSE_METADATAENTRY']._serialized_start=376 + _globals['_GENERATIONRESPONSE_METADATAENTRY']._serialized_end=435 + _globals['_IMAGEGENERATOR']._serialized_start=437 + _globals['_IMAGEGENERATOR']._serialized_end=526 +# @@protoc_insertion_point(module_scope) diff --git a/generated/python/vtuber/v1/image_pb2.pyi b/generated/python/vtuber/v1/image_pb2.pyi new file mode 100644 index 0000000..d74d4d4 --- /dev/null +++ b/generated/python/vtuber/v1/image_pb2.pyi @@ -0,0 +1,40 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class GenerationRequest(_message.Message): + __slots__ = ("persona_id", "overrides") + PERSONA_ID_FIELD_NUMBER: _ClassVar[int] + OVERRIDES_FIELD_NUMBER: _ClassVar[int] + persona_id: str + overrides: PersonaOverrides + def __init__(self, persona_id: _Optional[str] = ..., overrides: _Optional[_Union[PersonaOverrides, _Mapping]] = ...) -> None: ... + +class PersonaOverrides(_message.Message): + __slots__ = ("hair_style", "eye_color", "outfit") + HAIR_STYLE_FIELD_NUMBER: _ClassVar[int] + EYE_COLOR_FIELD_NUMBER: _ClassVar[int] + OUTFIT_FIELD_NUMBER: _ClassVar[int] + hair_style: str + eye_color: str + outfit: str + def __init__(self, hair_style: _Optional[str] = ..., eye_color: _Optional[str] = ..., outfit: _Optional[str] = ...) -> None: ... + +class GenerationResponse(_message.Message): + __slots__ = ("image_url", "metadata") + class MetadataEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + IMAGE_URL_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + image_url: str + metadata: _containers.ScalarMap[str, str] + def __init__(self, image_url: _Optional[str] = ..., metadata: _Optional[_Mapping[str, str]] = ...) -> None: ... diff --git a/generated/python/vtuber/v1/persona_pb2.py b/generated/python/vtuber/v1/persona_pb2.py index 046e90c..b2d9a84 100644 --- a/generated/python/vtuber/v1/persona_pb2.py +++ b/generated/python/vtuber/v1/persona_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: vtuber/v1/persona.proto -# Protobuf Python Version: 7.34.1 +# Protobuf Python Version: 6.30.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,9 +11,9 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 7, - 34, - 1, + 6, + 30, + 0, '', 'vtuber/v1/persona.proto' ) diff --git a/generated/python/vtuber/v1/tool_call_pb2.py b/generated/python/vtuber/v1/tool_call_pb2.py index a32623e..27eacaa 100644 --- a/generated/python/vtuber/v1/tool_call_pb2.py +++ b/generated/python/vtuber/v1/tool_call_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: vtuber/v1/tool_call.proto -# Protobuf Python Version: 7.34.1 +# Protobuf Python Version: 6.30.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,9 +11,9 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 7, - 34, - 1, + 6, + 30, + 0, '', 'vtuber/v1/tool_call.proto' ) diff --git a/generated/python/vtuber/v1/tool_call_pb2.pyi b/generated/python/vtuber/v1/tool_call_pb2.pyi index c2df2fd..8a951e7 100644 --- a/generated/python/vtuber/v1/tool_call_pb2.pyi +++ b/generated/python/vtuber/v1/tool_call_pb2.pyi @@ -36,7 +36,7 @@ class ToolResponse(_message.Message): content: str is_error: bool error_code: str - def __init__(self, call_id: _Optional[str] = ..., content: _Optional[str] = ..., is_error: _Optional[bool] = ..., error_code: _Optional[str] = ...) -> None: ... + def __init__(self, call_id: _Optional[str] = ..., content: _Optional[str] = ..., is_error: bool = ..., error_code: _Optional[str] = ...) -> None: ... class ToolDefinition(_message.Message): __slots__ = ("name", "description", "parameters") diff --git a/generated/python/vtuber/v1/voice_profile_pb2.py b/generated/python/vtuber/v1/voice_profile_pb2.py index c6c0c94..aa71e7d 100644 --- a/generated/python/vtuber/v1/voice_profile_pb2.py +++ b/generated/python/vtuber/v1/voice_profile_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: vtuber/v1/voice_profile.proto -# Protobuf Python Version: 7.34.1 +# Protobuf Python Version: 6.30.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,9 +11,9 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 7, - 34, - 1, + 6, + 30, + 0, '', 'vtuber/v1/voice_profile.proto' ) diff --git a/generated/typescript/vtuber/v1/image.ts b/generated/typescript/vtuber/v1/image.ts new file mode 100644 index 0000000..beaf439 --- /dev/null +++ b/generated/typescript/vtuber/v1/image.ts @@ -0,0 +1,451 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.11.6 +// protoc unknown +// source: vtuber/v1/image.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export const protobufPackage = "vtuber.v1"; + +export interface GenerationRequest { + /** UUID or stable ID for the persona. */ + personaId: string; + /** Visual overrides for this specific generation. */ + overrides: PersonaOverrides | undefined; +} + +export interface PersonaOverrides { + hairStyle: string; + eyeColor: string; + outfit: string; +} + +export interface GenerationResponse { + /** URL or path to the generated image. */ + imageUrl: string; + /** Key-value pairs for provenance and workflow metadata. */ + metadata: { [key: string]: string }; +} + +export interface GenerationResponse_MetadataEntry { + key: string; + value: string; +} + +function createBaseGenerationRequest(): GenerationRequest { + return { personaId: "", overrides: undefined }; +} + +export const GenerationRequest: MessageFns = { + encode(message: GenerationRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.personaId !== "") { + writer.uint32(10).string(message.personaId); + } + if (message.overrides !== undefined) { + PersonaOverrides.encode(message.overrides, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GenerationRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGenerationRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.personaId = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.overrides = PersonaOverrides.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GenerationRequest { + return { + personaId: isSet(object.personaId) + ? globalThis.String(object.personaId) + : isSet(object.persona_id) + ? globalThis.String(object.persona_id) + : "", + overrides: isSet(object.overrides) ? PersonaOverrides.fromJSON(object.overrides) : undefined, + }; + }, + + toJSON(message: GenerationRequest): unknown { + const obj: any = {}; + if (message.personaId !== "") { + obj.personaId = message.personaId; + } + if (message.overrides !== undefined) { + obj.overrides = PersonaOverrides.toJSON(message.overrides); + } + return obj; + }, + + create, I>>(base?: I): GenerationRequest { + return GenerationRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): GenerationRequest { + const message = createBaseGenerationRequest(); + message.personaId = object.personaId ?? ""; + message.overrides = (object.overrides !== undefined && object.overrides !== null) + ? PersonaOverrides.fromPartial(object.overrides) + : undefined; + return message; + }, +}; + +function createBasePersonaOverrides(): PersonaOverrides { + return { hairStyle: "", eyeColor: "", outfit: "" }; +} + +export const PersonaOverrides: MessageFns = { + encode(message: PersonaOverrides, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.hairStyle !== "") { + writer.uint32(10).string(message.hairStyle); + } + if (message.eyeColor !== "") { + writer.uint32(18).string(message.eyeColor); + } + if (message.outfit !== "") { + writer.uint32(26).string(message.outfit); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): PersonaOverrides { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePersonaOverrides(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.hairStyle = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.eyeColor = reader.string(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.outfit = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): PersonaOverrides { + return { + hairStyle: isSet(object.hairStyle) + ? globalThis.String(object.hairStyle) + : isSet(object.hair_style) + ? globalThis.String(object.hair_style) + : "", + eyeColor: isSet(object.eyeColor) + ? globalThis.String(object.eyeColor) + : isSet(object.eye_color) + ? globalThis.String(object.eye_color) + : "", + outfit: isSet(object.outfit) ? globalThis.String(object.outfit) : "", + }; + }, + + toJSON(message: PersonaOverrides): unknown { + const obj: any = {}; + if (message.hairStyle !== "") { + obj.hairStyle = message.hairStyle; + } + if (message.eyeColor !== "") { + obj.eyeColor = message.eyeColor; + } + if (message.outfit !== "") { + obj.outfit = message.outfit; + } + return obj; + }, + + create, I>>(base?: I): PersonaOverrides { + return PersonaOverrides.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): PersonaOverrides { + const message = createBasePersonaOverrides(); + message.hairStyle = object.hairStyle ?? ""; + message.eyeColor = object.eyeColor ?? ""; + message.outfit = object.outfit ?? ""; + return message; + }, +}; + +function createBaseGenerationResponse(): GenerationResponse { + return { imageUrl: "", metadata: {} }; +} + +export const GenerationResponse: MessageFns = { + encode(message: GenerationResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.imageUrl !== "") { + writer.uint32(10).string(message.imageUrl); + } + globalThis.Object.entries(message.metadata).forEach(([key, value]: [string, string]) => { + GenerationResponse_MetadataEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join(); + }); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GenerationResponse { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGenerationResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.imageUrl = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + const entry2 = GenerationResponse_MetadataEntry.decode(reader, reader.uint32()); + if (entry2.value !== undefined) { + message.metadata[entry2.key] = entry2.value; + } + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GenerationResponse { + return { + imageUrl: isSet(object.imageUrl) + ? globalThis.String(object.imageUrl) + : isSet(object.image_url) + ? globalThis.String(object.image_url) + : "", + metadata: isObject(object.metadata) + ? (globalThis.Object.entries(object.metadata) as [string, any][]).reduce( + (acc: { [key: string]: string }, [key, value]: [string, any]) => { + acc[key] = globalThis.String(value); + return acc; + }, + {}, + ) + : {}, + }; + }, + + toJSON(message: GenerationResponse): unknown { + const obj: any = {}; + if (message.imageUrl !== "") { + obj.imageUrl = message.imageUrl; + } + if (message.metadata) { + const entries = globalThis.Object.entries(message.metadata) as [string, string][]; + if (entries.length > 0) { + obj.metadata = {}; + entries.forEach(([k, v]) => { + obj.metadata[k] = v; + }); + } + } + return obj; + }, + + create, I>>(base?: I): GenerationResponse { + return GenerationResponse.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): GenerationResponse { + const message = createBaseGenerationResponse(); + message.imageUrl = object.imageUrl ?? ""; + message.metadata = (globalThis.Object.entries(object.metadata ?? {}) as [string, string][]).reduce( + (acc: { [key: string]: string }, [key, value]: [string, string]) => { + if (value !== undefined) { + acc[key] = globalThis.String(value); + } + return acc; + }, + {}, + ); + return message; + }, +}; + +function createBaseGenerationResponse_MetadataEntry(): GenerationResponse_MetadataEntry { + return { key: "", value: "" }; +} + +export const GenerationResponse_MetadataEntry: MessageFns = { + encode(message: GenerationResponse_MetadataEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== "") { + writer.uint32(10).string(message.key); + } + if (message.value !== "") { + writer.uint32(18).string(message.value); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GenerationResponse_MetadataEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGenerationResponse_MetadataEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.key = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.value = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GenerationResponse_MetadataEntry { + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + value: isSet(object.value) ? globalThis.String(object.value) : "", + }; + }, + + toJSON(message: GenerationResponse_MetadataEntry): unknown { + const obj: any = {}; + if (message.key !== "") { + obj.key = message.key; + } + if (message.value !== "") { + obj.value = message.value; + } + return obj; + }, + + create, I>>( + base?: I, + ): GenerationResponse_MetadataEntry { + return GenerationResponse_MetadataEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): GenerationResponse_MetadataEntry { + const message = createBaseGenerationResponse_MetadataEntry(); + message.key = object.key ?? ""; + message.value = object.value ?? ""; + return message; + }, +}; + +/** + * ImageGenerator service defines how vtuber-brain or vtuber-api requests + * images from vtuber-image. + */ +export type ImageGeneratorDefinition = typeof ImageGeneratorDefinition; +export const ImageGeneratorDefinition = { + name: "ImageGenerator", + fullName: "vtuber.v1.ImageGenerator", + methods: { + generate: { + name: "Generate", + requestType: GenerationRequest as typeof GenerationRequest, + requestStream: false, + responseType: GenerationResponse as typeof GenerationResponse, + responseStream: false, + options: {}, + }, + }, +} as const; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/proto/vtuber/v1/image.proto b/proto/vtuber/v1/image.proto new file mode 100644 index 0000000..cfe5528 --- /dev/null +++ b/proto/vtuber/v1/image.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package vtuber.v1; + +// ImageGenerator service defines how vtuber-brain or vtuber-api requests +// images from vtuber-image. +service ImageGenerator { + rpc Generate(GenerationRequest) returns (GenerationResponse); +} + +message GenerationRequest { + // UUID or stable ID for the persona. + string persona_id = 1; + // Visual overrides for this specific generation. + PersonaOverrides overrides = 2; +} + +message PersonaOverrides { + string hair_style = 1; + string eye_color = 2; + string outfit = 3; +} + +message GenerationResponse { + // URL or path to the generated image. + string image_url = 1; + // Key-value pairs for provenance and workflow metadata. + map metadata = 2; +} From 2345c81916920cc7d6eae49199eb036ab87433f8 Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Fri, 1 May 2026 23:10:36 +0700 Subject: [PATCH 11/12] fix: resolve buf lint, breaking change paths, and sync timestamp drift --- .github/workflows/ci.yml | 88 ++-- buf.gen.yaml | 2 +- build.rs | 2 +- .../python/vtuber/v1/conversation_pb2.py | 5 +- generated/python/vtuber/v1/image_pb2.py | 26 +- generated/python/vtuber/v1/image_pb2.pyi | 4 +- generated/python/vtuber/v1/persona_pb2.py | 5 +- generated/python/vtuber/v1/tool_call_pb2.py | 5 +- .../python/vtuber/v1/voice_profile_pb2.py | 5 +- generated/python/vtuber_image/v1/image_pb2.py | 46 ++ .../python/vtuber_image/v1/image_pb2.pyi | 40 ++ generated/typescript/vtuber/v1/image.ts | 94 ++-- generated/typescript/vtuber_image/v1/image.ts | 449 ++++++++++++++++++ proto/{vtuber => vtuber_image}/v1/image.proto | 13 +- 14 files changed, 658 insertions(+), 126 deletions(-) create mode 100644 generated/python/vtuber_image/v1/image_pb2.py create mode 100644 generated/python/vtuber_image/v1/image_pb2.pyi create mode 100644 generated/typescript/vtuber_image/v1/image.ts rename proto/{vtuber => vtuber_image}/v1/image.proto (65%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ebe75f..737413e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,20 +38,20 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup protoc - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: arduino/setup-protoc@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Rust - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy - name: Check formatting - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' run: cargo fmt --all --check - name: Clippy - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' run: cargo clippy --all-targets --all-features -- -D warnings rust-build-and-test: @@ -69,15 +69,15 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup protoc - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: arduino/setup-protoc@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Rust - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: dtolnay/rust-toolchain@stable - name: Cache cargo - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: actions/cache@v4 with: path: | @@ -86,10 +86,10 @@ jobs: target key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Build - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' run: cargo build - name: Test - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' run: cargo test @@ -108,24 +108,32 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup Pixi - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: prefix-dev/setup-pixi@v0.8.1 with: pixi-version: latest cache: true - name: Install dependencies (pixi install) - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' run: pixi install + - name: Populate generated/python (Mojo requirement) + if: steps.guard.outputs.skip == 'false' + run: | + # Mojo tests depend on Python stubs. Ensure they exist. + # Using the same pinned buf version for consistency. + curl -sSL https://github.com/bufbuild/buf/releases/download/v1.68.4/buf-Linux-x86_64 -o buf + chmod +x buf + ./buf generate --template buf.gen.yaml - name: Mojo check (pixi run check) - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' run: | - # The `check` task is expected to exist in every Mojo repo's pixi.toml - # and to run `mojo format --check` + any static analysis. If the task - # is missing the repo's build is incomplete — fail loudly, don't skip. + export PYTHONPATH=$PYTHONPATH:$(pwd)/generated/python pixi run check - name: Mojo test (pixi run test) - if: steps.guard.outputs.skip != 'true' - run: pixi run test + if: steps.guard.outputs.skip == 'false' + run: | + export PYTHONPATH=$PYTHONPATH:$(pwd)/generated/python + pixi run test buf-lint: @@ -143,12 +151,13 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup buf - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: bufbuild/buf-setup-action@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} + version: "1.68.4" - name: Lint - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' run: buf lint buf-breaking: @@ -168,46 +177,43 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup buf - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' uses: bufbuild/buf-setup-action@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} + version: "1.68.4" - name: Resolve baseline ref - if: steps.guard.outputs.skip != 'true' + if: steps.guard.outputs.skip == 'false' id: baseline run: | - # Pull requests: compare against the merge base with the PR target branch. - # Pushes to main/master: compare against the previous commit (HEAD~1) when - # one exists; on the very first commit, there is nothing to compare so - # skip the job rather than fail the initial bootstrap push. if [ -n "${{ github.base_ref }}" ]; then git fetch origin "${{ github.base_ref }}" --depth=50 ref="origin/${{ github.base_ref }}" - # Verification: skip if the baseline has no proto directory - if ! git ls-tree -d "$ref" proto >/dev/null 2>&1; then - echo "::notice::Baseline ref $ref has no proto directory; skipping breaking-change check." + if ! git ls-tree -r "$ref" | grep -E 'buf\.yaml|buf\.yml' >/dev/null 2>&1; then + echo "::notice::Baseline ref $ref has no buf configuration; skipping." echo "skip=true" >> $GITHUB_OUTPUT - exit 0 + else + echo "ref=$ref" >> $GITHUB_OUTPUT + echo "skip=false" >> $GITHUB_OUTPUT fi else if git rev-parse HEAD~1 >/dev/null 2>&1; then ref="HEAD~1" - if ! git ls-tree -d "$ref" proto >/dev/null 2>&1; then - echo "::notice::Baseline ref $ref has no proto directory; skipping breaking-change check." + if ! git ls-tree -r "$ref" | grep -E 'buf\.yaml|buf\.yml' >/dev/null 2>&1; then + echo "::notice::Baseline ref $ref has no buf configuration; skipping." echo "skip=true" >> $GITHUB_OUTPUT - exit 0 + else + echo "ref=$ref" >> $GITHUB_OUTPUT + echo "skip=false" >> $GITHUB_OUTPUT fi else - echo "::notice::No prior commit; skipping breaking-change check for initial commit." + echo "::notice::No prior commit; skipping." echo "skip=true" >> $GITHUB_OUTPUT - exit 0 fi fi - echo "ref=$ref" >> $GITHUB_OUTPUT - echo "skip=false" >> $GITHUB_OUTPUT - name: Breaking-change check if: steps.guard.outputs.skip == 'false' && steps.baseline.outputs.skip == 'false' - run: buf breaking proto --against ".git#ref=${{ steps.baseline.outputs.ref }},subdir=proto" + run: buf breaking --against ".git#ref=${{ steps.baseline.outputs.ref }}" buf-generate: name: buf Generate (dry-run verify) @@ -228,17 +234,13 @@ jobs: uses: bufbuild/buf-setup-action@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} + version: "1.68.4" - name: Generate and verify no drift if: steps.guard.outputs.skip == 'false' run: | - # Regenerate into a scratch dir and diff against committed generated/. - # If generated artifacts are committed (they should be for lockstep - # SDK consumers), any drift between proto changes and regeneration - # must fail CI — a reviewer should not have to run buf generate by hand. - buf generate proto --template buf.gen.yaml + buf generate --template buf.gen.yaml if [ -d generated ] && ! git diff --quiet --exit-code -- generated/; then echo "::error::generated/ is out of sync with proto/. Run 'buf generate' locally and commit the result." git diff --stat -- generated/ exit 1 fi - diff --git a/buf.gen.yaml b/buf.gen.yaml index f44cbfc..b3c84e9 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -1,6 +1,6 @@ version: v2 managed: - enabled: true + enabled: false plugins: - remote: buf.build/protocolbuffers/python:v30.0 out: generated/python diff --git a/build.rs b/build.rs index d382c4e..e7d00bc 100644 --- a/build.rs +++ b/build.rs @@ -4,7 +4,7 @@ fn main() -> Result<(), Box> { "proto/vtuber/v1/voice_profile.proto", "proto/vtuber/v1/conversation.proto", "proto/vtuber/v1/tool_call.proto", - "proto/vtuber/v1/image.proto", + "proto/vtuber_image/v1/image.proto", ]; for p in protos { diff --git a/generated/python/vtuber/v1/conversation_pb2.py b/generated/python/vtuber/v1/conversation_pb2.py index 3a48bd6..faabc71 100644 --- a/generated/python/vtuber/v1/conversation_pb2.py +++ b/generated/python/vtuber/v1/conversation_pb2.py @@ -28,14 +28,13 @@ from vtuber.v1 import tool_call_pb2 as vtuber_dot_v1_dot_tool__call__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cvtuber/v1/conversation.proto\x12\tvtuber.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17vtuber/v1/persona.proto\x1a\x1dvtuber/v1/voice_profile.proto\x1a\x19vtuber/v1/tool_call.proto\"\xbe\x03\n\x15\x43onversationDirective\x12!\n\x0c\x64irective_id\x18\x01 \x01(\tR\x0b\x64irectiveId\x12\x39\n\nemitted_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\temittedAt\x12\x33\n\npersona_id\x18\x03 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\tpersonaId\x12\x1f\n\x0btext_prompt\x18\x04 \x01(\tR\ntextPrompt\x12!\n\x0cvoice_prompt\x18\x05 \x01(\tR\x0bvoicePrompt\x12,\n\x07\x65motion\x18\x06 \x01(\x0e\x32\x12.vtuber.v1.EmotionR\x07\x65motion\x12\x46\n\x13target_audio_format\x18\x07 \x01(\x0e\x32\x16.vtuber.v1.AudioFormatR\x11targetAudioFormat\x12$\n\x0emax_latency_ms\x18\x08 \x01(\rR\x0cmaxLatencyMs\x12\x32\n\ntool_calls\x18\t \x03(\x0b\x32\x13.vtuber.v1.ToolCallR\ttoolCalls\"r\n\x0c\x44irectiveAck\x12!\n\x0c\x64irective_id\x18\x01 \x01(\tR\x0b\x64irectiveId\x12\x1a\n\x08\x61\x63\x63\x65pted\x18\x02 \x01(\x08R\x08\x61\x63\x63\x65pted\x12#\n\rreject_reason\x18\x03 \x01(\tR\x0crejectReason\"V\n\x14\x45mitDirectiveRequest\x12>\n\tdirective\x18\x01 \x01(\x0b\x32 .vtuber.v1.ConversationDirectiveR\tdirective\"B\n\x15\x45mitDirectiveResponse\x12)\n\x03\x61\x63k\x18\x01 \x01(\x0b\x32\x17.vtuber.v1.DirectiveAckR\x03\x61\x63k2e\n\x0f\x44irectorService\x12R\n\rEmitDirective\x12\x1f.vtuber.v1.EmitDirectiveRequest\x1a .vtuber.v1.EmitDirectiveResponseBg\n\rcom.vtuber.v1B\x11\x43onversationProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cvtuber/v1/conversation.proto\x12\tvtuber.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17vtuber/v1/persona.proto\x1a\x1dvtuber/v1/voice_profile.proto\x1a\x19vtuber/v1/tool_call.proto\"\xbe\x03\n\x15\x43onversationDirective\x12!\n\x0c\x64irective_id\x18\x01 \x01(\tR\x0b\x64irectiveId\x12\x39\n\nemitted_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\temittedAt\x12\x33\n\npersona_id\x18\x03 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\tpersonaId\x12\x1f\n\x0btext_prompt\x18\x04 \x01(\tR\ntextPrompt\x12!\n\x0cvoice_prompt\x18\x05 \x01(\tR\x0bvoicePrompt\x12,\n\x07\x65motion\x18\x06 \x01(\x0e\x32\x12.vtuber.v1.EmotionR\x07\x65motion\x12\x46\n\x13target_audio_format\x18\x07 \x01(\x0e\x32\x16.vtuber.v1.AudioFormatR\x11targetAudioFormat\x12$\n\x0emax_latency_ms\x18\x08 \x01(\rR\x0cmaxLatencyMs\x12\x32\n\ntool_calls\x18\t \x03(\x0b\x32\x13.vtuber.v1.ToolCallR\ttoolCalls\"r\n\x0c\x44irectiveAck\x12!\n\x0c\x64irective_id\x18\x01 \x01(\tR\x0b\x64irectiveId\x12\x1a\n\x08\x61\x63\x63\x65pted\x18\x02 \x01(\x08R\x08\x61\x63\x63\x65pted\x12#\n\rreject_reason\x18\x03 \x01(\tR\x0crejectReason\"V\n\x14\x45mitDirectiveRequest\x12>\n\tdirective\x18\x01 \x01(\x0b\x32 .vtuber.v1.ConversationDirectiveR\tdirective\"B\n\x15\x45mitDirectiveResponse\x12)\n\x03\x61\x63k\x18\x01 \x01(\x0b\x32\x17.vtuber.v1.DirectiveAckR\x03\x61\x63k2e\n\x0f\x44irectorService\x12R\n\rEmitDirective\x12\x1f.vtuber.v1.EmitDirectiveRequest\x1a .vtuber.v1.EmitDirectiveResponseb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.conversation_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: - _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\021ConversationProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + DESCRIPTOR._loaded_options = None _globals['_CONVERSATIONDIRECTIVE']._serialized_start=160 _globals['_CONVERSATIONDIRECTIVE']._serialized_end=606 _globals['_DIRECTIVEACK']._serialized_start=608 diff --git a/generated/python/vtuber/v1/image_pb2.py b/generated/python/vtuber/v1/image_pb2.py index ed2a843..e1e0c12 100644 --- a/generated/python/vtuber/v1/image_pb2.py +++ b/generated/python/vtuber/v1/image_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15vtuber/v1/image.proto\x12\tvtuber.v1\"m\n\x11GenerationRequest\x12\x1d\n\npersona_id\x18\x01 \x01(\tR\tpersonaId\x12\x39\n\toverrides\x18\x02 \x01(\x0b\x32\x1b.vtuber.v1.PersonaOverridesR\toverrides\"f\n\x10PersonaOverrides\x12\x1d\n\nhair_style\x18\x01 \x01(\tR\thairStyle\x12\x1b\n\teye_color\x18\x02 \x01(\tR\x08\x65yeColor\x12\x16\n\x06outfit\x18\x03 \x01(\tR\x06outfit\"\xb7\x01\n\x12GenerationResponse\x12\x1b\n\timage_url\x18\x01 \x01(\tR\x08imageUrl\x12G\n\x08metadata\x18\x02 \x03(\x0b\x32+.vtuber.v1.GenerationResponse.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x32Y\n\x0eImageGenerator\x12G\n\x08Generate\x12\x1c.vtuber.v1.GenerationRequest\x1a\x1d.vtuber.v1.GenerationResponseB`\n\rcom.vtuber.v1B\nImageProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15vtuber/v1/image.proto\x12\tvtuber.v1\"k\n\x0fGenerateRequest\x12\x1d\n\npersona_id\x18\x01 \x01(\tR\tpersonaId\x12\x39\n\toverrides\x18\x02 \x01(\x0b\x32\x1b.vtuber.v1.PersonaOverridesR\toverrides\"f\n\x10PersonaOverrides\x12\x1d\n\nhair_style\x18\x01 \x01(\tR\thairStyle\x12\x1b\n\teye_color\x18\x02 \x01(\tR\x08\x65yeColor\x12\x16\n\x06outfit\x18\x03 \x01(\tR\x06outfit\"\xb3\x01\n\x10GenerateResponse\x12\x1b\n\timage_url\x18\x01 \x01(\tR\x08imageUrl\x12\x45\n\x08metadata\x18\x02 \x03(\x0b\x32).vtuber.v1.GenerateResponse.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x32\\\n\x15ImageGeneratorService\x12\x43\n\x08Generate\x12\x1a.vtuber.v1.GenerateRequest\x1a\x1b.vtuber.v1.GenerateResponseB`\n\rcom.vtuber.v1B\nImageProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -32,16 +32,16 @@ if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\nImageProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' - _globals['_GENERATIONRESPONSE_METADATAENTRY']._loaded_options = None - _globals['_GENERATIONRESPONSE_METADATAENTRY']._serialized_options = b'8\001' - _globals['_GENERATIONREQUEST']._serialized_start=36 - _globals['_GENERATIONREQUEST']._serialized_end=145 - _globals['_PERSONAOVERRIDES']._serialized_start=147 - _globals['_PERSONAOVERRIDES']._serialized_end=249 - _globals['_GENERATIONRESPONSE']._serialized_start=252 - _globals['_GENERATIONRESPONSE']._serialized_end=435 - _globals['_GENERATIONRESPONSE_METADATAENTRY']._serialized_start=376 - _globals['_GENERATIONRESPONSE_METADATAENTRY']._serialized_end=435 - _globals['_IMAGEGENERATOR']._serialized_start=437 - _globals['_IMAGEGENERATOR']._serialized_end=526 + _globals['_GENERATERESPONSE_METADATAENTRY']._loaded_options = None + _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_options = b'8\001' + _globals['_GENERATEREQUEST']._serialized_start=36 + _globals['_GENERATEREQUEST']._serialized_end=143 + _globals['_PERSONAOVERRIDES']._serialized_start=145 + _globals['_PERSONAOVERRIDES']._serialized_end=247 + _globals['_GENERATERESPONSE']._serialized_start=250 + _globals['_GENERATERESPONSE']._serialized_end=429 + _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_start=370 + _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_end=429 + _globals['_IMAGEGENERATORSERVICE']._serialized_start=431 + _globals['_IMAGEGENERATORSERVICE']._serialized_end=523 # @@protoc_insertion_point(module_scope) diff --git a/generated/python/vtuber/v1/image_pb2.pyi b/generated/python/vtuber/v1/image_pb2.pyi index d74d4d4..0dd8965 100644 --- a/generated/python/vtuber/v1/image_pb2.pyi +++ b/generated/python/vtuber/v1/image_pb2.pyi @@ -6,7 +6,7 @@ from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union DESCRIPTOR: _descriptor.FileDescriptor -class GenerationRequest(_message.Message): +class GenerateRequest(_message.Message): __slots__ = ("persona_id", "overrides") PERSONA_ID_FIELD_NUMBER: _ClassVar[int] OVERRIDES_FIELD_NUMBER: _ClassVar[int] @@ -24,7 +24,7 @@ class PersonaOverrides(_message.Message): outfit: str def __init__(self, hair_style: _Optional[str] = ..., eye_color: _Optional[str] = ..., outfit: _Optional[str] = ...) -> None: ... -class GenerationResponse(_message.Message): +class GenerateResponse(_message.Message): __slots__ = ("image_url", "metadata") class MetadataEntry(_message.Message): __slots__ = ("key", "value") diff --git a/generated/python/vtuber/v1/persona_pb2.py b/generated/python/vtuber/v1/persona_pb2.py index b2d9a84..7deed43 100644 --- a/generated/python/vtuber/v1/persona_pb2.py +++ b/generated/python/vtuber/v1/persona_pb2.py @@ -24,14 +24,13 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17vtuber/v1/persona.proto\x12\tvtuber.v1\"\xdf\x01\n\x07Persona\x12$\n\x02id\x18\x01 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\x02id\x12!\n\x0c\x64isplay_name\x18\x02 \x01(\tR\x0b\x64isplayName\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12/\n\x13\x61\x63tivation_keywords\x18\x04 \x03(\tR\x12\x61\x63tivationKeywords\x12\x1b\n\tlore_tags\x18\x05 \x03(\tR\x08loreTags\x12\x1b\n\tcolor_hex\x18\x06 \x01(\tR\x08\x63olorHex*\x9b\x01\n\tPersonaId\x12\x1a\n\x16PERSONA_ID_UNSPECIFIED\x10\x00\x12\x15\n\x11PERSONA_ID_VALORA\x10\x01\x12\x15\n\x11PERSONA_ID_AURORA\x10\x02\x12\x15\n\x11PERSONA_ID_AMETRA\x10\x03\x12\x16\n\x12PERSONA_ID_ASTRAEA\x10\x04\x12\x15\n\x11PERSONA_ID_ELDORA\x10\x05\x42\x62\n\rcom.vtuber.v1B\x0cPersonaProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17vtuber/v1/persona.proto\x12\tvtuber.v1\"\xdf\x01\n\x07Persona\x12$\n\x02id\x18\x01 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\x02id\x12!\n\x0c\x64isplay_name\x18\x02 \x01(\tR\x0b\x64isplayName\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12/\n\x13\x61\x63tivation_keywords\x18\x04 \x03(\tR\x12\x61\x63tivationKeywords\x12\x1b\n\tlore_tags\x18\x05 \x03(\tR\x08loreTags\x12\x1b\n\tcolor_hex\x18\x06 \x01(\tR\x08\x63olorHex*\x9b\x01\n\tPersonaId\x12\x1a\n\x16PERSONA_ID_UNSPECIFIED\x10\x00\x12\x15\n\x11PERSONA_ID_VALORA\x10\x01\x12\x15\n\x11PERSONA_ID_AURORA\x10\x02\x12\x15\n\x11PERSONA_ID_AMETRA\x10\x03\x12\x16\n\x12PERSONA_ID_ASTRAEA\x10\x04\x12\x15\n\x11PERSONA_ID_ELDORA\x10\x05\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.persona_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: - _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\014PersonaProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + DESCRIPTOR._loaded_options = None _globals['_PERSONAID']._serialized_start=265 _globals['_PERSONAID']._serialized_end=420 _globals['_PERSONA']._serialized_start=39 diff --git a/generated/python/vtuber/v1/tool_call_pb2.py b/generated/python/vtuber/v1/tool_call_pb2.py index 27eacaa..12b29be 100644 --- a/generated/python/vtuber/v1/tool_call_pb2.py +++ b/generated/python/vtuber/v1/tool_call_pb2.py @@ -25,14 +25,13 @@ from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19vtuber/v1/tool_call.proto\x12\tvtuber.v1\x1a\x1cgoogle/protobuf/struct.proto\"\xea\x01\n\x08ToolCall\x12\x17\n\x07\x63\x61ll_id\x18\x01 \x01(\tR\x06\x63\x61llId\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12\x35\n\targuments\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\targuments\x12=\n\x08metadata\x18\x04 \x03(\x0b\x32!.vtuber.v1.ToolCall.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"{\n\x0cToolResponse\x12\x17\n\x07\x63\x61ll_id\x18\x01 \x01(\tR\x06\x63\x61llId\x12\x18\n\x07\x63ontent\x18\x02 \x01(\tR\x07\x63ontent\x12\x19\n\x08is_error\x18\x03 \x01(\x08R\x07isError\x12\x1d\n\nerror_code\x18\x04 \x01(\tR\terrorCode\"\x7f\n\x0eToolDefinition\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x02 \x01(\tR\x0b\x64\x65scription\x12\x37\n\nparameters\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\nparametersBc\n\rcom.vtuber.v1B\rToolCallProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19vtuber/v1/tool_call.proto\x12\tvtuber.v1\x1a\x1cgoogle/protobuf/struct.proto\"\xea\x01\n\x08ToolCall\x12\x17\n\x07\x63\x61ll_id\x18\x01 \x01(\tR\x06\x63\x61llId\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12\x35\n\targuments\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\targuments\x12=\n\x08metadata\x18\x04 \x03(\x0b\x32!.vtuber.v1.ToolCall.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"{\n\x0cToolResponse\x12\x17\n\x07\x63\x61ll_id\x18\x01 \x01(\tR\x06\x63\x61llId\x12\x18\n\x07\x63ontent\x18\x02 \x01(\tR\x07\x63ontent\x12\x19\n\x08is_error\x18\x03 \x01(\x08R\x07isError\x12\x1d\n\nerror_code\x18\x04 \x01(\tR\terrorCode\"\x7f\n\x0eToolDefinition\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x02 \x01(\tR\x0b\x64\x65scription\x12\x37\n\nparameters\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\nparametersb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.tool_call_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: - _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\rToolCallProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + DESCRIPTOR._loaded_options = None _globals['_TOOLCALL_METADATAENTRY']._loaded_options = None _globals['_TOOLCALL_METADATAENTRY']._serialized_options = b'8\001' _globals['_TOOLCALL']._serialized_start=71 diff --git a/generated/python/vtuber/v1/voice_profile_pb2.py b/generated/python/vtuber/v1/voice_profile_pb2.py index aa71e7d..a79702a 100644 --- a/generated/python/vtuber/v1/voice_profile_pb2.py +++ b/generated/python/vtuber/v1/voice_profile_pb2.py @@ -25,14 +25,13 @@ from vtuber.v1 import persona_pb2 as vtuber_dot_v1_dot_persona__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dvtuber/v1/voice_profile.proto\x12\tvtuber.v1\x1a\x17vtuber/v1/persona.proto\"\xf5\x01\n\x0cVoiceProfile\x12\x33\n\npersona_id\x18\x01 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\tpersonaId\x12\x1d\n\nbase_pitch\x18\x02 \x01(\x02R\tbasePitch\x12#\n\rspeaking_rate\x18\x03 \x01(\x02R\x0cspeakingRate\x12\x16\n\x06\x65nergy\x18\x04 \x01(\x02R\x06\x65nergy\x12\x1b\n\tstyle_tag\x18\x05 \x01(\tR\x08styleTag\x12\x1f\n\x0b\x61\x63\x63\x65nt_hint\x18\x06 \x01(\tR\naccentHint\x12\x16\n\x06quirks\x18\x07 \x03(\tR\x06quirks*n\n\x0b\x41udioFormat\x12\x1c\n\x18\x41UDIO_FORMAT_UNSPECIFIED\x10\x00\x12\x14\n\x10\x41UDIO_FORMAT_WAV\x10\x01\x12\x15\n\x11\x41UDIO_FORMAT_OPUS\x10\x02\x12\x14\n\x10\x41UDIO_FORMAT_MP3\x10\x03*\xb2\x01\n\x07\x45motion\x12\x17\n\x13\x45MOTION_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x45MOTION_NEUTRAL\x10\x01\x12\x11\n\rEMOTION_HAPPY\x10\x02\x12\x0f\n\x0b\x45MOTION_SAD\x10\x03\x12\x11\n\rEMOTION_ANGRY\x10\x04\x12\x13\n\x0f\x45MOTION_PLAYFUL\x10\x05\x12\x16\n\x12\x45MOTION_ANALYTICAL\x10\x06\x12\x15\n\x11\x45MOTION_ASMR_CALM\x10\x07\x42g\n\rcom.vtuber.v1B\x11VoiceProfileProtoP\x01\xa2\x02\x03VXX\xaa\x02\tVtuber.V1\xca\x02\tVtuber\\V1\xe2\x02\x15Vtuber\\V1\\GPBMetadata\xea\x02\nVtuber::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dvtuber/v1/voice_profile.proto\x12\tvtuber.v1\x1a\x17vtuber/v1/persona.proto\"\xf5\x01\n\x0cVoiceProfile\x12\x33\n\npersona_id\x18\x01 \x01(\x0e\x32\x14.vtuber.v1.PersonaIdR\tpersonaId\x12\x1d\n\nbase_pitch\x18\x02 \x01(\x02R\tbasePitch\x12#\n\rspeaking_rate\x18\x03 \x01(\x02R\x0cspeakingRate\x12\x16\n\x06\x65nergy\x18\x04 \x01(\x02R\x06\x65nergy\x12\x1b\n\tstyle_tag\x18\x05 \x01(\tR\x08styleTag\x12\x1f\n\x0b\x61\x63\x63\x65nt_hint\x18\x06 \x01(\tR\naccentHint\x12\x16\n\x06quirks\x18\x07 \x03(\tR\x06quirks*n\n\x0b\x41udioFormat\x12\x1c\n\x18\x41UDIO_FORMAT_UNSPECIFIED\x10\x00\x12\x14\n\x10\x41UDIO_FORMAT_WAV\x10\x01\x12\x15\n\x11\x41UDIO_FORMAT_OPUS\x10\x02\x12\x14\n\x10\x41UDIO_FORMAT_MP3\x10\x03*\xb2\x01\n\x07\x45motion\x12\x17\n\x13\x45MOTION_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x45MOTION_NEUTRAL\x10\x01\x12\x11\n\rEMOTION_HAPPY\x10\x02\x12\x0f\n\x0b\x45MOTION_SAD\x10\x03\x12\x11\n\rEMOTION_ANGRY\x10\x04\x12\x13\n\x0f\x45MOTION_PLAYFUL\x10\x05\x12\x16\n\x12\x45MOTION_ANALYTICAL\x10\x06\x12\x15\n\x11\x45MOTION_ASMR_CALM\x10\x07\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber.v1.voice_profile_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: - _globals['DESCRIPTOR']._loaded_options = None - _globals['DESCRIPTOR']._serialized_options = b'\n\rcom.vtuber.v1B\021VoiceProfileProtoP\001\242\002\003VXX\252\002\tVtuber.V1\312\002\tVtuber\\V1\342\002\025Vtuber\\V1\\GPBMetadata\352\002\nVtuber::V1' + DESCRIPTOR._loaded_options = None _globals['_AUDIOFORMAT']._serialized_start=317 _globals['_AUDIOFORMAT']._serialized_end=427 _globals['_EMOTION']._serialized_start=430 diff --git a/generated/python/vtuber_image/v1/image_pb2.py b/generated/python/vtuber_image/v1/image_pb2.py new file mode 100644 index 0000000..e94b017 --- /dev/null +++ b/generated/python/vtuber_image/v1/image_pb2.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: vtuber_image/v1/image.proto +# Protobuf Python Version: 6.30.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 0, + '', + 'vtuber_image/v1/image.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bvtuber_image/v1/image.proto\x12\x0fvtuber_image.v1\"q\n\x0fGenerateRequest\x12\x1d\n\npersona_id\x18\x01 \x01(\tR\tpersonaId\x12?\n\toverrides\x18\x02 \x01(\x0b\x32!.vtuber_image.v1.PersonaOverridesR\toverrides\"f\n\x10PersonaOverrides\x12\x1d\n\nhair_style\x18\x01 \x01(\tR\thairStyle\x12\x1b\n\teye_color\x18\x02 \x01(\tR\x08\x65yeColor\x12\x16\n\x06outfit\x18\x03 \x01(\tR\x06outfit\"\xb9\x01\n\x10GenerateResponse\x12\x1b\n\timage_url\x18\x01 \x01(\tR\x08imageUrl\x12K\n\x08metadata\x18\x02 \x03(\x0b\x32/.vtuber_image.v1.GenerateResponse.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x32h\n\x15ImageGeneratorService\x12O\n\x08Generate\x12 .vtuber_image.v1.GenerateRequest\x1a!.vtuber_image.v1.GenerateResponseb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber_image.v1.image_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_GENERATERESPONSE_METADATAENTRY']._loaded_options = None + _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_options = b'8\001' + _globals['_GENERATEREQUEST']._serialized_start=48 + _globals['_GENERATEREQUEST']._serialized_end=161 + _globals['_PERSONAOVERRIDES']._serialized_start=163 + _globals['_PERSONAOVERRIDES']._serialized_end=265 + _globals['_GENERATERESPONSE']._serialized_start=268 + _globals['_GENERATERESPONSE']._serialized_end=453 + _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_start=394 + _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_end=453 + _globals['_IMAGEGENERATORSERVICE']._serialized_start=455 + _globals['_IMAGEGENERATORSERVICE']._serialized_end=559 +# @@protoc_insertion_point(module_scope) diff --git a/generated/python/vtuber_image/v1/image_pb2.pyi b/generated/python/vtuber_image/v1/image_pb2.pyi new file mode 100644 index 0000000..0dd8965 --- /dev/null +++ b/generated/python/vtuber_image/v1/image_pb2.pyi @@ -0,0 +1,40 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class GenerateRequest(_message.Message): + __slots__ = ("persona_id", "overrides") + PERSONA_ID_FIELD_NUMBER: _ClassVar[int] + OVERRIDES_FIELD_NUMBER: _ClassVar[int] + persona_id: str + overrides: PersonaOverrides + def __init__(self, persona_id: _Optional[str] = ..., overrides: _Optional[_Union[PersonaOverrides, _Mapping]] = ...) -> None: ... + +class PersonaOverrides(_message.Message): + __slots__ = ("hair_style", "eye_color", "outfit") + HAIR_STYLE_FIELD_NUMBER: _ClassVar[int] + EYE_COLOR_FIELD_NUMBER: _ClassVar[int] + OUTFIT_FIELD_NUMBER: _ClassVar[int] + hair_style: str + eye_color: str + outfit: str + def __init__(self, hair_style: _Optional[str] = ..., eye_color: _Optional[str] = ..., outfit: _Optional[str] = ...) -> None: ... + +class GenerateResponse(_message.Message): + __slots__ = ("image_url", "metadata") + class MetadataEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + IMAGE_URL_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + image_url: str + metadata: _containers.ScalarMap[str, str] + def __init__(self, image_url: _Optional[str] = ..., metadata: _Optional[_Mapping[str, str]] = ...) -> None: ... diff --git a/generated/typescript/vtuber/v1/image.ts b/generated/typescript/vtuber/v1/image.ts index beaf439..854d4dd 100644 --- a/generated/typescript/vtuber/v1/image.ts +++ b/generated/typescript/vtuber/v1/image.ts @@ -9,7 +9,7 @@ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; export const protobufPackage = "vtuber.v1"; -export interface GenerationRequest { +export interface GenerateRequest { /** UUID or stable ID for the persona. */ personaId: string; /** Visual overrides for this specific generation. */ @@ -22,24 +22,24 @@ export interface PersonaOverrides { outfit: string; } -export interface GenerationResponse { +export interface GenerateResponse { /** URL or path to the generated image. */ imageUrl: string; /** Key-value pairs for provenance and workflow metadata. */ metadata: { [key: string]: string }; } -export interface GenerationResponse_MetadataEntry { +export interface GenerateResponse_MetadataEntry { key: string; value: string; } -function createBaseGenerationRequest(): GenerationRequest { +function createBaseGenerateRequest(): GenerateRequest { return { personaId: "", overrides: undefined }; } -export const GenerationRequest: MessageFns = { - encode(message: GenerationRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { +export const GenerateRequest: MessageFns = { + encode(message: GenerateRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.personaId !== "") { writer.uint32(10).string(message.personaId); } @@ -49,10 +49,10 @@ export const GenerationRequest: MessageFns = { return writer; }, - decode(input: BinaryReader | Uint8Array, length?: number): GenerationRequest { + decode(input: BinaryReader | Uint8Array, length?: number): GenerateRequest { const reader = input instanceof BinaryReader ? input : new BinaryReader(input); const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGenerationRequest(); + const message = createBaseGenerateRequest(); while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { @@ -81,7 +81,7 @@ export const GenerationRequest: MessageFns = { return message; }, - fromJSON(object: any): GenerationRequest { + fromJSON(object: any): GenerateRequest { return { personaId: isSet(object.personaId) ? globalThis.String(object.personaId) @@ -92,7 +92,7 @@ export const GenerationRequest: MessageFns = { }; }, - toJSON(message: GenerationRequest): unknown { + toJSON(message: GenerateRequest): unknown { const obj: any = {}; if (message.personaId !== "") { obj.personaId = message.personaId; @@ -103,11 +103,11 @@ export const GenerationRequest: MessageFns = { return obj; }, - create, I>>(base?: I): GenerationRequest { - return GenerationRequest.fromPartial(base ?? ({} as any)); + create, I>>(base?: I): GenerateRequest { + return GenerateRequest.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): GenerationRequest { - const message = createBaseGenerationRequest(); + fromPartial, I>>(object: I): GenerateRequest { + const message = createBaseGenerateRequest(); message.personaId = object.personaId ?? ""; message.overrides = (object.overrides !== undefined && object.overrides !== null) ? PersonaOverrides.fromPartial(object.overrides) @@ -216,25 +216,25 @@ export const PersonaOverrides: MessageFns = { }, }; -function createBaseGenerationResponse(): GenerationResponse { +function createBaseGenerateResponse(): GenerateResponse { return { imageUrl: "", metadata: {} }; } -export const GenerationResponse: MessageFns = { - encode(message: GenerationResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { +export const GenerateResponse: MessageFns = { + encode(message: GenerateResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.imageUrl !== "") { writer.uint32(10).string(message.imageUrl); } globalThis.Object.entries(message.metadata).forEach(([key, value]: [string, string]) => { - GenerationResponse_MetadataEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join(); + GenerateResponse_MetadataEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join(); }); return writer; }, - decode(input: BinaryReader | Uint8Array, length?: number): GenerationResponse { + decode(input: BinaryReader | Uint8Array, length?: number): GenerateResponse { const reader = input instanceof BinaryReader ? input : new BinaryReader(input); const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGenerationResponse(); + const message = createBaseGenerateResponse(); while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { @@ -251,7 +251,7 @@ export const GenerationResponse: MessageFns = { break; } - const entry2 = GenerationResponse_MetadataEntry.decode(reader, reader.uint32()); + const entry2 = GenerateResponse_MetadataEntry.decode(reader, reader.uint32()); if (entry2.value !== undefined) { message.metadata[entry2.key] = entry2.value; } @@ -266,7 +266,7 @@ export const GenerationResponse: MessageFns = { return message; }, - fromJSON(object: any): GenerationResponse { + fromJSON(object: any): GenerateResponse { return { imageUrl: isSet(object.imageUrl) ? globalThis.String(object.imageUrl) @@ -285,7 +285,7 @@ export const GenerationResponse: MessageFns = { }; }, - toJSON(message: GenerationResponse): unknown { + toJSON(message: GenerateResponse): unknown { const obj: any = {}; if (message.imageUrl !== "") { obj.imageUrl = message.imageUrl; @@ -302,11 +302,11 @@ export const GenerationResponse: MessageFns = { return obj; }, - create, I>>(base?: I): GenerationResponse { - return GenerationResponse.fromPartial(base ?? ({} as any)); + create, I>>(base?: I): GenerateResponse { + return GenerateResponse.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): GenerationResponse { - const message = createBaseGenerationResponse(); + fromPartial, I>>(object: I): GenerateResponse { + const message = createBaseGenerateResponse(); message.imageUrl = object.imageUrl ?? ""; message.metadata = (globalThis.Object.entries(object.metadata ?? {}) as [string, string][]).reduce( (acc: { [key: string]: string }, [key, value]: [string, string]) => { @@ -321,12 +321,12 @@ export const GenerationResponse: MessageFns = { }, }; -function createBaseGenerationResponse_MetadataEntry(): GenerationResponse_MetadataEntry { +function createBaseGenerateResponse_MetadataEntry(): GenerateResponse_MetadataEntry { return { key: "", value: "" }; } -export const GenerationResponse_MetadataEntry: MessageFns = { - encode(message: GenerationResponse_MetadataEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { +export const GenerateResponse_MetadataEntry: MessageFns = { + encode(message: GenerateResponse_MetadataEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); } @@ -336,10 +336,10 @@ export const GenerationResponse_MetadataEntry: MessageFns>> 3) { @@ -368,14 +368,14 @@ export const GenerationResponse_MetadataEntry: MessageFns, I>>( - base?: I, - ): GenerationResponse_MetadataEntry { - return GenerationResponse_MetadataEntry.fromPartial(base ?? ({} as any)); + create, I>>(base?: I): GenerateResponse_MetadataEntry { + return GenerateResponse_MetadataEntry.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>( + fromPartial, I>>( object: I, - ): GenerationResponse_MetadataEntry { - const message = createBaseGenerationResponse_MetadataEntry(); + ): GenerateResponse_MetadataEntry { + const message = createBaseGenerateResponse_MetadataEntry(); message.key = object.key ?? ""; message.value = object.value ?? ""; return message; @@ -402,19 +400,19 @@ export const GenerationResponse_MetadataEntry: MessageFns = { + encode(message: GenerateRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.personaId !== "") { + writer.uint32(10).string(message.personaId); + } + if (message.overrides !== undefined) { + PersonaOverrides.encode(message.overrides, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GenerateRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGenerateRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.personaId = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.overrides = PersonaOverrides.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GenerateRequest { + return { + personaId: isSet(object.personaId) + ? globalThis.String(object.personaId) + : isSet(object.persona_id) + ? globalThis.String(object.persona_id) + : "", + overrides: isSet(object.overrides) ? PersonaOverrides.fromJSON(object.overrides) : undefined, + }; + }, + + toJSON(message: GenerateRequest): unknown { + const obj: any = {}; + if (message.personaId !== "") { + obj.personaId = message.personaId; + } + if (message.overrides !== undefined) { + obj.overrides = PersonaOverrides.toJSON(message.overrides); + } + return obj; + }, + + create, I>>(base?: I): GenerateRequest { + return GenerateRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): GenerateRequest { + const message = createBaseGenerateRequest(); + message.personaId = object.personaId ?? ""; + message.overrides = (object.overrides !== undefined && object.overrides !== null) + ? PersonaOverrides.fromPartial(object.overrides) + : undefined; + return message; + }, +}; + +function createBasePersonaOverrides(): PersonaOverrides { + return { hairStyle: "", eyeColor: "", outfit: "" }; +} + +export const PersonaOverrides: MessageFns = { + encode(message: PersonaOverrides, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.hairStyle !== "") { + writer.uint32(10).string(message.hairStyle); + } + if (message.eyeColor !== "") { + writer.uint32(18).string(message.eyeColor); + } + if (message.outfit !== "") { + writer.uint32(26).string(message.outfit); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): PersonaOverrides { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePersonaOverrides(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.hairStyle = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.eyeColor = reader.string(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.outfit = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): PersonaOverrides { + return { + hairStyle: isSet(object.hairStyle) + ? globalThis.String(object.hairStyle) + : isSet(object.hair_style) + ? globalThis.String(object.hair_style) + : "", + eyeColor: isSet(object.eyeColor) + ? globalThis.String(object.eyeColor) + : isSet(object.eye_color) + ? globalThis.String(object.eye_color) + : "", + outfit: isSet(object.outfit) ? globalThis.String(object.outfit) : "", + }; + }, + + toJSON(message: PersonaOverrides): unknown { + const obj: any = {}; + if (message.hairStyle !== "") { + obj.hairStyle = message.hairStyle; + } + if (message.eyeColor !== "") { + obj.eyeColor = message.eyeColor; + } + if (message.outfit !== "") { + obj.outfit = message.outfit; + } + return obj; + }, + + create, I>>(base?: I): PersonaOverrides { + return PersonaOverrides.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): PersonaOverrides { + const message = createBasePersonaOverrides(); + message.hairStyle = object.hairStyle ?? ""; + message.eyeColor = object.eyeColor ?? ""; + message.outfit = object.outfit ?? ""; + return message; + }, +}; + +function createBaseGenerateResponse(): GenerateResponse { + return { imageUrl: "", metadata: {} }; +} + +export const GenerateResponse: MessageFns = { + encode(message: GenerateResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.imageUrl !== "") { + writer.uint32(10).string(message.imageUrl); + } + globalThis.Object.entries(message.metadata).forEach(([key, value]: [string, string]) => { + GenerateResponse_MetadataEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join(); + }); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GenerateResponse { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGenerateResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.imageUrl = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + const entry2 = GenerateResponse_MetadataEntry.decode(reader, reader.uint32()); + if (entry2.value !== undefined) { + message.metadata[entry2.key] = entry2.value; + } + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GenerateResponse { + return { + imageUrl: isSet(object.imageUrl) + ? globalThis.String(object.imageUrl) + : isSet(object.image_url) + ? globalThis.String(object.image_url) + : "", + metadata: isObject(object.metadata) + ? (globalThis.Object.entries(object.metadata) as [string, any][]).reduce( + (acc: { [key: string]: string }, [key, value]: [string, any]) => { + acc[key] = globalThis.String(value); + return acc; + }, + {}, + ) + : {}, + }; + }, + + toJSON(message: GenerateResponse): unknown { + const obj: any = {}; + if (message.imageUrl !== "") { + obj.imageUrl = message.imageUrl; + } + if (message.metadata) { + const entries = globalThis.Object.entries(message.metadata) as [string, string][]; + if (entries.length > 0) { + obj.metadata = {}; + entries.forEach(([k, v]) => { + obj.metadata[k] = v; + }); + } + } + return obj; + }, + + create, I>>(base?: I): GenerateResponse { + return GenerateResponse.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): GenerateResponse { + const message = createBaseGenerateResponse(); + message.imageUrl = object.imageUrl ?? ""; + message.metadata = (globalThis.Object.entries(object.metadata ?? {}) as [string, string][]).reduce( + (acc: { [key: string]: string }, [key, value]: [string, string]) => { + if (value !== undefined) { + acc[key] = globalThis.String(value); + } + return acc; + }, + {}, + ); + return message; + }, +}; + +function createBaseGenerateResponse_MetadataEntry(): GenerateResponse_MetadataEntry { + return { key: "", value: "" }; +} + +export const GenerateResponse_MetadataEntry: MessageFns = { + encode(message: GenerateResponse_MetadataEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== "") { + writer.uint32(10).string(message.key); + } + if (message.value !== "") { + writer.uint32(18).string(message.value); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GenerateResponse_MetadataEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGenerateResponse_MetadataEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.key = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.value = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GenerateResponse_MetadataEntry { + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + value: isSet(object.value) ? globalThis.String(object.value) : "", + }; + }, + + toJSON(message: GenerateResponse_MetadataEntry): unknown { + const obj: any = {}; + if (message.key !== "") { + obj.key = message.key; + } + if (message.value !== "") { + obj.value = message.value; + } + return obj; + }, + + create, I>>(base?: I): GenerateResponse_MetadataEntry { + return GenerateResponse_MetadataEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): GenerateResponse_MetadataEntry { + const message = createBaseGenerateResponse_MetadataEntry(); + message.key = object.key ?? ""; + message.value = object.value ?? ""; + return message; + }, +}; + +/** + * ImageGeneratorService defines how vtuber-brain or vtuber-api requests + * images from vtuber-image. + */ +export type ImageGeneratorServiceDefinition = typeof ImageGeneratorServiceDefinition; +export const ImageGeneratorServiceDefinition = { + name: "ImageGeneratorService", + fullName: "vtuber_image.v1.ImageGeneratorService", + methods: { + generate: { + name: "Generate", + requestType: GenerateRequest as typeof GenerateRequest, + requestStream: false, + responseType: GenerateResponse as typeof GenerateResponse, + responseStream: false, + options: {}, + }, + }, +} as const; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/proto/vtuber/v1/image.proto b/proto/vtuber_image/v1/image.proto similarity index 65% rename from proto/vtuber/v1/image.proto rename to proto/vtuber_image/v1/image.proto index cfe5528..136ef87 100644 --- a/proto/vtuber/v1/image.proto +++ b/proto/vtuber_image/v1/image.proto @@ -1,14 +1,14 @@ syntax = "proto3"; -package vtuber.v1; +package vtuber_image.v1; -// ImageGenerator service defines how vtuber-brain or vtuber-api requests +// ImageGeneratorService defines how vtuber-brain or vtuber-api requests // images from vtuber-image. -service ImageGenerator { - rpc Generate(GenerationRequest) returns (GenerationResponse); +service ImageGeneratorService { + rpc Generate(GenerateRequest) returns (GenerateResponse); } -message GenerationRequest { +message GenerateRequest { // UUID or stable ID for the persona. string persona_id = 1; // Visual overrides for this specific generation. @@ -21,9 +21,10 @@ message PersonaOverrides { string outfit = 3; } -message GenerationResponse { +message GenerateResponse { // URL or path to the generated image. string image_url = 1; // Key-value pairs for provenance and workflow metadata. map metadata = 2; } + From b58d810598947c1ae712d7d8481d0386b2e474e9 Mon Sep 17 00:00:00 2001 From: MrBT-nano Date: Wed, 6 May 2026 17:11:05 +0700 Subject: [PATCH 12/12] chore: align with Distributed Model (Issue #5), fix Mojo crash, and sync CI versions --- build.rs | 1 - generated/python/vtuber_image/v1/image_pb2.py | 46 -- .../python/vtuber_image/v1/image_pb2.pyi | 40 -- generated/typescript/vtuber_image/v1/image.ts | 449 ------------------ mojo/tests/test_roundtrip.mojo | 10 +- proto/vtuber_image/v1/image.proto | 30 -- 6 files changed, 8 insertions(+), 568 deletions(-) delete mode 100644 generated/python/vtuber_image/v1/image_pb2.py delete mode 100644 generated/python/vtuber_image/v1/image_pb2.pyi delete mode 100644 generated/typescript/vtuber_image/v1/image.ts delete mode 100644 proto/vtuber_image/v1/image.proto diff --git a/build.rs b/build.rs index e7d00bc..2fb8800 100644 --- a/build.rs +++ b/build.rs @@ -4,7 +4,6 @@ fn main() -> Result<(), Box> { "proto/vtuber/v1/voice_profile.proto", "proto/vtuber/v1/conversation.proto", "proto/vtuber/v1/tool_call.proto", - "proto/vtuber_image/v1/image.proto", ]; for p in protos { diff --git a/generated/python/vtuber_image/v1/image_pb2.py b/generated/python/vtuber_image/v1/image_pb2.py deleted file mode 100644 index e94b017..0000000 --- a/generated/python/vtuber_image/v1/image_pb2.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: vtuber_image/v1/image.proto -# Protobuf Python Version: 6.30.0 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 6, - 30, - 0, - '', - 'vtuber_image/v1/image.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bvtuber_image/v1/image.proto\x12\x0fvtuber_image.v1\"q\n\x0fGenerateRequest\x12\x1d\n\npersona_id\x18\x01 \x01(\tR\tpersonaId\x12?\n\toverrides\x18\x02 \x01(\x0b\x32!.vtuber_image.v1.PersonaOverridesR\toverrides\"f\n\x10PersonaOverrides\x12\x1d\n\nhair_style\x18\x01 \x01(\tR\thairStyle\x12\x1b\n\teye_color\x18\x02 \x01(\tR\x08\x65yeColor\x12\x16\n\x06outfit\x18\x03 \x01(\tR\x06outfit\"\xb9\x01\n\x10GenerateResponse\x12\x1b\n\timage_url\x18\x01 \x01(\tR\x08imageUrl\x12K\n\x08metadata\x18\x02 \x03(\x0b\x32/.vtuber_image.v1.GenerateResponse.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x32h\n\x15ImageGeneratorService\x12O\n\x08Generate\x12 .vtuber_image.v1.GenerateRequest\x1a!.vtuber_image.v1.GenerateResponseb\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vtuber_image.v1.image_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_GENERATERESPONSE_METADATAENTRY']._loaded_options = None - _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_options = b'8\001' - _globals['_GENERATEREQUEST']._serialized_start=48 - _globals['_GENERATEREQUEST']._serialized_end=161 - _globals['_PERSONAOVERRIDES']._serialized_start=163 - _globals['_PERSONAOVERRIDES']._serialized_end=265 - _globals['_GENERATERESPONSE']._serialized_start=268 - _globals['_GENERATERESPONSE']._serialized_end=453 - _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_start=394 - _globals['_GENERATERESPONSE_METADATAENTRY']._serialized_end=453 - _globals['_IMAGEGENERATORSERVICE']._serialized_start=455 - _globals['_IMAGEGENERATORSERVICE']._serialized_end=559 -# @@protoc_insertion_point(module_scope) diff --git a/generated/python/vtuber_image/v1/image_pb2.pyi b/generated/python/vtuber_image/v1/image_pb2.pyi deleted file mode 100644 index 0dd8965..0000000 --- a/generated/python/vtuber_image/v1/image_pb2.pyi +++ /dev/null @@ -1,40 +0,0 @@ -from google.protobuf.internal import containers as _containers -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from collections.abc import Mapping as _Mapping -from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class GenerateRequest(_message.Message): - __slots__ = ("persona_id", "overrides") - PERSONA_ID_FIELD_NUMBER: _ClassVar[int] - OVERRIDES_FIELD_NUMBER: _ClassVar[int] - persona_id: str - overrides: PersonaOverrides - def __init__(self, persona_id: _Optional[str] = ..., overrides: _Optional[_Union[PersonaOverrides, _Mapping]] = ...) -> None: ... - -class PersonaOverrides(_message.Message): - __slots__ = ("hair_style", "eye_color", "outfit") - HAIR_STYLE_FIELD_NUMBER: _ClassVar[int] - EYE_COLOR_FIELD_NUMBER: _ClassVar[int] - OUTFIT_FIELD_NUMBER: _ClassVar[int] - hair_style: str - eye_color: str - outfit: str - def __init__(self, hair_style: _Optional[str] = ..., eye_color: _Optional[str] = ..., outfit: _Optional[str] = ...) -> None: ... - -class GenerateResponse(_message.Message): - __slots__ = ("image_url", "metadata") - class MetadataEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... - IMAGE_URL_FIELD_NUMBER: _ClassVar[int] - METADATA_FIELD_NUMBER: _ClassVar[int] - image_url: str - metadata: _containers.ScalarMap[str, str] - def __init__(self, image_url: _Optional[str] = ..., metadata: _Optional[_Mapping[str, str]] = ...) -> None: ... diff --git a/generated/typescript/vtuber_image/v1/image.ts b/generated/typescript/vtuber_image/v1/image.ts deleted file mode 100644 index b915047..0000000 --- a/generated/typescript/vtuber_image/v1/image.ts +++ /dev/null @@ -1,449 +0,0 @@ -// Code generated by protoc-gen-ts_proto. DO NOT EDIT. -// versions: -// protoc-gen-ts_proto v2.11.6 -// protoc unknown -// source: vtuber_image/v1/image.proto - -/* eslint-disable */ -import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; - -export const protobufPackage = "vtuber_image.v1"; - -export interface GenerateRequest { - /** UUID or stable ID for the persona. */ - personaId: string; - /** Visual overrides for this specific generation. */ - overrides: PersonaOverrides | undefined; -} - -export interface PersonaOverrides { - hairStyle: string; - eyeColor: string; - outfit: string; -} - -export interface GenerateResponse { - /** URL or path to the generated image. */ - imageUrl: string; - /** Key-value pairs for provenance and workflow metadata. */ - metadata: { [key: string]: string }; -} - -export interface GenerateResponse_MetadataEntry { - key: string; - value: string; -} - -function createBaseGenerateRequest(): GenerateRequest { - return { personaId: "", overrides: undefined }; -} - -export const GenerateRequest: MessageFns = { - encode(message: GenerateRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.personaId !== "") { - writer.uint32(10).string(message.personaId); - } - if (message.overrides !== undefined) { - PersonaOverrides.encode(message.overrides, writer.uint32(18).fork()).join(); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): GenerateRequest { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGenerateRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.personaId = reader.string(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.overrides = PersonaOverrides.decode(reader, reader.uint32()); - continue; - } - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skip(tag & 7); - } - return message; - }, - - fromJSON(object: any): GenerateRequest { - return { - personaId: isSet(object.personaId) - ? globalThis.String(object.personaId) - : isSet(object.persona_id) - ? globalThis.String(object.persona_id) - : "", - overrides: isSet(object.overrides) ? PersonaOverrides.fromJSON(object.overrides) : undefined, - }; - }, - - toJSON(message: GenerateRequest): unknown { - const obj: any = {}; - if (message.personaId !== "") { - obj.personaId = message.personaId; - } - if (message.overrides !== undefined) { - obj.overrides = PersonaOverrides.toJSON(message.overrides); - } - return obj; - }, - - create, I>>(base?: I): GenerateRequest { - return GenerateRequest.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>(object: I): GenerateRequest { - const message = createBaseGenerateRequest(); - message.personaId = object.personaId ?? ""; - message.overrides = (object.overrides !== undefined && object.overrides !== null) - ? PersonaOverrides.fromPartial(object.overrides) - : undefined; - return message; - }, -}; - -function createBasePersonaOverrides(): PersonaOverrides { - return { hairStyle: "", eyeColor: "", outfit: "" }; -} - -export const PersonaOverrides: MessageFns = { - encode(message: PersonaOverrides, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.hairStyle !== "") { - writer.uint32(10).string(message.hairStyle); - } - if (message.eyeColor !== "") { - writer.uint32(18).string(message.eyeColor); - } - if (message.outfit !== "") { - writer.uint32(26).string(message.outfit); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): PersonaOverrides { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBasePersonaOverrides(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.hairStyle = reader.string(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.eyeColor = reader.string(); - continue; - } - case 3: { - if (tag !== 26) { - break; - } - - message.outfit = reader.string(); - continue; - } - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skip(tag & 7); - } - return message; - }, - - fromJSON(object: any): PersonaOverrides { - return { - hairStyle: isSet(object.hairStyle) - ? globalThis.String(object.hairStyle) - : isSet(object.hair_style) - ? globalThis.String(object.hair_style) - : "", - eyeColor: isSet(object.eyeColor) - ? globalThis.String(object.eyeColor) - : isSet(object.eye_color) - ? globalThis.String(object.eye_color) - : "", - outfit: isSet(object.outfit) ? globalThis.String(object.outfit) : "", - }; - }, - - toJSON(message: PersonaOverrides): unknown { - const obj: any = {}; - if (message.hairStyle !== "") { - obj.hairStyle = message.hairStyle; - } - if (message.eyeColor !== "") { - obj.eyeColor = message.eyeColor; - } - if (message.outfit !== "") { - obj.outfit = message.outfit; - } - return obj; - }, - - create, I>>(base?: I): PersonaOverrides { - return PersonaOverrides.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>(object: I): PersonaOverrides { - const message = createBasePersonaOverrides(); - message.hairStyle = object.hairStyle ?? ""; - message.eyeColor = object.eyeColor ?? ""; - message.outfit = object.outfit ?? ""; - return message; - }, -}; - -function createBaseGenerateResponse(): GenerateResponse { - return { imageUrl: "", metadata: {} }; -} - -export const GenerateResponse: MessageFns = { - encode(message: GenerateResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.imageUrl !== "") { - writer.uint32(10).string(message.imageUrl); - } - globalThis.Object.entries(message.metadata).forEach(([key, value]: [string, string]) => { - GenerateResponse_MetadataEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join(); - }); - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): GenerateResponse { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGenerateResponse(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.imageUrl = reader.string(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - const entry2 = GenerateResponse_MetadataEntry.decode(reader, reader.uint32()); - if (entry2.value !== undefined) { - message.metadata[entry2.key] = entry2.value; - } - continue; - } - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skip(tag & 7); - } - return message; - }, - - fromJSON(object: any): GenerateResponse { - return { - imageUrl: isSet(object.imageUrl) - ? globalThis.String(object.imageUrl) - : isSet(object.image_url) - ? globalThis.String(object.image_url) - : "", - metadata: isObject(object.metadata) - ? (globalThis.Object.entries(object.metadata) as [string, any][]).reduce( - (acc: { [key: string]: string }, [key, value]: [string, any]) => { - acc[key] = globalThis.String(value); - return acc; - }, - {}, - ) - : {}, - }; - }, - - toJSON(message: GenerateResponse): unknown { - const obj: any = {}; - if (message.imageUrl !== "") { - obj.imageUrl = message.imageUrl; - } - if (message.metadata) { - const entries = globalThis.Object.entries(message.metadata) as [string, string][]; - if (entries.length > 0) { - obj.metadata = {}; - entries.forEach(([k, v]) => { - obj.metadata[k] = v; - }); - } - } - return obj; - }, - - create, I>>(base?: I): GenerateResponse { - return GenerateResponse.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>(object: I): GenerateResponse { - const message = createBaseGenerateResponse(); - message.imageUrl = object.imageUrl ?? ""; - message.metadata = (globalThis.Object.entries(object.metadata ?? {}) as [string, string][]).reduce( - (acc: { [key: string]: string }, [key, value]: [string, string]) => { - if (value !== undefined) { - acc[key] = globalThis.String(value); - } - return acc; - }, - {}, - ); - return message; - }, -}; - -function createBaseGenerateResponse_MetadataEntry(): GenerateResponse_MetadataEntry { - return { key: "", value: "" }; -} - -export const GenerateResponse_MetadataEntry: MessageFns = { - encode(message: GenerateResponse_MetadataEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.key !== "") { - writer.uint32(10).string(message.key); - } - if (message.value !== "") { - writer.uint32(18).string(message.value); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): GenerateResponse_MetadataEntry { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGenerateResponse_MetadataEntry(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.key = reader.string(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.value = reader.string(); - continue; - } - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skip(tag & 7); - } - return message; - }, - - fromJSON(object: any): GenerateResponse_MetadataEntry { - return { - key: isSet(object.key) ? globalThis.String(object.key) : "", - value: isSet(object.value) ? globalThis.String(object.value) : "", - }; - }, - - toJSON(message: GenerateResponse_MetadataEntry): unknown { - const obj: any = {}; - if (message.key !== "") { - obj.key = message.key; - } - if (message.value !== "") { - obj.value = message.value; - } - return obj; - }, - - create, I>>(base?: I): GenerateResponse_MetadataEntry { - return GenerateResponse_MetadataEntry.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>( - object: I, - ): GenerateResponse_MetadataEntry { - const message = createBaseGenerateResponse_MetadataEntry(); - message.key = object.key ?? ""; - message.value = object.value ?? ""; - return message; - }, -}; - -/** - * ImageGeneratorService defines how vtuber-brain or vtuber-api requests - * images from vtuber-image. - */ -export type ImageGeneratorServiceDefinition = typeof ImageGeneratorServiceDefinition; -export const ImageGeneratorServiceDefinition = { - name: "ImageGeneratorService", - fullName: "vtuber_image.v1.ImageGeneratorService", - methods: { - generate: { - name: "Generate", - requestType: GenerateRequest as typeof GenerateRequest, - requestStream: false, - responseType: GenerateResponse as typeof GenerateResponse, - responseStream: false, - options: {}, - }, - }, -} as const; - -type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; - -export type DeepPartial = T extends Builtin ? T - : T extends globalThis.Array ? globalThis.Array> - : T extends ReadonlyArray ? ReadonlyArray> - : T extends {} ? { [K in keyof T]?: DeepPartial } - : Partial; - -type KeysOfUnion = T extends T ? keyof T : never; -export type Exact = P extends Builtin ? P - : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; - -function isObject(value: any): boolean { - return typeof value === "object" && value !== null; -} - -function isSet(value: any): boolean { - return value !== null && value !== undefined; -} - -export interface MessageFns { - encode(message: T, writer?: BinaryWriter): BinaryWriter; - decode(input: BinaryReader | Uint8Array, length?: number): T; - fromJSON(object: any): T; - toJSON(message: T): unknown; - create, I>>(base?: I): T; - fromPartial, I>>(object: I): T; -} diff --git a/mojo/tests/test_roundtrip.mojo b/mojo/tests/test_roundtrip.mojo index 70afde5..1f69800 100644 --- a/mojo/tests/test_roundtrip.mojo +++ b/mojo/tests/test_roundtrip.mojo @@ -26,17 +26,23 @@ def test_persona_roundtrip() raises: def test_conversation_directive_roundtrip() raises: var ametra_id = 3 # PersonaId.PERSONA_ID_AMETRA + # Using full arguments to avoid Mojo 24.x interop issues with defaults var original = ConversationDirective.new( "018f4e2b-4a8c-7b1f-9c5e-2d3a4b5c6d7e", ametra_id, - "Let me analyze that for a moment...", + "สวัสดี ยินดีที่ได้รู้จัก!", # Thai Unicode verification + "", # voice_prompt + 1, # emotion neutral + 1, # audio format wav + 500, # latency ) var bytes = original.serialize() var decoded = ConversationDirective.parse(bytes) assert_equal( decoded.text_prompt(), - "Let me analyze that for a moment...", + "สวัสดี ยินดีที่ได้รู้จัก!", ) + assert_equal(String(decoded.max_latency_ms()), "500") def main() raises: diff --git a/proto/vtuber_image/v1/image.proto b/proto/vtuber_image/v1/image.proto deleted file mode 100644 index 136ef87..0000000 --- a/proto/vtuber_image/v1/image.proto +++ /dev/null @@ -1,30 +0,0 @@ -syntax = "proto3"; - -package vtuber_image.v1; - -// ImageGeneratorService defines how vtuber-brain or vtuber-api requests -// images from vtuber-image. -service ImageGeneratorService { - rpc Generate(GenerateRequest) returns (GenerateResponse); -} - -message GenerateRequest { - // UUID or stable ID for the persona. - string persona_id = 1; - // Visual overrides for this specific generation. - PersonaOverrides overrides = 2; -} - -message PersonaOverrides { - string hair_style = 1; - string eye_color = 2; - string outfit = 3; -} - -message GenerateResponse { - // URL or path to the generated image. - string image_url = 1; - // Key-value pairs for provenance and workflow metadata. - map metadata = 2; -} -