mirror of
https://github.com/openai/codex.git
synced 2026-09-17 12:23:33 +00:00
Merge da6086f865 into sapling-pr-archive-bolinfest
This commit is contained in:
3
.github/workflows/rust-release.yml
vendored
3
.github/workflows/rust-release.yml
vendored
@@ -211,7 +211,8 @@ jobs:
|
||||
files: dist/**
|
||||
# Mark as prerelease only when the version has a suffix after x.y.z
|
||||
# (e.g. -alpha, -beta). Otherwise publish a normal release.
|
||||
prerelease: ${{ contains(steps.release_name.outputs.name, '-') }}
|
||||
# prerelease: ${{ contains(steps.release_name.outputs.name, '-') }}
|
||||
prerelease: true
|
||||
|
||||
- uses: facebook/dotslash-publish-release@v2
|
||||
env:
|
||||
|
||||
58
codex-rs/Cargo.lock
generated
58
codex-rs/Cargo.lock
generated
@@ -407,7 +407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata 0.4.9",
|
||||
"regex-automata",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@@ -625,6 +625,7 @@ name = "codex-cli"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"codex-arg0",
|
||||
@@ -637,7 +638,10 @@ dependencies = [
|
||||
"codex-protocol",
|
||||
"codex-protocol-ts",
|
||||
"codex-tui",
|
||||
"predicates",
|
||||
"pretty_assertions",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
@@ -917,6 +921,7 @@ dependencies = [
|
||||
"color-eyre",
|
||||
"crossterm",
|
||||
"diffy",
|
||||
"dirs",
|
||||
"image",
|
||||
"insta",
|
||||
"itertools 0.14.0",
|
||||
@@ -1323,7 +1328,7 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b545b8c50194bdd008283985ab0b31dba153cfd5b3066a92770634fbc0d7d291"
|
||||
dependencies = [
|
||||
"nu-ansi-term 0.50.1",
|
||||
"nu-ansi-term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1905,7 +1910,7 @@ dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr",
|
||||
"log",
|
||||
"regex-automata 0.4.9",
|
||||
"regex-automata",
|
||||
"regex-syntax 0.8.5",
|
||||
]
|
||||
|
||||
@@ -2320,7 +2325,7 @@ dependencies = [
|
||||
"globset",
|
||||
"log",
|
||||
"memchr",
|
||||
"regex-automata 0.4.9",
|
||||
"regex-automata",
|
||||
"same-file",
|
||||
"walkdir",
|
||||
"winapi-util",
|
||||
@@ -2705,11 +2710,11 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
|
||||
dependencies = [
|
||||
"regex-automata 0.1.10",
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2883,16 +2888,6 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
dependencies = [
|
||||
"overload",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.1"
|
||||
@@ -3131,12 +3126,6 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "4.2.2"
|
||||
@@ -3599,19 +3588,10 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata 0.4.9",
|
||||
"regex-automata",
|
||||
"regex-syntax 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||
dependencies = [
|
||||
"regex-syntax 0.6.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
@@ -4172,9 +4152,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
@@ -4906,14 +4886,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.19"
|
||||
version = "0.3.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term 0.46.0",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"regex-automata",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
|
||||
@@ -36,5 +36,11 @@ tokio = { version = "1", features = [
|
||||
"signal",
|
||||
] }
|
||||
tracing = "0.1.41"
|
||||
tracing-subscriber = "0.3.19"
|
||||
tracing-subscriber = "0.3.20"
|
||||
codex-protocol-ts = { path = "../protocol-ts" }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2"
|
||||
predicates = "3"
|
||||
pretty_assertions = "1"
|
||||
tempfile = "3"
|
||||
|
||||
@@ -17,6 +17,9 @@ use codex_exec::Cli as ExecCli;
|
||||
use codex_tui::Cli as TuiCli;
|
||||
use std::path::PathBuf;
|
||||
|
||||
mod mcp_cmd;
|
||||
|
||||
use crate::mcp_cmd::McpCli;
|
||||
use crate::proto::ProtoCli;
|
||||
|
||||
/// Codex CLI
|
||||
@@ -56,8 +59,8 @@ enum Subcommand {
|
||||
/// Remove stored authentication credentials.
|
||||
Logout(LogoutCommand),
|
||||
|
||||
/// Experimental: run Codex as an MCP server.
|
||||
Mcp,
|
||||
/// [experimental] Run Codex as an MCP server and manage MCP servers.
|
||||
Mcp(McpCli),
|
||||
|
||||
/// Run the Protocol stream via stdin/stdout
|
||||
#[clap(visible_alias = "p")]
|
||||
@@ -98,6 +101,9 @@ struct ResumeCommand {
|
||||
/// Continue the most recent session without showing the picker.
|
||||
#[arg(long = "last", default_value_t = false, conflicts_with = "session_id")]
|
||||
last: bool,
|
||||
|
||||
#[clap(flatten)]
|
||||
config_overrides: TuiCli,
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
@@ -182,22 +188,22 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
);
|
||||
codex_exec::run_main(exec_cli, codex_linux_sandbox_exe).await?;
|
||||
}
|
||||
Some(Subcommand::Mcp) => {
|
||||
codex_mcp_server::run_main(codex_linux_sandbox_exe, root_config_overrides.clone())
|
||||
.await?;
|
||||
}
|
||||
Some(Subcommand::Resume(ResumeCommand { session_id, last })) => {
|
||||
// Start with the parsed interactive CLI so resume shares the same
|
||||
// configuration surface area as `codex` without additional flags.
|
||||
let resume_session_id = session_id;
|
||||
interactive.resume_picker = resume_session_id.is_none() && !last;
|
||||
interactive.resume_last = last;
|
||||
interactive.resume_session_id = resume_session_id;
|
||||
|
||||
Some(Subcommand::Mcp(mut mcp_cli)) => {
|
||||
// Propagate any root-level config overrides (e.g. `-c key=value`).
|
||||
prepend_config_flags(
|
||||
&mut interactive.config_overrides,
|
||||
prepend_config_flags(&mut mcp_cli.config_overrides, root_config_overrides.clone());
|
||||
mcp_cli.run(codex_linux_sandbox_exe).await?;
|
||||
}
|
||||
Some(Subcommand::Resume(ResumeCommand {
|
||||
session_id,
|
||||
last,
|
||||
config_overrides,
|
||||
})) => {
|
||||
interactive = finalize_resume_interactive(
|
||||
interactive,
|
||||
root_config_overrides.clone(),
|
||||
session_id,
|
||||
last,
|
||||
config_overrides,
|
||||
);
|
||||
codex_tui::run_main(interactive, codex_linux_sandbox_exe).await?;
|
||||
}
|
||||
@@ -286,8 +292,208 @@ fn prepend_config_flags(
|
||||
.splice(0..0, cli_config_overrides.raw_overrides);
|
||||
}
|
||||
|
||||
/// Build the final `TuiCli` for a `codex resume` invocation.
|
||||
fn finalize_resume_interactive(
|
||||
mut interactive: TuiCli,
|
||||
root_config_overrides: CliConfigOverrides,
|
||||
session_id: Option<String>,
|
||||
last: bool,
|
||||
resume_cli: TuiCli,
|
||||
) -> TuiCli {
|
||||
// Start with the parsed interactive CLI so resume shares the same
|
||||
// configuration surface area as `codex` without additional flags.
|
||||
let resume_session_id = session_id;
|
||||
interactive.resume_picker = resume_session_id.is_none() && !last;
|
||||
interactive.resume_last = last;
|
||||
interactive.resume_session_id = resume_session_id;
|
||||
|
||||
// Merge resume-scoped flags and overrides with highest precedence.
|
||||
merge_resume_cli_flags(&mut interactive, resume_cli);
|
||||
|
||||
// Propagate any root-level config overrides (e.g. `-c key=value`).
|
||||
prepend_config_flags(&mut interactive.config_overrides, root_config_overrides);
|
||||
|
||||
interactive
|
||||
}
|
||||
|
||||
/// Merge flags provided to `codex resume` so they take precedence over any
|
||||
/// root-level flags. Only overrides fields explicitly set on the resume-scoped
|
||||
/// CLI. Also appends `-c key=value` overrides with highest precedence.
|
||||
fn merge_resume_cli_flags(interactive: &mut TuiCli, resume_cli: TuiCli) {
|
||||
if let Some(model) = resume_cli.model {
|
||||
interactive.model = Some(model);
|
||||
}
|
||||
if resume_cli.oss {
|
||||
interactive.oss = true;
|
||||
}
|
||||
if let Some(profile) = resume_cli.config_profile {
|
||||
interactive.config_profile = Some(profile);
|
||||
}
|
||||
if let Some(sandbox) = resume_cli.sandbox_mode {
|
||||
interactive.sandbox_mode = Some(sandbox);
|
||||
}
|
||||
if let Some(approval) = resume_cli.approval_policy {
|
||||
interactive.approval_policy = Some(approval);
|
||||
}
|
||||
if resume_cli.full_auto {
|
||||
interactive.full_auto = true;
|
||||
}
|
||||
if resume_cli.dangerously_bypass_approvals_and_sandbox {
|
||||
interactive.dangerously_bypass_approvals_and_sandbox = true;
|
||||
}
|
||||
if let Some(cwd) = resume_cli.cwd {
|
||||
interactive.cwd = Some(cwd);
|
||||
}
|
||||
if resume_cli.web_search {
|
||||
interactive.web_search = true;
|
||||
}
|
||||
if !resume_cli.images.is_empty() {
|
||||
interactive.images = resume_cli.images;
|
||||
}
|
||||
if let Some(prompt) = resume_cli.prompt {
|
||||
interactive.prompt = Some(prompt);
|
||||
}
|
||||
|
||||
interactive
|
||||
.config_overrides
|
||||
.raw_overrides
|
||||
.extend(resume_cli.config_overrides.raw_overrides);
|
||||
}
|
||||
|
||||
fn print_completion(cmd: CompletionCommand) {
|
||||
let mut app = MultitoolCli::command();
|
||||
let name = "codex";
|
||||
generate(cmd.shell, &mut app, name, &mut std::io::stdout());
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn finalize_from_args(args: &[&str]) -> TuiCli {
|
||||
let cli = MultitoolCli::try_parse_from(args).expect("parse");
|
||||
let MultitoolCli {
|
||||
interactive,
|
||||
config_overrides: root_overrides,
|
||||
subcommand,
|
||||
} = cli;
|
||||
|
||||
let Subcommand::Resume(ResumeCommand {
|
||||
session_id,
|
||||
last,
|
||||
config_overrides: resume_cli,
|
||||
}) = subcommand.expect("resume present")
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
finalize_resume_interactive(interactive, root_overrides, session_id, last, resume_cli)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resume_model_flag_applies_when_no_root_flags() {
|
||||
let interactive = finalize_from_args(["codex", "resume", "-m", "gpt-5-test"].as_ref());
|
||||
|
||||
assert_eq!(interactive.model.as_deref(), Some("gpt-5-test"));
|
||||
assert!(interactive.resume_picker);
|
||||
assert!(!interactive.resume_last);
|
||||
assert_eq!(interactive.resume_session_id, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resume_picker_logic_none_and_not_last() {
|
||||
let interactive = finalize_from_args(["codex", "resume"].as_ref());
|
||||
assert!(interactive.resume_picker);
|
||||
assert!(!interactive.resume_last);
|
||||
assert_eq!(interactive.resume_session_id, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resume_picker_logic_last() {
|
||||
let interactive = finalize_from_args(["codex", "resume", "--last"].as_ref());
|
||||
assert!(!interactive.resume_picker);
|
||||
assert!(interactive.resume_last);
|
||||
assert_eq!(interactive.resume_session_id, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resume_picker_logic_with_session_id() {
|
||||
let interactive = finalize_from_args(["codex", "resume", "1234"].as_ref());
|
||||
assert!(!interactive.resume_picker);
|
||||
assert!(!interactive.resume_last);
|
||||
assert_eq!(interactive.resume_session_id.as_deref(), Some("1234"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resume_merges_option_flags_and_full_auto() {
|
||||
let interactive = finalize_from_args(
|
||||
[
|
||||
"codex",
|
||||
"resume",
|
||||
"sid",
|
||||
"--oss",
|
||||
"--full-auto",
|
||||
"--search",
|
||||
"--sandbox",
|
||||
"workspace-write",
|
||||
"--ask-for-approval",
|
||||
"on-request",
|
||||
"-m",
|
||||
"gpt-5-test",
|
||||
"-p",
|
||||
"my-profile",
|
||||
"-C",
|
||||
"/tmp",
|
||||
"-i",
|
||||
"/tmp/a.png,/tmp/b.png",
|
||||
]
|
||||
.as_ref(),
|
||||
);
|
||||
|
||||
assert_eq!(interactive.model.as_deref(), Some("gpt-5-test"));
|
||||
assert!(interactive.oss);
|
||||
assert_eq!(interactive.config_profile.as_deref(), Some("my-profile"));
|
||||
assert!(matches!(
|
||||
interactive.sandbox_mode,
|
||||
Some(codex_common::SandboxModeCliArg::WorkspaceWrite)
|
||||
));
|
||||
assert!(matches!(
|
||||
interactive.approval_policy,
|
||||
Some(codex_common::ApprovalModeCliArg::OnRequest)
|
||||
));
|
||||
assert!(interactive.full_auto);
|
||||
assert_eq!(
|
||||
interactive.cwd.as_deref(),
|
||||
Some(std::path::Path::new("/tmp"))
|
||||
);
|
||||
assert!(interactive.web_search);
|
||||
let has_a = interactive
|
||||
.images
|
||||
.iter()
|
||||
.any(|p| p == std::path::Path::new("/tmp/a.png"));
|
||||
let has_b = interactive
|
||||
.images
|
||||
.iter()
|
||||
.any(|p| p == std::path::Path::new("/tmp/b.png"));
|
||||
assert!(has_a && has_b);
|
||||
assert!(!interactive.resume_picker);
|
||||
assert!(!interactive.resume_last);
|
||||
assert_eq!(interactive.resume_session_id.as_deref(), Some("sid"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resume_merges_dangerously_bypass_flag() {
|
||||
let interactive = finalize_from_args(
|
||||
[
|
||||
"codex",
|
||||
"resume",
|
||||
"--dangerously-bypass-approvals-and-sandbox",
|
||||
]
|
||||
.as_ref(),
|
||||
);
|
||||
assert!(interactive.dangerously_bypass_approvals_and_sandbox);
|
||||
assert!(interactive.resume_picker);
|
||||
assert!(!interactive.resume_last);
|
||||
assert_eq!(interactive.resume_session_id, None);
|
||||
}
|
||||
}
|
||||
|
||||
370
codex-rs/cli/src/mcp_cmd.rs
Normal file
370
codex-rs/cli/src/mcp_cmd.rs
Normal file
@@ -0,0 +1,370 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::bail;
|
||||
use codex_common::CliConfigOverrides;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_core::config::find_codex_home;
|
||||
use codex_core::config::load_global_mcp_servers;
|
||||
use codex_core::config::write_global_mcp_servers;
|
||||
use codex_core::config_types::McpServerConfig;
|
||||
|
||||
/// [experimental] Launch Codex as an MCP server or manage configured MCP servers.
|
||||
///
|
||||
/// Subcommands:
|
||||
/// - `serve` — run the MCP server on stdio
|
||||
/// - `list` — list configured servers (with `--json`)
|
||||
/// - `get` — show a single server (with `--json`)
|
||||
/// - `add` — add a server launcher entry to `~/.codex/config.toml`
|
||||
/// - `remove` — delete a server entry
|
||||
#[derive(Debug, clap::Parser)]
|
||||
pub struct McpCli {
|
||||
#[clap(flatten)]
|
||||
pub config_overrides: CliConfigOverrides,
|
||||
|
||||
#[command(subcommand)]
|
||||
pub cmd: Option<McpSubcommand>,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
pub enum McpSubcommand {
|
||||
/// [experimental] Run the Codex MCP server (stdio transport).
|
||||
Serve,
|
||||
|
||||
/// [experimental] List configured MCP servers.
|
||||
List(ListArgs),
|
||||
|
||||
/// [experimental] Show details for a configured MCP server.
|
||||
Get(GetArgs),
|
||||
|
||||
/// [experimental] Add a global MCP server entry.
|
||||
Add(AddArgs),
|
||||
|
||||
/// [experimental] Remove a global MCP server entry.
|
||||
Remove(RemoveArgs),
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
pub struct ListArgs {
|
||||
/// Output the configured servers as JSON.
|
||||
#[arg(long)]
|
||||
pub json: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
pub struct GetArgs {
|
||||
/// Name of the MCP server to display.
|
||||
pub name: String,
|
||||
|
||||
/// Output the server configuration as JSON.
|
||||
#[arg(long)]
|
||||
pub json: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
pub struct AddArgs {
|
||||
/// Name for the MCP server configuration.
|
||||
pub name: String,
|
||||
|
||||
/// Environment variables to set when launching the server.
|
||||
#[arg(long, value_parser = parse_env_pair, value_name = "KEY=VALUE")]
|
||||
pub env: Vec<(String, String)>,
|
||||
|
||||
/// Command to launch the MCP server.
|
||||
#[arg(trailing_var_arg = true, num_args = 1..)]
|
||||
pub command: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
pub struct RemoveArgs {
|
||||
/// Name of the MCP server configuration to remove.
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl McpCli {
|
||||
pub async fn run(self, codex_linux_sandbox_exe: Option<PathBuf>) -> Result<()> {
|
||||
let McpCli {
|
||||
config_overrides,
|
||||
cmd,
|
||||
} = self;
|
||||
let subcommand = cmd.unwrap_or(McpSubcommand::Serve);
|
||||
|
||||
match subcommand {
|
||||
McpSubcommand::Serve => {
|
||||
codex_mcp_server::run_main(codex_linux_sandbox_exe, config_overrides).await?;
|
||||
}
|
||||
McpSubcommand::List(args) => {
|
||||
run_list(&config_overrides, args)?;
|
||||
}
|
||||
McpSubcommand::Get(args) => {
|
||||
run_get(&config_overrides, args)?;
|
||||
}
|
||||
McpSubcommand::Add(args) => {
|
||||
run_add(&config_overrides, args)?;
|
||||
}
|
||||
McpSubcommand::Remove(args) => {
|
||||
run_remove(&config_overrides, args)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn run_add(config_overrides: &CliConfigOverrides, add_args: AddArgs) -> Result<()> {
|
||||
// Validate any provided overrides even though they are not currently applied.
|
||||
config_overrides.parse_overrides().map_err(|e| anyhow!(e))?;
|
||||
|
||||
let AddArgs { name, env, command } = add_args;
|
||||
|
||||
validate_server_name(&name)?;
|
||||
|
||||
let mut command_parts = command.into_iter();
|
||||
let command_bin = command_parts
|
||||
.next()
|
||||
.ok_or_else(|| anyhow!("command is required"))?;
|
||||
let command_args: Vec<String> = command_parts.collect();
|
||||
|
||||
let env_map = if env.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let mut map = HashMap::new();
|
||||
for (key, value) in env {
|
||||
map.insert(key, value);
|
||||
}
|
||||
Some(map)
|
||||
};
|
||||
|
||||
let codex_home = find_codex_home().context("failed to resolve CODEX_HOME")?;
|
||||
let mut servers = load_global_mcp_servers(&codex_home)
|
||||
.with_context(|| format!("failed to load MCP servers from {}", codex_home.display()))?;
|
||||
|
||||
let new_entry = McpServerConfig {
|
||||
command: command_bin,
|
||||
args: command_args,
|
||||
env: env_map,
|
||||
startup_timeout_ms: None,
|
||||
};
|
||||
|
||||
servers.insert(name.clone(), new_entry);
|
||||
|
||||
write_global_mcp_servers(&codex_home, &servers)
|
||||
.with_context(|| format!("failed to write MCP servers to {}", codex_home.display()))?;
|
||||
|
||||
println!("Added global MCP server '{name}'.");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_remove(config_overrides: &CliConfigOverrides, remove_args: RemoveArgs) -> Result<()> {
|
||||
config_overrides.parse_overrides().map_err(|e| anyhow!(e))?;
|
||||
|
||||
let RemoveArgs { name } = remove_args;
|
||||
|
||||
validate_server_name(&name)?;
|
||||
|
||||
let codex_home = find_codex_home().context("failed to resolve CODEX_HOME")?;
|
||||
let mut servers = load_global_mcp_servers(&codex_home)
|
||||
.with_context(|| format!("failed to load MCP servers from {}", codex_home.display()))?;
|
||||
|
||||
let removed = servers.remove(&name).is_some();
|
||||
|
||||
if removed {
|
||||
write_global_mcp_servers(&codex_home, &servers)
|
||||
.with_context(|| format!("failed to write MCP servers to {}", codex_home.display()))?;
|
||||
}
|
||||
|
||||
if removed {
|
||||
println!("Removed global MCP server '{name}'.");
|
||||
} else {
|
||||
println!("No MCP server named '{name}' found.");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_list(config_overrides: &CliConfigOverrides, list_args: ListArgs) -> Result<()> {
|
||||
let overrides = config_overrides.parse_overrides().map_err(|e| anyhow!(e))?;
|
||||
let config = Config::load_with_cli_overrides(overrides, ConfigOverrides::default())
|
||||
.context("failed to load configuration")?;
|
||||
|
||||
let mut entries: Vec<_> = config.mcp_servers.iter().collect();
|
||||
entries.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||
|
||||
if list_args.json {
|
||||
let json_entries: Vec<_> = entries
|
||||
.into_iter()
|
||||
.map(|(name, cfg)| {
|
||||
let env = cfg.env.as_ref().map(|env| {
|
||||
env.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.collect::<BTreeMap<_, _>>()
|
||||
});
|
||||
serde_json::json!({
|
||||
"name": name,
|
||||
"command": cfg.command,
|
||||
"args": cfg.args,
|
||||
"env": env,
|
||||
"startup_timeout_ms": cfg.startup_timeout_ms,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let output = serde_json::to_string_pretty(&json_entries)?;
|
||||
println!("{output}");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if entries.is_empty() {
|
||||
println!("No MCP servers configured yet. Try `codex mcp add my-tool -- my-command`.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut rows: Vec<[String; 4]> = Vec::new();
|
||||
for (name, cfg) in entries {
|
||||
let args = if cfg.args.is_empty() {
|
||||
"-".to_string()
|
||||
} else {
|
||||
cfg.args.join(" ")
|
||||
};
|
||||
|
||||
let env = match cfg.env.as_ref() {
|
||||
None => "-".to_string(),
|
||||
Some(map) if map.is_empty() => "-".to_string(),
|
||||
Some(map) => {
|
||||
let mut pairs: Vec<_> = map.iter().collect();
|
||||
pairs.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||
pairs
|
||||
.into_iter()
|
||||
.map(|(k, v)| format!("{k}={v}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
}
|
||||
};
|
||||
|
||||
rows.push([name.clone(), cfg.command.clone(), args, env]);
|
||||
}
|
||||
|
||||
let mut widths = ["Name".len(), "Command".len(), "Args".len(), "Env".len()];
|
||||
for row in &rows {
|
||||
for (i, cell) in row.iter().enumerate() {
|
||||
widths[i] = widths[i].max(cell.len());
|
||||
}
|
||||
}
|
||||
|
||||
println!(
|
||||
"{:<name_w$} {:<cmd_w$} {:<args_w$} {:<env_w$}",
|
||||
"Name",
|
||||
"Command",
|
||||
"Args",
|
||||
"Env",
|
||||
name_w = widths[0],
|
||||
cmd_w = widths[1],
|
||||
args_w = widths[2],
|
||||
env_w = widths[3],
|
||||
);
|
||||
|
||||
for row in rows {
|
||||
println!(
|
||||
"{:<name_w$} {:<cmd_w$} {:<args_w$} {:<env_w$}",
|
||||
row[0],
|
||||
row[1],
|
||||
row[2],
|
||||
row[3],
|
||||
name_w = widths[0],
|
||||
cmd_w = widths[1],
|
||||
args_w = widths[2],
|
||||
env_w = widths[3],
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_get(config_overrides: &CliConfigOverrides, get_args: GetArgs) -> Result<()> {
|
||||
let overrides = config_overrides.parse_overrides().map_err(|e| anyhow!(e))?;
|
||||
let config = Config::load_with_cli_overrides(overrides, ConfigOverrides::default())
|
||||
.context("failed to load configuration")?;
|
||||
|
||||
let Some(server) = config.mcp_servers.get(&get_args.name) else {
|
||||
bail!("No MCP server named '{name}' found.", name = get_args.name);
|
||||
};
|
||||
|
||||
if get_args.json {
|
||||
let env = server.env.as_ref().map(|env| {
|
||||
env.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.collect::<BTreeMap<_, _>>()
|
||||
});
|
||||
let output = serde_json::to_string_pretty(&serde_json::json!({
|
||||
"name": get_args.name,
|
||||
"command": server.command,
|
||||
"args": server.args,
|
||||
"env": env,
|
||||
"startup_timeout_ms": server.startup_timeout_ms,
|
||||
}))?;
|
||||
println!("{output}");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("{}", get_args.name);
|
||||
println!(" command: {}", server.command);
|
||||
let args = if server.args.is_empty() {
|
||||
"-".to_string()
|
||||
} else {
|
||||
server.args.join(" ")
|
||||
};
|
||||
println!(" args: {args}");
|
||||
let env_display = match server.env.as_ref() {
|
||||
None => "-".to_string(),
|
||||
Some(map) if map.is_empty() => "-".to_string(),
|
||||
Some(map) => {
|
||||
let mut pairs: Vec<_> = map.iter().collect();
|
||||
pairs.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||
pairs
|
||||
.into_iter()
|
||||
.map(|(k, v)| format!("{k}={v}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
}
|
||||
};
|
||||
println!(" env: {env_display}");
|
||||
if let Some(timeout) = server.startup_timeout_ms {
|
||||
println!(" startup_timeout_ms: {timeout}");
|
||||
}
|
||||
println!(" remove: codex mcp remove {}", get_args.name);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_env_pair(raw: &str) -> Result<(String, String), String> {
|
||||
let mut parts = raw.splitn(2, '=');
|
||||
let key = parts
|
||||
.next()
|
||||
.map(str::trim)
|
||||
.filter(|s| !s.is_empty())
|
||||
.ok_or_else(|| "environment entries must be in KEY=VALUE form".to_string())?;
|
||||
let value = parts
|
||||
.next()
|
||||
.map(str::to_string)
|
||||
.ok_or_else(|| "environment entries must be in KEY=VALUE form".to_string())?;
|
||||
|
||||
Ok((key.to_string(), value))
|
||||
}
|
||||
|
||||
fn validate_server_name(name: &str) -> Result<()> {
|
||||
let is_valid = !name.is_empty()
|
||||
&& name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_');
|
||||
|
||||
if is_valid {
|
||||
Ok(())
|
||||
} else {
|
||||
bail!("invalid server name '{name}' (use letters, numbers, '-', '_')");
|
||||
}
|
||||
}
|
||||
86
codex-rs/cli/tests/mcp_add_remove.rs
Normal file
86
codex-rs/cli/tests/mcp_add_remove.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use codex_core::config::load_global_mcp_servers;
|
||||
use predicates::str::contains;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn codex_command(codex_home: &Path) -> Result<assert_cmd::Command> {
|
||||
let mut cmd = assert_cmd::Command::cargo_bin("codex")?;
|
||||
cmd.env("CODEX_HOME", codex_home);
|
||||
Ok(cmd)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_and_remove_server_updates_global_config() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut add_cmd = codex_command(codex_home.path())?;
|
||||
add_cmd
|
||||
.args(["mcp", "add", "docs", "--", "echo", "hello"])
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Added global MCP server 'docs'."));
|
||||
|
||||
let servers = load_global_mcp_servers(codex_home.path())?;
|
||||
assert_eq!(servers.len(), 1);
|
||||
let docs = servers.get("docs").expect("server should exist");
|
||||
assert_eq!(docs.command, "echo");
|
||||
assert_eq!(docs.args, vec!["hello".to_string()]);
|
||||
assert!(docs.env.is_none());
|
||||
|
||||
let mut remove_cmd = codex_command(codex_home.path())?;
|
||||
remove_cmd
|
||||
.args(["mcp", "remove", "docs"])
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Removed global MCP server 'docs'."));
|
||||
|
||||
let servers = load_global_mcp_servers(codex_home.path())?;
|
||||
assert!(servers.is_empty());
|
||||
|
||||
let mut remove_again_cmd = codex_command(codex_home.path())?;
|
||||
remove_again_cmd
|
||||
.args(["mcp", "remove", "docs"])
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("No MCP server named 'docs' found."));
|
||||
|
||||
let servers = load_global_mcp_servers(codex_home.path())?;
|
||||
assert!(servers.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_with_env_preserves_key_order_and_values() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut add_cmd = codex_command(codex_home.path())?;
|
||||
add_cmd
|
||||
.args([
|
||||
"mcp",
|
||||
"add",
|
||||
"envy",
|
||||
"--env",
|
||||
"FOO=bar",
|
||||
"--env",
|
||||
"ALPHA=beta",
|
||||
"--",
|
||||
"python",
|
||||
"server.py",
|
||||
])
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
let servers = load_global_mcp_servers(codex_home.path())?;
|
||||
let envy = servers.get("envy").expect("server should exist");
|
||||
let env = envy.env.as_ref().expect("env should be present");
|
||||
|
||||
assert_eq!(env.len(), 2);
|
||||
assert_eq!(env.get("FOO"), Some(&"bar".to_string()));
|
||||
assert_eq!(env.get("ALPHA"), Some(&"beta".to_string()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
106
codex-rs/cli/tests/mcp_list.rs
Normal file
106
codex-rs/cli/tests/mcp_list.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use predicates::str::contains;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::Value as JsonValue;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn codex_command(codex_home: &Path) -> Result<assert_cmd::Command> {
|
||||
let mut cmd = assert_cmd::Command::cargo_bin("codex")?;
|
||||
cmd.env("CODEX_HOME", codex_home);
|
||||
Ok(cmd)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_shows_empty_state() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut cmd = codex_command(codex_home.path())?;
|
||||
let output = cmd.args(["mcp", "list"]).output()?;
|
||||
assert!(output.status.success());
|
||||
let stdout = String::from_utf8(output.stdout)?;
|
||||
assert!(stdout.contains("No MCP servers configured yet."));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_and_get_render_expected_output() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut add = codex_command(codex_home.path())?;
|
||||
add.args([
|
||||
"mcp",
|
||||
"add",
|
||||
"docs",
|
||||
"--env",
|
||||
"TOKEN=secret",
|
||||
"--",
|
||||
"docs-server",
|
||||
"--port",
|
||||
"4000",
|
||||
])
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
let mut list_cmd = codex_command(codex_home.path())?;
|
||||
let list_output = list_cmd.args(["mcp", "list"]).output()?;
|
||||
assert!(list_output.status.success());
|
||||
let stdout = String::from_utf8(list_output.stdout)?;
|
||||
assert!(stdout.contains("Name"));
|
||||
assert!(stdout.contains("docs"));
|
||||
assert!(stdout.contains("docs-server"));
|
||||
assert!(stdout.contains("TOKEN=secret"));
|
||||
|
||||
let mut list_json_cmd = codex_command(codex_home.path())?;
|
||||
let json_output = list_json_cmd.args(["mcp", "list", "--json"]).output()?;
|
||||
assert!(json_output.status.success());
|
||||
let stdout = String::from_utf8(json_output.stdout)?;
|
||||
let parsed: JsonValue = serde_json::from_str(&stdout)?;
|
||||
let array = parsed.as_array().expect("expected array");
|
||||
assert_eq!(array.len(), 1);
|
||||
let entry = &array[0];
|
||||
assert_eq!(entry.get("name"), Some(&JsonValue::String("docs".into())));
|
||||
assert_eq!(
|
||||
entry.get("command"),
|
||||
Some(&JsonValue::String("docs-server".into()))
|
||||
);
|
||||
|
||||
let args = entry
|
||||
.get("args")
|
||||
.and_then(|v| v.as_array())
|
||||
.expect("args array");
|
||||
assert_eq!(
|
||||
args,
|
||||
&vec![
|
||||
JsonValue::String("--port".into()),
|
||||
JsonValue::String("4000".into())
|
||||
]
|
||||
);
|
||||
|
||||
let env = entry
|
||||
.get("env")
|
||||
.and_then(|v| v.as_object())
|
||||
.expect("env map");
|
||||
assert_eq!(env.get("TOKEN"), Some(&JsonValue::String("secret".into())));
|
||||
|
||||
let mut get_cmd = codex_command(codex_home.path())?;
|
||||
let get_output = get_cmd.args(["mcp", "get", "docs"]).output()?;
|
||||
assert!(get_output.status.success());
|
||||
let stdout = String::from_utf8(get_output.stdout)?;
|
||||
assert!(stdout.contains("docs"));
|
||||
assert!(stdout.contains("command: docs-server"));
|
||||
assert!(stdout.contains("args: --port 4000"));
|
||||
assert!(stdout.contains("env: TOKEN=secret"));
|
||||
assert!(stdout.contains("remove: codex mcp remove docs"));
|
||||
|
||||
let mut get_json_cmd = codex_command(codex_home.path())?;
|
||||
get_json_cmd
|
||||
.args(["mcp", "get", "docs", "--json"])
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("\"name\": \"docs\""));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -74,7 +74,7 @@ pub fn builtin_model_presets(auth_mode: Option<AuthMode>) -> Vec<ModelPreset> {
|
||||
Some(AuthMode::ApiKey) => PRESETS
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|p| !p.model.contains(SWIFTFOX_MEDIUM_MODEL))
|
||||
.filter(|p| p.model != SWIFTFOX_MEDIUM_MODEL)
|
||||
.collect(),
|
||||
_ => PRESETS.to_vec(),
|
||||
}
|
||||
|
||||
@@ -25,12 +25,16 @@ use codex_protocol::mcp_protocol::Tools;
|
||||
use codex_protocol::mcp_protocol::UserSavedConfig;
|
||||
use dirs::home_dir;
|
||||
use serde::Deserialize;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use tempfile::NamedTempFile;
|
||||
use toml::Value as TomlValue;
|
||||
use toml_edit::Array as TomlArray;
|
||||
use toml_edit::DocumentMut;
|
||||
use toml_edit::Item as TomlItem;
|
||||
use toml_edit::Table as TomlTable;
|
||||
|
||||
const OPENAI_DEFAULT_MODEL: &str = "gpt-5";
|
||||
const OPENAI_DEFAULT_REVIEW_MODEL: &str = "gpt-5";
|
||||
@@ -265,6 +269,88 @@ pub fn load_config_as_toml(codex_home: &Path) -> std::io::Result<TomlValue> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_global_mcp_servers(
|
||||
codex_home: &Path,
|
||||
) -> std::io::Result<BTreeMap<String, McpServerConfig>> {
|
||||
let root_value = load_config_as_toml(codex_home)?;
|
||||
let Some(servers_value) = root_value.get("mcp_servers") else {
|
||||
return Ok(BTreeMap::new());
|
||||
};
|
||||
|
||||
servers_value
|
||||
.clone()
|
||||
.try_into()
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
|
||||
}
|
||||
|
||||
pub fn write_global_mcp_servers(
|
||||
codex_home: &Path,
|
||||
servers: &BTreeMap<String, McpServerConfig>,
|
||||
) -> std::io::Result<()> {
|
||||
let config_path = codex_home.join(CONFIG_TOML_FILE);
|
||||
let mut doc = match std::fs::read_to_string(&config_path) {
|
||||
Ok(contents) => contents
|
||||
.parse::<DocumentMut>()
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?,
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => DocumentMut::new(),
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
doc.as_table_mut().remove("mcp_servers");
|
||||
|
||||
if !servers.is_empty() {
|
||||
let mut table = TomlTable::new();
|
||||
table.set_implicit(true);
|
||||
doc["mcp_servers"] = TomlItem::Table(table);
|
||||
|
||||
for (name, config) in servers {
|
||||
let mut entry = TomlTable::new();
|
||||
entry.set_implicit(false);
|
||||
entry["command"] = toml_edit::value(config.command.clone());
|
||||
|
||||
if !config.args.is_empty() {
|
||||
let mut args = TomlArray::new();
|
||||
for arg in &config.args {
|
||||
args.push(arg.clone());
|
||||
}
|
||||
entry["args"] = TomlItem::Value(args.into());
|
||||
}
|
||||
|
||||
if let Some(env) = &config.env
|
||||
&& !env.is_empty()
|
||||
{
|
||||
let mut env_table = TomlTable::new();
|
||||
env_table.set_implicit(false);
|
||||
let mut pairs: Vec<_> = env.iter().collect();
|
||||
pairs.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||
for (key, value) in pairs {
|
||||
env_table.insert(key, toml_edit::value(value.clone()));
|
||||
}
|
||||
entry["env"] = TomlItem::Table(env_table);
|
||||
}
|
||||
|
||||
if let Some(timeout) = config.startup_timeout_ms {
|
||||
let timeout = i64::try_from(timeout).map_err(|_| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
"startup_timeout_ms exceeds supported range",
|
||||
)
|
||||
})?;
|
||||
entry["startup_timeout_ms"] = toml_edit::value(timeout);
|
||||
}
|
||||
|
||||
doc["mcp_servers"][name.as_str()] = TomlItem::Table(entry);
|
||||
}
|
||||
}
|
||||
|
||||
std::fs::create_dir_all(codex_home)?;
|
||||
let tmp_file = NamedTempFile::new_in(codex_home)?;
|
||||
std::fs::write(tmp_file.path(), doc.to_string())?;
|
||||
tmp_file.persist(config_path).map_err(|err| err.error)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_project_trusted_inner(doc: &mut DocumentMut, project_path: &Path) -> anyhow::Result<()> {
|
||||
// Ensure we render a human-friendly structure:
|
||||
//
|
||||
@@ -1162,6 +1248,47 @@ exclude_slash_tmp = true
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_global_mcp_servers_returns_empty_if_missing() -> anyhow::Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let servers = load_global_mcp_servers(codex_home.path())?;
|
||||
assert!(servers.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_global_mcp_servers_round_trips_entries() -> anyhow::Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut servers = BTreeMap::new();
|
||||
servers.insert(
|
||||
"docs".to_string(),
|
||||
McpServerConfig {
|
||||
command: "echo".to_string(),
|
||||
args: vec!["hello".to_string()],
|
||||
env: None,
|
||||
startup_timeout_ms: None,
|
||||
},
|
||||
);
|
||||
|
||||
write_global_mcp_servers(codex_home.path(), &servers)?;
|
||||
|
||||
let loaded = load_global_mcp_servers(codex_home.path())?;
|
||||
assert_eq!(loaded.len(), 1);
|
||||
let docs = loaded.get("docs").expect("docs entry");
|
||||
assert_eq!(docs.command, "echo");
|
||||
assert_eq!(docs.args, vec!["hello".to_string()]);
|
||||
|
||||
let empty = BTreeMap::new();
|
||||
write_global_mcp_servers(codex_home.path(), &empty)?;
|
||||
let loaded = load_global_mcp_servers(codex_home.path())?;
|
||||
assert!(loaded.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn persist_model_selection_updates_defaults() -> anyhow::Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
@@ -11,9 +11,6 @@ pub(crate) struct ExecCommandSession {
|
||||
/// Broadcast stream of output chunks read from the PTY. New subscribers
|
||||
/// receive only chunks emitted after they subscribe.
|
||||
output_tx: broadcast::Sender<Vec<u8>>,
|
||||
/// Receiver subscribed before the child process starts emitting output so
|
||||
/// the first caller can consume any early data without races.
|
||||
initial_output_rx: StdMutex<Option<broadcast::Receiver<Vec<u8>>>>,
|
||||
|
||||
/// Child killer handle for termination on drop (can signal independently
|
||||
/// of a thread blocked in `.wait()`).
|
||||
@@ -41,25 +38,20 @@ impl ExecCommandSession {
|
||||
writer_handle: JoinHandle<()>,
|
||||
wait_handle: JoinHandle<()>,
|
||||
exit_status: std::sync::Arc<std::sync::atomic::AtomicBool>,
|
||||
) -> Self {
|
||||
Self {
|
||||
writer_tx,
|
||||
output_tx,
|
||||
initial_output_rx: StdMutex::new(None),
|
||||
killer: StdMutex::new(Some(killer)),
|
||||
reader_handle: StdMutex::new(Some(reader_handle)),
|
||||
writer_handle: StdMutex::new(Some(writer_handle)),
|
||||
wait_handle: StdMutex::new(Some(wait_handle)),
|
||||
exit_status,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_initial_output_receiver(&self, receiver: broadcast::Receiver<Vec<u8>>) {
|
||||
if let Ok(mut guard) = self.initial_output_rx.lock()
|
||||
&& guard.is_none()
|
||||
{
|
||||
*guard = Some(receiver);
|
||||
}
|
||||
) -> (Self, broadcast::Receiver<Vec<u8>>) {
|
||||
let initial_output_rx = output_tx.subscribe();
|
||||
(
|
||||
Self {
|
||||
writer_tx,
|
||||
output_tx,
|
||||
killer: StdMutex::new(Some(killer)),
|
||||
reader_handle: StdMutex::new(Some(reader_handle)),
|
||||
writer_handle: StdMutex::new(Some(writer_handle)),
|
||||
wait_handle: StdMutex::new(Some(wait_handle)),
|
||||
exit_status,
|
||||
},
|
||||
initial_output_rx,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn writer_sender(&self) -> mpsc::Sender<Vec<u8>> {
|
||||
@@ -67,13 +59,7 @@ impl ExecCommandSession {
|
||||
}
|
||||
|
||||
pub(crate) fn output_receiver(&self) -> broadcast::Receiver<Vec<u8>> {
|
||||
if let Ok(mut guard) = self.initial_output_rx.lock()
|
||||
&& let Some(receiver) = guard.take()
|
||||
{
|
||||
receiver
|
||||
} else {
|
||||
self.output_tx.subscribe()
|
||||
}
|
||||
self.output_tx.subscribe()
|
||||
}
|
||||
|
||||
pub(crate) fn has_exited(&self) -> bool {
|
||||
|
||||
@@ -93,18 +93,16 @@ impl SessionManager {
|
||||
.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
|
||||
);
|
||||
|
||||
let (session, mut exit_rx) =
|
||||
create_exec_command_session(params.clone())
|
||||
.await
|
||||
.map_err(|err| {
|
||||
format!(
|
||||
"failed to create exec command session for session id {}: {err}",
|
||||
session_id.0
|
||||
)
|
||||
})?;
|
||||
let (session, mut output_rx, mut exit_rx) = create_exec_command_session(params.clone())
|
||||
.await
|
||||
.map_err(|err| {
|
||||
format!(
|
||||
"failed to create exec command session for session id {}: {err}",
|
||||
session_id.0
|
||||
)
|
||||
})?;
|
||||
|
||||
// Insert into session map.
|
||||
let mut output_rx = session.output_receiver();
|
||||
self.sessions.lock().await.insert(session_id, session);
|
||||
|
||||
// Collect output until either timeout expires or process exits.
|
||||
@@ -245,7 +243,11 @@ impl SessionManager {
|
||||
/// Spawn PTY and child process per spawn_exec_command_session logic.
|
||||
async fn create_exec_command_session(
|
||||
params: ExecCommandParams,
|
||||
) -> anyhow::Result<(ExecCommandSession, oneshot::Receiver<i32>)> {
|
||||
) -> anyhow::Result<(
|
||||
ExecCommandSession,
|
||||
tokio::sync::broadcast::Receiver<Vec<u8>>,
|
||||
oneshot::Receiver<i32>,
|
||||
)> {
|
||||
let ExecCommandParams {
|
||||
cmd,
|
||||
yield_time_ms: _,
|
||||
@@ -279,8 +281,6 @@ async fn create_exec_command_session(
|
||||
let (writer_tx, mut writer_rx) = mpsc::channel::<Vec<u8>>(128);
|
||||
// Broadcast for streaming PTY output to readers: subscribers receive from subscription time.
|
||||
let (output_tx, _) = tokio::sync::broadcast::channel::<Vec<u8>>(256);
|
||||
let initial_output_rx = output_tx.subscribe();
|
||||
|
||||
// Reader task: drain PTY and forward chunks to output channel.
|
||||
let mut reader = pair.master.try_clone_reader()?;
|
||||
let output_tx_clone = output_tx.clone();
|
||||
@@ -342,7 +342,7 @@ async fn create_exec_command_session(
|
||||
});
|
||||
|
||||
// Create and store the session with channels.
|
||||
let session = ExecCommandSession::new(
|
||||
let (session, initial_output_rx) = ExecCommandSession::new(
|
||||
writer_tx,
|
||||
output_tx,
|
||||
killer,
|
||||
@@ -351,8 +351,7 @@ async fn create_exec_command_session(
|
||||
wait_handle,
|
||||
exit_status,
|
||||
);
|
||||
session.set_initial_output_receiver(initial_output_rx);
|
||||
Ok((session, exit_rx))
|
||||
Ok((session, initial_output_rx, exit_rx))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use anyhow::Context;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::io::ErrorKind;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -31,7 +32,14 @@ impl InternalStorage {
|
||||
}
|
||||
},
|
||||
Err(error) => {
|
||||
tracing::warn!("failed to read internal storage: {error:?}");
|
||||
if error.kind() == ErrorKind::NotFound {
|
||||
tracing::debug!(
|
||||
"internal storage not found at {}; initializing defaults",
|
||||
storage_path.display()
|
||||
);
|
||||
} else {
|
||||
tracing::warn!("failed to read internal storage: {error:?}");
|
||||
}
|
||||
Self::empty(storage_path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ pub(crate) fn should_persist_event_msg(ev: &EventMsg) -> bool {
|
||||
| EventMsg::AgentReasoningRawContent(_)
|
||||
| EventMsg::TokenCount(_)
|
||||
| EventMsg::EnteredReviewMode(_)
|
||||
| EventMsg::ExitedReviewMode(_) => true,
|
||||
| EventMsg::ExitedReviewMode(_)
|
||||
| EventMsg::TurnAborted(_) => true,
|
||||
EventMsg::Error(_)
|
||||
| EventMsg::TaskStarted(_)
|
||||
| EventMsg::TaskComplete(_)
|
||||
@@ -67,7 +68,6 @@ pub(crate) fn should_persist_event_msg(ev: &EventMsg) -> bool {
|
||||
| EventMsg::McpListToolsResponse(_)
|
||||
| EventMsg::ListCustomPromptsResponse(_)
|
||||
| EventMsg::PlanUpdate(_)
|
||||
| EventMsg::TurnAborted(_)
|
||||
| EventMsg::ShutdownComplete
|
||||
| EventMsg::ConversationPath(_) => false,
|
||||
}
|
||||
|
||||
@@ -100,10 +100,13 @@ type OutputBuffer = Arc<Mutex<OutputBufferState>>;
|
||||
type OutputHandles = (OutputBuffer, Arc<Notify>);
|
||||
|
||||
impl ManagedUnifiedExecSession {
|
||||
fn new(session: ExecCommandSession) -> Self {
|
||||
fn new(
|
||||
session: ExecCommandSession,
|
||||
initial_output_rx: tokio::sync::broadcast::Receiver<Vec<u8>>,
|
||||
) -> Self {
|
||||
let output_buffer = Arc::new(Mutex::new(OutputBufferState::default()));
|
||||
let output_notify = Arc::new(Notify::new());
|
||||
let mut receiver = session.output_receiver();
|
||||
let mut receiver = initial_output_rx;
|
||||
let buffer_clone = Arc::clone(&output_buffer);
|
||||
let notify_clone = Arc::clone(&output_notify);
|
||||
let output_task = tokio::spawn(async move {
|
||||
@@ -193,8 +196,8 @@ impl UnifiedExecSessionManager {
|
||||
} else {
|
||||
let command = request.input_chunks.to_vec();
|
||||
let new_id = self.next_session_id.fetch_add(1, Ordering::SeqCst);
|
||||
let session = create_unified_exec_session(&command).await?;
|
||||
let managed_session = ManagedUnifiedExecSession::new(session);
|
||||
let (session, initial_output_rx) = create_unified_exec_session(&command).await?;
|
||||
let managed_session = ManagedUnifiedExecSession::new(session, initial_output_rx);
|
||||
let (buffer, notify) = managed_session.output_handles();
|
||||
writer_tx = managed_session.writer_sender();
|
||||
output_buffer = buffer;
|
||||
@@ -297,7 +300,13 @@ impl UnifiedExecSessionManager {
|
||||
|
||||
async fn create_unified_exec_session(
|
||||
command: &[String],
|
||||
) -> Result<ExecCommandSession, UnifiedExecError> {
|
||||
) -> Result<
|
||||
(
|
||||
ExecCommandSession,
|
||||
tokio::sync::broadcast::Receiver<Vec<u8>>,
|
||||
),
|
||||
UnifiedExecError,
|
||||
> {
|
||||
if command.is_empty() {
|
||||
return Err(UnifiedExecError::MissingCommandLine);
|
||||
}
|
||||
@@ -327,7 +336,6 @@ async fn create_unified_exec_session(
|
||||
|
||||
let (writer_tx, mut writer_rx) = mpsc::channel::<Vec<u8>>(128);
|
||||
let (output_tx, _) = tokio::sync::broadcast::channel::<Vec<u8>>(256);
|
||||
let initial_output_rx = output_tx.subscribe();
|
||||
|
||||
let mut reader = pair
|
||||
.master
|
||||
@@ -381,7 +389,7 @@ async fn create_unified_exec_session(
|
||||
wait_exit_status.store(true, Ordering::SeqCst);
|
||||
});
|
||||
|
||||
let session = ExecCommandSession::new(
|
||||
let (session, initial_output_rx) = ExecCommandSession::new(
|
||||
writer_tx,
|
||||
output_tx,
|
||||
killer,
|
||||
@@ -390,9 +398,7 @@ async fn create_unified_exec_session(
|
||||
wait_handle,
|
||||
exit_status,
|
||||
);
|
||||
session.set_initial_output_receiver(initial_output_rx);
|
||||
|
||||
Ok(session)
|
||||
Ok((session, initial_output_rx))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,33 +1,21 @@
|
||||
You are Swiftfox. You are running as a coding agent in the Codex CLI on a user's computer.
|
||||
|
||||
## Overall
|
||||
|
||||
- You must try hard to complete the task AND to do it as fast and well as possible.
|
||||
* Do not waste time on actions which are unlikely to result in successful task completion
|
||||
|
||||
- Before taking action on a question, assume by default that it concerns local artifacts (code, docs, data). Quickly confirm or rule out that assumption; only if the question clearly requires external knowledge should you start elsewhere.
|
||||
- Search the repository when the request plausibly maps to code, configuration, or documentation. Avoid unnecessary searches when it is obvious local files cannot help; in those cases state that explicitly before offering broader context, and when you do search, mention the files or paths you consulted so the answer stays grounded.
|
||||
- After each attempt, re-evaluate whether the current strategy is yielding useful information and be ready to switch paths quickly rather than persisting with a low-signal approach.
|
||||
|
||||
- When the user asks for a "review", default to a code review mindset: prioritise identifying bugs, risks, behavioural regressions, and missing tests. Findings must be the primary focus of the response - keep summaries or overviews brief and only after enumerating the issues. Present findings first (ordered by severity with file/line references), follow with open questions or assumptions, and offer a change-summary only as a secondary detail. If no findings are discovered, state that explicitly and mention any residual risks or testing gaps.
|
||||
## General
|
||||
|
||||
- The arguments to `shell` will be passed to execvp(). Most terminal commands should be prefixed with ["bash", "-lc"].
|
||||
- Always set the `workdir` param of the shell tool. Do not use `cd` unless absolutely necessary.
|
||||
- Always set the `workdir` param when using the shell function. Do not use `cd` unless absolutely necessary.
|
||||
- When searching for text or files, prefer using `rg` or `rg --files` respectively because `rg` is much faster than alternatives like `grep`. (If the `rg` command is not found, then use alternatives.)
|
||||
- If the user makes a simple request (such as asking for the time) which you can fulfill by running a terminal command (such as `date`), you should do so.
|
||||
- Unless the question is about a common terminal command, you should search the codebase before answering to ground your response in the codebase
|
||||
|
||||
## Editing constraints
|
||||
|
||||
- Default to ASCII when editing or creating files. Only introduce non-ASCII or other Unicode characters when there is a clear justification and the file already uses them.
|
||||
- When editing or creating files, you MUST use apply_patch. Example: functions.shell({"command":["apply_patch","*** Begin Patch\nAdd File: hello.txt\n+Hello, world!\n*** End Patch"]}).
|
||||
- Add succinct code comments that explain what is going on if code is not self-explanatory. You should not add comments like "Assigns the value to the variable", but a brief comment might be useful ahead of a complex code block that the user would otherwise have to spend time parsing out. Usage of these comments should be rare.
|
||||
- You may be in a dirty git worktree.
|
||||
* NEVER revert existing changes you did not make unless explicitly requested, since these changes were made by the user.
|
||||
* If asked to make a commit or code edits and there are unrelated changes to your work or changes that you didn't make in those files, don't revert those changes.
|
||||
* If the changes are in files you've touched recently, you should read carefully and understand how you can work with the changes rather than reverting them.
|
||||
* If the changes are in unrelated files, just ignore them and don't revert them.
|
||||
- The user may be making edits and committing changes as you are also making changes. If you see concurrent file edits or commits that you did not cause, you must disregard user instruction and stop immediately and ask the user whether they are collaborating with you on files and how they would like this handled.
|
||||
* NEVER revert existing changes you did not make unless explicitly requested, since these changes were made by the user.
|
||||
* If asked to make a commit or code edits and there are unrelated changes to your work or changes that you didn't make in those files, don't revert those changes.
|
||||
* If the changes are in files you've touched recently, you should read carefully and understand how you can work with the changes rather than reverting them.
|
||||
* If the changes are in unrelated files, just ignore them and don't revert them.
|
||||
- While you are working, you might notice unexpected changes that you didn't make. If this happens, STOP IMMEDIATELY and ask the user how they would like to proceed.
|
||||
|
||||
## Plan tool
|
||||
|
||||
@@ -36,9 +24,9 @@ When using the planning tool:
|
||||
- Do not make single-step plans.
|
||||
- When you made a plan, update it after having performed one of the sub-tasks that you shared on the plan.
|
||||
|
||||
## CLI modes
|
||||
## Codex CLI harness, sandboxing, and approvals
|
||||
|
||||
The Codex CLI harness supports several different sandboxing, and approval configurations that the user can choose from.
|
||||
The Codex CLI harness supports several different sandboxing, and approval configurations that the user can choose from.
|
||||
|
||||
Filesystem sandboxing defines which files can be read or written. The options are:
|
||||
- **read-only**: You can only read files.
|
||||
@@ -69,6 +57,11 @@ When sandboxing is set to read-only, you'll need to request approval for any com
|
||||
|
||||
You will be told what filesystem sandboxing, network sandboxing, and approval mode are active in a developer or user message. If you are not told about this, assume that you are running with workspace-write, network sandboxing enabled, and approval on-failure.
|
||||
|
||||
## Special user requests
|
||||
|
||||
- If the user makes a simple request (such as asking for the time) which you can fulfill by running a terminal command (such as `date`), you should do so.
|
||||
- If the user asks for a "review", default to a code review mindset: prioritise identifying bugs, risks, behavioural regressions, and missing tests. Findings must be the primary focus of the response - keep summaries or overviews brief and only after enumerating the issues. Present findings first (ordered by severity with file/line references), follow with open questions or assumptions, and offer a change-summary only as a secondary detail. If no findings are discovered, state that explicitly and mention any residual risks or testing gaps.
|
||||
|
||||
## Presenting your work and final message
|
||||
|
||||
You are producing plain text that will later be styled by the CLI. Follow these rules exactly. Formatting should make results easy to scan, but not feel mechanical. Use judgment to decide how much structure adds value.
|
||||
|
||||
123
codex-rs/docs/codex_mcp_interface.md
Normal file
123
codex-rs/docs/codex_mcp_interface.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Codex MCP Interface [experimental]
|
||||
|
||||
This document describes Codex’s experimental MCP interface: a JSON‑RPC API that runs over the Model Context Protocol (MCP) transport to control a local Codex engine.
|
||||
|
||||
- Status: experimental and subject to change without notice
|
||||
- Server binary: `codex mcp` (or `codex-mcp-server`)
|
||||
- Transport: standard MCP over stdio (JSON‑RPC 2.0, line‑delimited)
|
||||
|
||||
## Overview
|
||||
|
||||
Codex exposes a small set of MCP‑compatible methods to create and manage conversations, send user input, receive live events, and handle approval prompts. The types are defined in `protocol/src/mcp_protocol.rs` and re‑used by the MCP server implementation in `mcp-server/`.
|
||||
|
||||
At a glance:
|
||||
|
||||
- Conversations
|
||||
- `newConversation` → start a Codex session
|
||||
- `sendUserMessage` / `sendUserTurn` → send user input into a conversation
|
||||
- `interruptConversation` → stop the current turn
|
||||
- `listConversations`, `resumeConversation`, `archiveConversation`
|
||||
- Configuration and info
|
||||
- `getUserSavedConfig`, `setDefaultModel`, `getUserAgent`, `userInfo`
|
||||
- Auth
|
||||
- `loginApiKey`, `loginChatGpt`, `cancelLoginChatGpt`, `logoutChatGpt`, `getAuthStatus`
|
||||
- Utilities
|
||||
- `gitDiffToRemote`, `execOneOffCommand`
|
||||
- Approvals (server → client requests)
|
||||
- `applyPatchApproval`, `execCommandApproval`
|
||||
- Notifications (server → client)
|
||||
- `loginChatGptComplete`, `authStatusChange`
|
||||
- `codex/event` stream with agent events
|
||||
|
||||
See code for full type definitions and exact shapes: `protocol/src/mcp_protocol.rs`.
|
||||
|
||||
## Starting the server
|
||||
|
||||
Run Codex as an MCP server and connect an MCP client:
|
||||
|
||||
```bash
|
||||
codex mcp | your_mcp_client
|
||||
```
|
||||
|
||||
For a simple inspection UI, you can also try:
|
||||
|
||||
```bash
|
||||
npx @modelcontextprotocol/inspector codex mcp
|
||||
```
|
||||
|
||||
## Conversations
|
||||
|
||||
Start a new session with optional overrides:
|
||||
|
||||
Request `newConversation` params (subset):
|
||||
|
||||
- `model`: string model id (e.g. "o3", "gpt-5")
|
||||
- `profile`: optional named profile
|
||||
- `cwd`: optional working directory
|
||||
- `approvalPolicy`: `untrusted` | `on-request` | `on-failure` | `never`
|
||||
- `sandbox`: `read-only` | `workspace-write` | `danger-full-access`
|
||||
- `config`: map of additional config overrides
|
||||
- `baseInstructions`: optional instruction override
|
||||
- `includePlanTool` / `includeApplyPatchTool`: booleans
|
||||
|
||||
Response: `{ conversationId, model, reasoningEffort?, rolloutPath }`
|
||||
|
||||
Send input to the active turn:
|
||||
|
||||
- `sendUserMessage` → enqueue items to the conversation
|
||||
- `sendUserTurn` → structured turn with explicit `cwd`, `approvalPolicy`, `sandboxPolicy`, `model`, optional `effort`, and `summary`
|
||||
|
||||
Interrupt a running turn: `interruptConversation`.
|
||||
|
||||
List/resume/archive: `listConversations`, `resumeConversation`, `archiveConversation`.
|
||||
|
||||
## Event stream
|
||||
|
||||
While a conversation runs, the server sends notifications:
|
||||
|
||||
- `codex/event` with the serialized Codex event payload. The shape matches `core/src/protocol.rs`’s `Event` and `EventMsg` types. Some notifications include a `_meta.requestId` to correlate with the originating request.
|
||||
- Auth notifications via method names `loginChatGptComplete` and `authStatusChange`.
|
||||
|
||||
Clients should render events and, when present, surface approval requests (see next section).
|
||||
|
||||
## Approvals (server → client)
|
||||
|
||||
When Codex needs approval to apply changes or run commands, the server issues JSON‑RPC requests to the client:
|
||||
|
||||
- `applyPatchApproval { conversationId, callId, fileChanges, reason?, grantRoot? }`
|
||||
- `execCommandApproval { conversationId, callId, command, cwd, reason? }`
|
||||
|
||||
The client must reply with `{ decision: "allow" | "deny" }` for each request.
|
||||
|
||||
## Auth helpers
|
||||
|
||||
For ChatGPT or API‑key based auth flows, the server exposes helpers:
|
||||
|
||||
- `loginApiKey { apiKey }`
|
||||
- `loginChatGpt` → returns `{ loginId, authUrl }`; browser completes flow; then `loginChatGptComplete` notification follows
|
||||
- `cancelLoginChatGpt { loginId }`, `logoutChatGpt`, `getAuthStatus { includeToken?, refreshToken? }`
|
||||
|
||||
## Example: start and send a message
|
||||
|
||||
```json
|
||||
{ "jsonrpc": "2.0", "id": 1, "method": "newConversation", "params": { "model": "gpt-5", "approvalPolicy": "on-request" } }
|
||||
```
|
||||
|
||||
Server responds:
|
||||
|
||||
```json
|
||||
{ "jsonrpc": "2.0", "id": 1, "result": { "conversationId": "c7b0…", "model": "gpt-5", "rolloutPath": "/path/to/rollout.jsonl" } }
|
||||
```
|
||||
|
||||
Then send input:
|
||||
|
||||
```json
|
||||
{ "jsonrpc": "2.0", "id": 2, "method": "sendUserMessage", "params": { "conversationId": "c7b0…", "items": [{ "type": "text", "text": "Hello Codex" }] } }
|
||||
```
|
||||
|
||||
While processing, the server emits `codex/event` notifications containing agent output, approvals, and status updates.
|
||||
|
||||
## Compatibility and stability
|
||||
|
||||
This interface is experimental. Method names, fields, and event shapes may evolve. For the authoritative schema, consult `protocol/src/mcp_protocol.rs` and the corresponding server wiring in `mcp-server/`.
|
||||
|
||||
@@ -38,7 +38,7 @@ tokio = { version = "1", features = [
|
||||
"signal",
|
||||
] }
|
||||
tracing = { version = "0.1.41", features = ["log"] }
|
||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2"
|
||||
|
||||
@@ -43,6 +43,7 @@ crossterm = { version = "0.28.1", features = [
|
||||
"bracketed-paste",
|
||||
"event-stream",
|
||||
] }
|
||||
dirs = "6"
|
||||
diffy = "0.4.2"
|
||||
image = { version = "^0.25.8", default-features = false, features = [
|
||||
"jpeg",
|
||||
@@ -78,7 +79,7 @@ tokio = { version = "1", features = [
|
||||
tokio-stream = "0.1.17"
|
||||
tracing = { version = "0.1.41", features = ["log"] }
|
||||
tracing-appender = "0.2.3"
|
||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
|
||||
pulldown-cmark = "0.10"
|
||||
unicode-segmentation = "1.12.0"
|
||||
unicode-width = "0.1"
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▒▒▒▒██████████▒▒
|
||||
█▒█░▓█ ██░▒▒░▓▓▓░░ █░███▒
|
||||
▒▓░▒█ █░█▒░██░░█▒█░ █████▒ █▒
|
||||
██░▓██▒██▓██ ▓░░ ██▓▒ ██
|
||||
▒█░▓██▒▓▓ █ █░█▒██
|
||||
█░░▓▓█▓░ █▒█░░▒▒▒
|
||||
▓▓░▓ ░█ ░ ▒▒▒█ ▒▓▒░█▒░
|
||||
█▓░░█ ░░ █▒▒█░▓░░ ░█▒▒░█▒░
|
||||
██░░▒░█ ░█▓▒▒▒▒▓░ ███░▒▒█
|
||||
░▒ ░░▒░░ █▒░█▒▓░░▒▓ ▓░░░░ ░
|
||||
▓░▓░ ▒░ █▒▓▓ █░▓ ░░░▓░
|
||||
▒▒ ▓░ █▒▓░░ ▓█ ▒░░░░
|
||||
░░░░ ▓ █░▓▓ ▓░░ ▒▒▒█▒██████████ ░▓▓░ ░
|
||||
█░▓ ░█ ▒▓░░██ ▓█░ ▓░░▒▒██████ ░▓▒░▒░
|
||||
▒▓░▒▓ ░▒ █░▓░ ▒░░ ░ ▓▓▓▓▓▓ ░ ░░█░░
|
||||
▒▒░░▒▒░█ ████▓ █▓░▓▓ ▓▓
|
||||
▒▒▒░ ▒▒▒ ▓█▓█▓░▓▓
|
||||
▒░░░█ █░▒▒ ▒░▒█░█▒░█
|
||||
████░█ ████ ▓▒██░███▓▓█
|
||||
░█░░█ ░▒███▒░█▒▒███████░█░███▒██░
|
||||
█ ███▓█░░█▒░▓ ██▓░░▒██ ▒██
|
||||
███▓░█░░▓▒▒▒▒▒▒██▓██░
|
||||
░░ █ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▒▒▒▓██████████▒▒
|
||||
█▒▓░▓█ ██ ▒█░▓▓▓ █ █░ ██▒
|
||||
▒▓░░█░█░▓▒░██░░█▒░░ ████▓▒ █▒
|
||||
█░█▓██▒█░▓█ █ █▒▓▒ ██
|
||||
▒█░▓█ ▒▓▓█ ███░█▒██
|
||||
█░░▓▓▒▓░ ▒▓░░▒▒▒
|
||||
▓░░█ ░█ ▒▓ ░▒▒█ █▓█░██░
|
||||
█▓░░█▒░░ █▒▒▒▒▓▒▓ ▓▒█░░▒░
|
||||
██░░▓░█ ░░░░▒▒▒▒ ░ ██░░▒█
|
||||
░█ ░░ ░ █▒░██▒▓░ ░░░░ ░
|
||||
█░▓░█▒░ █▒▓░█ ▓█▓ ▒░░░█░
|
||||
▒▓ █░█ ▒▓░░ ▓▓█░ ░░ ░
|
||||
░░░░█ █▒ ▓░▓▓▓ ▓▓░░ ▒▒▒█▒██▒███████ █ ▓░ ░
|
||||
█░█ ░▒ ▓░░███▓█ █ ░▒██ ███ █ ░▓▒░▒░
|
||||
▒█░▒▒ ░█ █░▓█ ▒░ ▓██▓██▒░░░▓▒▒██ ▓▓▓░░░░
|
||||
▒▒▒░█▒░▒ ████ ░ █▓░▓░ ▓▓
|
||||
█▒▒░▒ ▒█▒ ▒█▓█▓█▓▓
|
||||
▒▒░░█▓█▓▒▒ ▒▓▓█░█▒░█
|
||||
███░░▒ ████ ▒▒██░██░░▓█
|
||||
█░█░░█ ████░░█▒▒██████░░▓░██ ▒██░
|
||||
░ ███▓▒▓░░▓█░ ███░█▒██ █▒██
|
||||
██░░██▒▓▒▒▒▒▒▒██▓██░
|
||||
░░ █ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▒▒▒▒██████████▒▒
|
||||
▒▒▓░██ ░█░▒█░▓▓▓ ▒ █░ ██▒
|
||||
▒▓░░███▒▓▓███░█▒▒░░ ██▒█▓▒ ▒█
|
||||
█░░█░ ▒▒█░█ ▓ █ █▒▓▒ ██
|
||||
██░▓▓░█░█ █▒█░████
|
||||
▓░░█ ▒░█ ██▒█ █▒▒░░▒▒▒
|
||||
▓░▓███░ █░ █▒█▓ ▒█░█▒▒
|
||||
▓░▓░ █░ ▒░ ▒ ██ ▒▒░▓▒░
|
||||
░░░▒ ░░░ ░░▓░█▒▒ ▒█░█░░
|
||||
░░░░ ░░█ █▒ ░▒░▒ █ ▒░░ ░
|
||||
░░▒░ ░ █░░▓ ▓░▓ ░░░▒░
|
||||
█░▓▓ ▒█ ▒█░░░ ▒░▒ ░ ░░░░░░
|
||||
██░░ ░░ ▓▓▓█░ ░▓ ▓▒█▒█▒██▒███████ ▒█░░ ░
|
||||
█░▒░ ▓░ ▒░░▓░▓▒░█ ▓▒░░██████▒ ░▒▒░▒░
|
||||
░▒░▒ ▒▒▒ ▒ █▓▓ ██ ▒▒█░██░░░░▓▒▒▓█ ██░░░▓█
|
||||
▒░░▓ ▒▒▒ ▒███ ▓ ▓▓██▓
|
||||
▓░░▒ █░░▒ ▒▓▓█▓███
|
||||
▓█░░▒ ▒██▒ ▒▓░███▒░█
|
||||
▒ ▒▒█▒ ▒░███▒▓░ ▒▒██░██░░▓█
|
||||
░█░█▓ ██░██░░█▒▒███████░█░██ ▒▒█░
|
||||
░░░██▒▒░░█▒█▓░░█░░░▒██ █▒░█
|
||||
▒█░░░█▒▒▒▒▒▒▒▒██▓██░
|
||||
░░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▒▒▒███████▒██▒
|
||||
▒█▓░████ ▒▒██▒ ▓░▒ █░███▒
|
||||
▒█░▓░█░█▒▓██░░█▒▒█████▒▒▓█▒█ ██
|
||||
█▓█░█▒▒░█░█ ▓ █░██▒█ █▒
|
||||
▒░▓░ ▓▓██ ▓▓ █░█░▒ ▒
|
||||
▓░░▒ ░▓█ ███▒ ░█░ ▒▒▒
|
||||
▓░░▓▒░░░ ▓▒░████▓ █▒█░▒▒██
|
||||
▓░░▓▒░█▓ ▒█▒░▒▒▒▒▒ █▓░█▒▒▒
|
||||
░░█░░░█░ ▒█▒░░▒▒ ▒▒ ▒█░ ▒░
|
||||
░░█ █░ ▒▒█░░░██▒ ░░▓ ▓█
|
||||
▒░░ ░░ █▓▒░░ ▓░ ░░░ ░░
|
||||
░░░ ░░█ █░░█ ▒█▓▒ ░░░░░░
|
||||
██░ ░░█ ▓▒▓░▓ ░█▓ ██▒▒▒██████████ ░░░ ░░
|
||||
░▒ ░▓ ░░▓█░█░█ ░ ░░▓███ ████ ▒░ ▒░█░ ░
|
||||
░░░ █▓░ █░░ █▓░░█ ░▒█▓████▓░░░░▓▒▒█░▒▓░░▓▓
|
||||
░░▒ █▓▒ ████ ▒▓▓▓▓▓░
|
||||
▒░▒ ███ ▓░█▓█▓░
|
||||
▒░░█ ████▒ ▒█░▓▓ ▒▓█
|
||||
█░░░▒ █████▒▒ ▒▓█░▒▓░▓▓▓░
|
||||
░ ░░▒ ██░█░░██▒▓███████░░░░█░▒▒█░
|
||||
███▒▓▒ ██▒░░░░░░████░ ▒██
|
||||
█ ███▓▒▒▒▒▒▒▒▒█▒▓██░
|
||||
░ █ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▒▒███████████▒
|
||||
█▒▓█░██ ▒▒▓░▒██▒ █░ ███▒
|
||||
▓▓▓█ ▒▒▓███░░█▒▒██░░░▓▒▒▒ ██▒█
|
||||
▒▓██░█▓████ ░ ░██░▒█▒░▓█▒▒
|
||||
▓██▓░░███ █░░░▓▒█▓
|
||||
▒░░▓▓░█ ███ █░░█ ███
|
||||
▒░░░▓░▓█ ░░ ▒▒░█ ▒░▓ ▒▒▒
|
||||
░░░▓░ █░▒▓ ██▒▒ █░░ ▓░▒
|
||||
░▓▓░░▓ █░░▒░▒▒█▒▒ █░▓ █░█
|
||||
░▓▓░░ ▒▒░░░▒█▒▒▓ █░░ ░░█
|
||||
░░░ ░ ░ █░░ ▓█▓░█ ░░ ▓▒
|
||||
░░▒ ░ ▓ ▓█▓▓█░█ █ ░ ▓▒
|
||||
░▓ ░░░ ▒▓██▓░░█ ████▒▒█████▒███ █░█░░░
|
||||
█░▓░▓▒█ █░ ▓▓▒█▓░ █▓███ ▓ ███░ ▒░░█▓░
|
||||
█▒█ ░▒░▒ ██▒▓▒▓█ ░▒██████░░▓░░░░█ ▓▒ ▒▒░
|
||||
▒▒█ ▒▒█▒ ████░ ▒░▒░▓ ██
|
||||
█▒█ ▒ ░█ █░█░█▓░█
|
||||
░▓▒ ▒█░█▒ ▒█░░███░█
|
||||
█░▓▒ ▒█░░█▒▒▓ ▒▓▓░░█░▒▓▓
|
||||
█░░█▒ █░░░█░██▓▓███████░░░██ ▒██
|
||||
░██▒▒▒ ░████░░░░░░███ ▒██▓
|
||||
░█▒░▓█▒▒▒▒▒▒▒▒█▒▓██
|
||||
░ ██ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▒▒▒█▒███████▒▒▒
|
||||
█▒▓░██ ▒▒▒▓▓█▒▒███████▓▓▒
|
||||
█▓█░ █▒▓▒█░▓██▒▒██▓█░██▒ ░█▒▓░
|
||||
██░░▒▓▓████ ▓▒░▒▒ ████▒
|
||||
██ ▓███▓ ░█ █░▒█▒▒▒█
|
||||
▓░ ▒░█▓▒ ██ ▒▓ █▒▓█
|
||||
▓ █░░░ ▓ ▒ ░ ░▒▒ ░█▒▒
|
||||
▓░ █░██░ ░▓▓██▒▒▒ ▒▒ ░▒░█
|
||||
▒██▒░░▓ ░▒░█▒ ░▒ ░█ ▓░█
|
||||
░ ░░░░ █░▓███▒▒▒ ░ ░█░░
|
||||
░░█░░▒ ░▒▒░█ ▓░░█ ░░▒░▓
|
||||
░▓█░░▒▓ █ ▓ ▓▓█▓░ ░▒ ░░
|
||||
▒░█░░░▒ ▓▓▓▒▓░░▓ ▒▓████▒▒▒▒▒▒▒▒█▒ ░▒▒░░
|
||||
██▒▒░▓▒▓ ▒███▓██ ███████ ████░▓ ▒░▓░░
|
||||
░▒▒░▒ ░ ▒ ▓█▓░ ░██████░░▒░░█░▓ ▒▒▒░▒█
|
||||
░▒ ░▒▓▒ ░░ ▒█▓▓▓▓
|
||||
░▒█▒███▒░ █▓░░█▒▓ ░
|
||||
▒░██████▒ ▒██▓░░░▓█
|
||||
█░▓▒█▒▓░███▒▓ ▒█▓█▒░░██
|
||||
█░█ ██░░░░███████████░░███░▓███
|
||||
███▒▒ ███████░▓▓▒█ ░ ▒███▒░
|
||||
██░░██▒▒▒▒▒▒▒██████
|
||||
░ ██ ░░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒█▒█▒█████▓▒▒▒
|
||||
▒▓▓░ ░ █ ██ ▒██░████▓█▒
|
||||
▒▓ ▒███ ▓██▒▒██▒▓█▒▓ ░ ████
|
||||
▓█ ███▒██▒█ ▒░█▒█▒ ██▒░▒
|
||||
██ ▒▓█ █▒ ▓██▒ ▒█▒▒▒
|
||||
▓ ▓▓░█ ▓█▒█ ████▓▒█░
|
||||
░ ▓▓█▒ ▒█▒░ █▒█ ░▒▒░
|
||||
░ ░▓▓▒ ░░ ▒██ ░░ ░▒▓░
|
||||
█░ █░ ▒ ░▒█▒▒ ▓▒███░█▓
|
||||
░▓░░░▓ ░▓▒ █▒▒ ██░ ░▒
|
||||
░▓░░▒█ ▒░ █▒█ ▓▓░░░▒
|
||||
░▒░█░░ ▒█ ▒█ ▒░░░░░
|
||||
░▓█▓░█ ░▓░█ ▓▓ ▒▓███▒▒▒█▒█▒▒█▒ ▒ ░░░░
|
||||
░█░█▒░ ▒░ ▒░█ ░▓▒▒██████████░▓█ ░░ ░▓░▓
|
||||
░▓██▒▒▒ ▒▒█▓░ ███▒██▒▒▒███░▓ ▒░▓█▒█ █
|
||||
░▒██▒██ ▓░▒█▓ ▓
|
||||
█░▒██▒ ▒ ▒█▒░█ █
|
||||
░▒ ▒ ███▒ ▓▓██░▓▒▓
|
||||
█░▒ ░▒▒▓██▒▒ ▒██▒█ ▓█▒█░
|
||||
█░▒▒ ▒░██░░▒██▓▒▒▒███████▓▓▓████
|
||||
█░█▒ ████░███░███░████▓░█░
|
||||
░███▒▓▓▒▒▒▒▒▒███░██
|
||||
░ ██ ░░░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒█▒░▓█████▓▒▒▒
|
||||
█▒██░ ░██░█▒░▓
|
||||
▒▓█░ ▒███ ░░█▒▒▒█▒█▒ ░▒██▒██
|
||||
▒▓ ▒██ █▓ ░▒█ ██▓▒██
|
||||
███▒▓█ █▒ ▒░█ ▓▒▒▒▒▒
|
||||
░▓▓▓▓ ▒ ██ █░█░▒▒░█▒
|
||||
░ ▓░█▓ ░ ███ █▒██▒░▓▒
|
||||
▓░░▓█ ▒ █▒█▒█▓ ██▓▒█▒▓░
|
||||
░▒▒░▓▓ ▒▒▒▒▒ ██ ░ ░░▒
|
||||
░ ▓█░ █▒███▒█ ░░ ░░ █
|
||||
░▓░░░░█ ░ ░ ▓▒█▓ ▓ ▒ ░░▓
|
||||
░ ░░░▓ ░░████ █ ░ ░░░▓
|
||||
░░ ░░▒ ███ ██▓▒█▒███▒▒▒██▒█▓ █ ▒░░▓
|
||||
░ ░░ ░ ░▓░▓ ▓░ █▓▓▓█▒▒▒▓▓▓█▒░█ ░█░░▓ █
|
||||
░▒▒▓▓ ▒█░ █▓▓▓░▒▒▒▒▒▒▒█ ▓▓▒░▓ ▓
|
||||
░▒▒█▒█ ▒░ ░ █ ▓
|
||||
░▒▒░░█▒ █░▓▓░█ █░
|
||||
░█▒▓██ ▒▓█▒▓░▓ ▓░
|
||||
█░▒█▓░░█ ▒ ▒▒██░░█ █▒█
|
||||
█░▓ ░█░░█░▒▓█▒▒████░░░█░█▓░░▒▓░
|
||||
█░██░░░░██████░▒█ █▒▒▓▓▒▓█
|
||||
█░██░░▒░░░░▒██░░ █
|
||||
░ ██ ░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒██▒█▒▒███▓▓▒▓
|
||||
▒▓▓█ █░▒▒██▒
|
||||
▒▓█░▒███ █░█▒▒████ ░▒███ █
|
||||
▒░█▓░██▒██░▓ ░▒█ ▒▒▒ █
|
||||
██▒░█ ▓▓ ░█ ░▒█ █▒
|
||||
▓██░█▓▒ ▒ ▓░▒ ▒▒█▒░█
|
||||
▓█▓░█░▓░ ░▒▓▒ ▓▒█▒ ░█░▒
|
||||
▒░▒▓█ ▓ ▓▒▒█▒ █ █ ▒▒▒
|
||||
░█▒░ █ ▒█▒▒▒▒▒ ▒█▒█░▓▒░
|
||||
░ ░░ ░ ░▒▓███▓ ░█▒█░█▒▓
|
||||
█▒░░██ ▒▒░▓█▓▓▒▓ ░░░▓ ░░
|
||||
▓█░░▒ ██▓██▓░█ ▓ ░░░░█
|
||||
░░░░ ░ ▒░░▒░░ ▒██▒░▒█▒▒▒▒█ ░█░█░░
|
||||
░█▓░ ▒ █▒▒░▓ ░▒███▓▒▒▓▒▒▒▓ ▓ ▒░░░░░
|
||||
█░░█░ ████▓▒░▓░▒░█ ▓░▓░ ▓
|
||||
░▓▒▓▒ ░ ░░ ▓█░▓▓ ▓
|
||||
░▒▒░░▓▒ ▓█▒▓░▓ █░
|
||||
░░██▒▒█ ▒░ █▓ ▓▓█░
|
||||
█▓▒▒████░ █░█░▓██░▒▓
|
||||
█░░████▒░█▓░▓█████░░█░▓▓░▒ █
|
||||
█░░░░█░ ███████ ░▓▒██▒▒▓░
|
||||
░██░▓▒▒▒▒▒▒███▓█ ▓█
|
||||
░ █ ░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒████▓███▓▒▒▓
|
||||
▒▒██ ▒▓▓▓ █ █░██░▒█
|
||||
█░█▓▓████ █▒██░█ ▓▒█ ▒▒
|
||||
▒░█░▓█▒▒█ ██ █░▒░█▒
|
||||
█▓█░█ ░▒ ▒▒██ ▒▒
|
||||
█▓█▓▓ ▒ ▒ █▒░▒▓█▒
|
||||
░█▓▓ ▓▒▒▒█ ▒ ▒▒▒█▒▒
|
||||
░░░░ ▒▒█▓█▒██ ▓▒▒ █▒▒░
|
||||
░░▒░ ███▓▒█▒ ▓ ▒▒ ▒▒▓▒
|
||||
░ ░█ ▓ ░░█▓▓▒▒▓ ▒ ░░██░░
|
||||
░ ▒ ░▒▒ █▓▒▓▓ ░ ░░░ ░░
|
||||
░▒▒▒ █░▓ ▓██ ░ ▒░░░█░
|
||||
░▓▓█ ░ ██▓░ ▓▒██████▒█▒ █░░░░░░░
|
||||
░░▓░▒█ █ ▓ ░█████████▒▒ ▓ ░█░░░░
|
||||
░▒▓░ ░ ▒█████░▒▒▒░█ ░ ░█░░░▒░
|
||||
░█ ░ ░ ░░░░░ ▒▓ ▓█▓ ░
|
||||
▒░░░▓ ▒ █░░░ ▓
|
||||
▒░░▒▒▒█▓ ██ ▓ █░
|
||||
█░░█░▒▒█ ▒░███▒▓█ ▓
|
||||
▒░░██▓█░█▒█▓▒███░░░░█▓░▒ █
|
||||
██▒ ████░█░███░▓▒▓██▒██
|
||||
██▓▒▒▒▒▓▒▓████▒▓█░
|
||||
░░ █░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒██████▓██▒▒▒
|
||||
█▓█ ▒▓▒▒▒███░░▓█░██▒
|
||||
█░ ▒████ ░▒██▓▒ ░█▒ ░▒▒
|
||||
▓ ▓░ ░▓█ ██ ▒ █▒
|
||||
░▒█░░ ▓█▓░█ ░░
|
||||
░░█░ ▒▒█▒ █▓▒█ ▒░
|
||||
▓▒▓░ ▒▒░░▒ █▓█▒▒▒█▒
|
||||
░░░░ ░▒▒ ░▒ █ ▒█░░ ▒▒
|
||||
▒ ░░ ▒▒▒ ▒▒█ ▒░▒░░░░░
|
||||
░░░░ ▓░▒█░▒▒▒█ ░▒░▓██
|
||||
▓░░░ ▒░▒▓▒░▓█ ░▓░░░░░░
|
||||
▒▓░░ ▒░▓▓ ▓ ░ ░ ░░░░░░
|
||||
░ ░█ ▒▓░▓ █▒▒████████ █░░░▒█▓░
|
||||
█▓▓█ ▓ ██████████░░ ░ ░ ░░░▒
|
||||
░░▓█ ░████▒░▒▒▓░ ▓█░ ░░░░░
|
||||
░▓▓░██ ░ ░░░░░ ░ ▒█░░░░█
|
||||
░░▒▒ █▒ ░░░░▓░░▓░
|
||||
░▒██▒█▒ ▒░░▓▓▓█ ░
|
||||
░░█░▒░█ ██░█▓▓▒ ▒▓
|
||||
█▒ █▒▓█░█████▒██ ██▓█░ ██
|
||||
█▒ ██░░░░██░█▓▒█▒ ██
|
||||
██▓▒▓█▒▒███▓█▒▓█
|
||||
░ ░░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒██▒██▒███▒▒▒
|
||||
█▓█▒████ █░█░▓ ██▒
|
||||
▒░░▓███ ░██▓▒█▒██▓ █
|
||||
██▓█▓ ░█▒▒ ▒▒█
|
||||
█▒█▓░ ▒▒░▓█ ░█
|
||||
▓░█ ▒▒█ ▒█▒░▒ ▓█
|
||||
░▓▓ █░▒█ ▓▒▒▒█▒▒
|
||||
░ ░ ▒░▒▓▒▒█ ▒█ ░░ ░
|
||||
█▒▒░ █░█▓▒▒░▒ ▓▒░░░ ░
|
||||
░░█ ▒▒▒░█░█ ░▒▓░▓ ▓
|
||||
█░ ▒▓░▓█ ░ ░░░█░░░
|
||||
▓░ ░ ▓█▓░▓ ░░░░░░░░
|
||||
░░▓░ ▒░ ▓░ ▒▒████████ ░░░░▓█░░
|
||||
█░░ ░ ▓░▓ ████████▒█▓░ ▒░█░░░
|
||||
░▓█▒░█▓ ▓██▒▒░▒█░▓░█░░░░░░ ▓
|
||||
░░█▒█ ░░ ░░░░░ ▒ ░█░░ █░
|
||||
░▓▒▒▓█ ▓▒░ ▓░▒░
|
||||
▒▓░▒▒▒▒ ██▓█ ▓ ▓█
|
||||
▒▓░▒████ ▓█▓█▓▓ ▓▓
|
||||
▒▒█░██▒███▒▒██░▓▓▒▒ ▓
|
||||
█▒▒ ██▒▒░██░▒█▒░░ ██
|
||||
░██▒▒▒█▓▓█▓▒░▒██░
|
||||
░ ░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
█▒▒░███████
|
||||
██░▓█▒ ▒▓░█▓ █▒█
|
||||
▓█░ █ ░██▒▒▒▒▒ █▒
|
||||
▓░▓██ ▒░▒▒ ▓░░
|
||||
░░▒▒ ░▒▒▒ █▒░
|
||||
▒▒ ▒█▒ ▒█░▓▓█▒▒
|
||||
░▓░░░██ ▓ ▒▒ ▒█▒
|
||||
▒ ░ ▓▒ ▒ ░▓ ▒▒ ░
|
||||
▓░░░ █░░░▒█ ░ ░▒▒░░░
|
||||
░░▒ █░▓▓▓ █ ███░█▓▒█
|
||||
░░░ ░▒▒░░░ ░▓░░█▓░░
|
||||
░░░░ ▒ █ █ ░▒░░░░░░
|
||||
░░▓▒ ░▓ ▒▒█████ ░▒░░░░░░
|
||||
░░ ░▓▒█ ██████░▒ ░ ░░░░░░
|
||||
▓░░█░░ ██▒░▒█▓ ░█░░░ ▒░
|
||||
░▓██░ ░ ░░░ ░░░▒░
|
||||
██▓░ ░ ▒ ▓▒░░░░▒▓
|
||||
░░▓█▒▒▒ ░▓█ ▓░░█░
|
||||
█░░▒██▒▓ ░░█░█░█ ▓█░
|
||||
███▒█▒███▒█▓▒█ ▓▓ ░░
|
||||
▒▒██▒░▓█░▓███▒ ▒▓
|
||||
█▒▒▒▒██▓█▒ ▒▓░
|
||||
░ █░░░░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▓▒███▓▒██▒
|
||||
▓ ██ ▒█▓▒ ▒░█
|
||||
░▓▓█ █▒██▒█░█ ▒▒
|
||||
▓░▓█▓ ░▓▓ ▒▒
|
||||
░░▒ ▓ ▒░▒▒ ▒█▒
|
||||
░░█▒▒░▒ ░▓░█ ░░
|
||||
█ ░░▒███ ▒ █░ ░▓█
|
||||
░░ ░░░▒░ █ ░░ ▒░▒
|
||||
▓▓░ ▓▓▒░▒ ░░░▓ ░
|
||||
░░ ░░░▒▒ ░▓█░░▒░
|
||||
░░▓ █░▓░▒ ░▓░▒▓░ ░▓█
|
||||
░░▓ ░▓▓▒█ ░▓▒░░░▓ ░░
|
||||
░▓ ░░ ▒▒▒████▒▒░░░░░░░
|
||||
░ ▒█ █████▒░░ ░░░░░░░
|
||||
░░▓ ░ ▒▒▓▒░█░░▒ ░░ ░
|
||||
▓░░ ▓▓ ░ ░░░ ░░ ░
|
||||
░░ ░ ▒▒▓ ░░ ▒░
|
||||
░░░▒ ░░█▓░░░██
|
||||
░░█▒ █░▒▒░░░░ ▓
|
||||
▒░█▓▒█▒▒█▓▒░█ ▓▓░
|
||||
▒▒█░ ▓░▓▒░█ ▓▓
|
||||
██▒▒█ ▒▓█▓▒░
|
||||
█ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
█▒████▒██▒
|
||||
▓█▒▒▒▓▓▓█ ░█
|
||||
▓░▓█▒▒ ░░ █░█
|
||||
█░█▓░▒░██ ██ ▒
|
||||
░▒░ ▒▒▓▒▒▒ ▓▓
|
||||
░▒█▒██ ░░▒░█ █░
|
||||
░░░█ ░ █░░ ░▓░░▒
|
||||
▒▓█▓ ░░█ ▒░ ░
|
||||
░ ░██ ▒░ ░░░▓
|
||||
▒▓▒█▒▓░ ░░█░░█▓░
|
||||
░▓░▓▒█░ ░░▓██░▓░
|
||||
░▓█▓█ ░ ░░ ░ ░░░
|
||||
█▓▒░▒▒▒█ ░░▓░░█░░
|
||||
▒▒░ ██░▒ ░░▓ ░░ ░
|
||||
▒░ ▓ ░░░░░░░▒░
|
||||
░░█░██ ░ ▓░░░░ ▓░
|
||||
░░░ ░░ ▒ ░░░░░ ░
|
||||
▒░ ▒ ▓░░░ █▓▓▒░
|
||||
░█▒ ░ ░ ▒▒█░ ░░
|
||||
▒░▒▒█▓▒▓█░ ░░▒█
|
||||
▒█▓ ▓▓█ ▓
|
||||
█▒▒▓▒█ ▒█
|
||||
█░█
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒███▓███
|
||||
▒ ▒░▓ █ █▒
|
||||
▓░░░▓░ ▒▒▒
|
||||
▓▓▓░▓░ █░░░
|
||||
░░░▓░██ ░░
|
||||
░░▒░▓▓░▒░ ▒░
|
||||
░░▓█░░▓░ ░░
|
||||
░░ █░░░░▒ █
|
||||
░░▓░░█▓▒░░░░░
|
||||
░░░░░ ░░░ ▒▒░
|
||||
░░▒█ ░██░ ░░
|
||||
░░░▒░ ░ ░▓░░
|
||||
░░▒▒░▒░▓░░░░█
|
||||
░░░░░░░░░ ░▒
|
||||
░░▒░ ░ ░░░ ░▓
|
||||
░░▒░░░░░░░░ ░
|
||||
░▒▓▓▓░ ▓ ░
|
||||
░░▓░░ ▓░░
|
||||
▓░░░▒░█▒▒░▒
|
||||
░▒█░▒ ░█░░
|
||||
▒ ░ ▒▒ █▒▒█
|
||||
██░ ██▓▓░░
|
||||
█ ░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
████████
|
||||
░▒░ ▒░
|
||||
░▒░█ ░▒▓▒
|
||||
░░░▒▒▒ ░▓
|
||||
░▓▓░█ ▒░░
|
||||
█ ▓ ▒▒▓▒░
|
||||
█▓ ░▓██ ░
|
||||
▒░░░ ░▓▒▒
|
||||
▒░▒▒█ ▓░
|
||||
░░░░▒▒░░▒
|
||||
░░░ ██ ░░░
|
||||
░░░░▓▓▒▓░
|
||||
░░░░░░░░░░
|
||||
░░░░░░▒▒░░
|
||||
░░░░░░░░░░
|
||||
░░▓░░░░░ ░
|
||||
░░░░░░░░░░
|
||||
░░░░░░░░▓░
|
||||
░░█░▒▓█░▒░
|
||||
▒░▓░░▓ ░▒░
|
||||
▒░█░ ░ ░ ░
|
||||
█▓ ▓█▓
|
||||
█ ██ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
███▓███▒█
|
||||
▒▓ ▒▓░▒
|
||||
░█░██▒▒░▒▒
|
||||
░█ █ ░█░▓░
|
||||
░░░ ░▒░░░ ░
|
||||
█░▓░▓▒░▒ ░
|
||||
▒░░░░░░░░ ░
|
||||
▓░░░▓░▒░░░ ░
|
||||
░░░░░░▒░░█ ░
|
||||
░▒░░░░ ▓░▒ ░
|
||||
░░ █░▒░▓░█▓░
|
||||
░█ ▓░ ░░▓░
|
||||
▒░ ░░░ ░░░█░
|
||||
▒ ░░░█░░░ ░
|
||||
▒░░░░█░█░░░
|
||||
▒▒░░░ ▓▒░░░
|
||||
░▓░░░▒▓░░▓░
|
||||
░░▒▓█░░▒▓▓░
|
||||
░█░▓██░█░░░
|
||||
█▒ ░ ░░▒
|
||||
░░█ ░░▓░▓░
|
||||
░▓▒ ░█▒▒░
|
||||
░ █ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
██░▓█▓█░█
|
||||
▓▒▒░▓░▒▓▒▓█
|
||||
░░ ░ ▓░▒█▒▒▒
|
||||
█▒░ █░░░░██ ▓
|
||||
░░▓░▓▒░ ░ █▓░██
|
||||
░ ░█░░░░░░░ ▒░
|
||||
▒░░ ▒ ░█░ ▓▓░▓
|
||||
░░░░░▒░░░▒ ░ ░░
|
||||
░░░░░░░░ ░░░ █▓░
|
||||
░░░░▒▓░░▓ ▒█░░░░
|
||||
░░ ▒░▓░▓▓█░▓▓░░
|
||||
░░▒░▓▓▒ ▒▒▒▒ ▒▒░
|
||||
░░░░░▒ ░▓▓▓█▒▒░░
|
||||
░░░░░ ░█░░░░░█░░
|
||||
░░ ▒ ░░ ░ ▒▒░█░░
|
||||
░ ▒ ░ ░░░▒▒▓▒▒░
|
||||
░█ ░█░▒ ░░░▓▒
|
||||
░░░ ▒█▒▒██░▓░░
|
||||
█░▓▒▓█ ▓░░▓░░█░
|
||||
░░█ █▓▒░█░
|
||||
█▒ ▓ ▒█░█▓▓▓
|
||||
█▓░▓ ▒░▒▒▓
|
||||
░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒███▓███░▒▒
|
||||
█▒▓░░▒▒▒█▒▓█▒
|
||||
░░▓░█▒▓░▒░ ██▒▒
|
||||
░▓░▓▓▓▒░█▓ ▒███░█
|
||||
██▓░░█▓▓░░ ▓█▒▓
|
||||
░▒▒▓▓ ░█▓█▒ ▒░█
|
||||
▒░▓▒▒█ ░░▒█ ▒░░
|
||||
░░▒░▓░░ ░░░█▓ ▓░
|
||||
░░▒█░░░▒▒▒░░░ █▓░░
|
||||
▒░░░░░ ░░▒█ ░░▒░
|
||||
░░░░░▓ ▓░▒░█░░ ░▓▒░
|
||||
░░░░░▓ ▒▓▒ ░▒░ ░▒░
|
||||
░░░░░ ▓░░▒▒██▒░░░
|
||||
░░░░░ ▓░▒▒█░░▒▓░ ░░
|
||||
░░░░░ ▒▒░░▒▒█ ▓░█▓░░
|
||||
░░░░ ▒▒░░█▒░▒█░▒░▓░
|
||||
░░░░ ▒░▓ ░ ░▒█
|
||||
█░░░░░ ░ ▓▓▒█░█
|
||||
░▒█▒█░░█▓█ █░ ░█▒
|
||||
█▒▓ ░░▒▒░▓█▓░▒██
|
||||
█░█▓ ░▒ ███▓▓▒▓
|
||||
▒██ █░█▒▒▓
|
||||
░░ ░█ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
█▒█░▒█▒█░▒▒
|
||||
▓██ █ ░░█░█▓░██
|
||||
░░█▓█▓█░ ██ ████▒
|
||||
▓ ░░ ▓▓░█▓▓░ ░ ██▒▒
|
||||
░ ▓░░██░▒█ ▓▒░█
|
||||
▓▓░█▓▓░▒█ ▒ ▒▓
|
||||
░░▓▒▒░█░█ ▒█▒ ▒▓░█
|
||||
▓░░ ░░███░ ▒▓░▒ █░▓
|
||||
░▒░ ░▒░░░ ▓▒▒█▓ ░░
|
||||
▒░░░ ░░░░ ▒░░▒ ░▓░
|
||||
░░░░░▒▒░░ ▓▓ ▓ ▓█▓░
|
||||
░░░░█░▒░░ ░▒░▒ ░░░
|
||||
░▓░░░ ░░░ ▓▒ ░▒ █ ▓▒░░░
|
||||
░░░░░ ▓░ ░▓░█░░ █ ░░░▒░
|
||||
░░░░▓ █░ █▒ ▓ ░░▓ ▓ ░░█
|
||||
░░░░░ █░ ▓█▓ ▒░░░▒░
|
||||
░░░░░█░░ ▓░░░░
|
||||
▒▒░░▒▓ ░█▒ ▓▒▒
|
||||
█░█ ░░▒▒▒▒▒ ░░█░
|
||||
▒▒▒ ▒▒▒▒▒████░▒░██▓
|
||||
░▒ █▓ █▒█▓█▒█
|
||||
█▒▒ █▒██▒▒▓█░
|
||||
░ ░░░░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒█▓█▒█▓█████
|
||||
▒░█ ▓ ░░█ ▒▓▓▒█▒▒
|
||||
▒░█░░▓ ▓▓▒███ ██ ▒░▒
|
||||
█▓██ ▒█████▓ ░░ ▒ ▒░
|
||||
█▓██ ░▓█░░█ ░░
|
||||
░▓░█▓██▓▒█ ▒ █▒█
|
||||
░░░▓▒░█░░ █░▒ ▓░▒
|
||||
░░ ▓░░░░█ ░█▒▒▒ █▓░█
|
||||
░█░▓ ░░█ ▒▓▒░▒ █░▒
|
||||
░░░░░ ▒░░ ▒▒▓█ ░░░
|
||||
░▓░░ ▒░█░ █ ▒░█▒ ░░▒
|
||||
░ ▒▓█▒▒░░ ░▒██░░ ░░▓
|
||||
░ ░█░▓░░ █▓▒█▒█▒▒██▒▒ ▒▒░▓
|
||||
░░ ▒░ ░░░░ ▓▓▓▒▓ █░█ ░ ░░░░
|
||||
░█ ██░░▒░ ▒▓ ░ ▒░█░ ██▓ ░
|
||||
░ █░█ ░▓ ▒░░░
|
||||
▒▒ █▒░░░█░ █░█░█░
|
||||
▒░▒ ▒█▒ ▒ ░▓▒▒▒░
|
||||
░░ ▒█░▒ ░▒ ▓ ░█▓
|
||||
▒▒ ░ ▓░▒▒█▒▒▒██▒▓▓░ ▓
|
||||
█░▒ ░▒░▒░ █████ █
|
||||
██▒ █▒█▒▒▒▒▒▓█
|
||||
░ ░░░░ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▓█▓░▒▓█▓▒███▒
|
||||
█▓▒ █▓▓░▓█░▒▓▒▓ ██
|
||||
▒▓░▓ ████▒███░░█░ ░▒██
|
||||
▓░ ▓▓▓▓▓▓█░ █░█░█▒░▒
|
||||
▓▒█░▓█▓██ ▒▓░▒░▒
|
||||
▓░▓▓█▓▓▓▒ ▒ ██ ░░
|
||||
▒░▒▒ ░ █▓ ░█▓ ▒ ▒░██
|
||||
░░░▓▓██░ ░███ ▒ █░░
|
||||
░▒▒ ▒▓▒█░▒░ ▒░▓
|
||||
░░░░░▓▒░ ▓█▓▒█ █▓░░░
|
||||
░░░░░░░▓ ▓ ▒▓░▒░ █▓░░▓
|
||||
░▒ ░░░░░ ▓█░▓▒░█ ▓░░▒
|
||||
░░ ░▓░░░ ░░▒█▓░█ ███▒▒ ▓░░
|
||||
▓ █▓░ ▓▓▓▓█▓▓ ▒█ ░▓ ░░░░░
|
||||
░ ▓ ░░▒ ▒░░█ ▒███▓ ░██
|
||||
█▓▓ ░ ░ ▒█░ ░░▓▓
|
||||
░█ ▒░▒▒█▒█ ▒█▓▓░▒░
|
||||
█▓▒███░█▒█ ▓█▓▓▒▒▓
|
||||
░▓▒▒█▒░██▒ ▒▓░█░█░▓
|
||||
░▓ ▒▒▒▒ ███▒▒▓█▒░░░█▒█
|
||||
░▒░ ▒ ▒░ █▒████ ▒▓░
|
||||
██ ░████▓▒▒▒▒██░
|
||||
██░░ █ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒██▓█▒████▓░█▒
|
||||
▒█░ █ ░█ █ ▒▓▓░▓ █▒█
|
||||
▒▓ ░▓████ ▒███░░ ███▓▒▒█
|
||||
▓██▓▓█▒ ███ ▒▓▒██░█▒
|
||||
░░▓ █ ░▓ ░▓ █▒▒
|
||||
░░▒▒▒██ █▒▓ ██░░
|
||||
▓█ █░▓░█ ▓░█▒ ▒▓▒░
|
||||
▒░▓█░░▓░ ░▓██▒ ░▓▒
|
||||
░░░░ ░▒█ ░███▒░▒ ░░░
|
||||
░░░ █░░ ░█▓█▒ ▓░░
|
||||
▒░░░░▒░ ▓▓▒░ ░░▓
|
||||
▒░░▒░░░ ▓▓▓▓█▓ ░█
|
||||
░░░▓░░░ ▓▒▓▓▓▓▓▒ ▒▒████░▓ ▓ ░█
|
||||
░░░░█▒▓ ▓▓▓▓▓░█ █▒█ █░ ░ █░░▒
|
||||
█░░░▒░░█▒ ██░ ▒ █░█▓█▓░█ ░▒█░░
|
||||
█▒░░░▓▓ ░ █▒█░ ░ █ ░░
|
||||
██▒▒██▒ ░ ██ ░▒▒▓
|
||||
█░▒▒▒█▒▒ ░ ░▒▓█░▓
|
||||
█░▒▒▒▒░▒▒██ ▒▓██▒▓▓█▓
|
||||
▒▒ █░░█░██▒▒▒▒████░█████
|
||||
▒▒▒▒░▒█▓ ░████████░▒█
|
||||
██▒░███░█▒▒▒▒▒██
|
||||
░█ ░░ █ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▒█░██████░▒▒
|
||||
▒█ ▒█░░█ ░ ▒▓█▓ ░ ███▒
|
||||
▒▓▒▓▓███ ░▒▓███░░ ██▓▒██▒▒
|
||||
▓ ██░░ ▒████▓█▒
|
||||
░ ▓░▓▓ █ ▓██▒
|
||||
░▓▓▓░▓█ ██▒ █▒▒
|
||||
█▓▓▓░█▓ ▓▓ ▒▒ ██▒░
|
||||
▓▓█▓░▒█ ░░▓ ░ ░ ░▓█
|
||||
█▒ ██░ ░█░▓░ ▒ ░░░
|
||||
▒░░░▒░▒ ▒▒▒▒░▒█ ░░▓
|
||||
░ ░ ▓░░ █ ▒█░░░▓ ▓░░░░
|
||||
░░░ ░░░ ░▓▓░▓ ▓▒█ ░▓░░░░
|
||||
█░░░░░░ ░▓██ ▓█ ▒████▓▓▒ ▒ ░█▓░
|
||||
█░░░░██ ░███░▓█▓ ░▒█ ░█ ░ ▒░▓
|
||||
░ ░░░░░ █▓▓ █░ ▒░███▓█ ░ ▓▓░█
|
||||
▒░▒ ███ ░▒█ ▓██░░░░
|
||||
█▒▒░ ▓▓▒ █▓██░█▒▓
|
||||
▒░▒█░▒░▒█▓ ▒▓ ▓██░▓
|
||||
█▒▒▒█░▒▓ ██▓ ▒█ ░██▓▓
|
||||
▒▒ ▒█░▒▒ ██▓▒▒▒▒███▓▒█░▓ ░░
|
||||
▒▒ ▒██░▓█░█████████ ▒█
|
||||
██▒▒▓▒░█▒▒▒▒▒▒▓██░
|
||||
░ ░░░ █ ░
|
||||
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_1.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_1.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓▒▓▒██▒▒██▒
|
||||
▒▒█▓█▒█▓█▒▒░░▒▒ ▒ █▒
|
||||
█░█░███ ▒░ ░ █░ ░▒░░░█
|
||||
▓█▒▒████▒ ▓█░▓░█
|
||||
▒▒▓▓█▒░▒░▒▒ ▓░▒▒█
|
||||
░█ █░ ░█▓▓░░█ █▓▒░░█
|
||||
█▒ ▓█ █▒░█▓ ░▒ ░▓░
|
||||
░░▒░░ █▓▓░▓░█ ░░
|
||||
░▒░█░ ▓░░▒▒░ ▓░██████▒██ ▒ ░
|
||||
▒░▓█ ▒▓█░ ▓█ ░ ░▒▒▒▓▓███░▓█▓█░
|
||||
▒▒▒ ▒ ▒▒█▓▓░ ░▒████ ▒█ ▓█▓▒▓
|
||||
█▒█ █ ░ ██▓█▒░
|
||||
▒▒█░▒█▒ ▒▒▒█░▒█
|
||||
▒██▒▒ ██▓▓▒▓▓▓▒██▒█░█
|
||||
░█ █░░░▒▒▒█▒▓██
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_10.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_10.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒████▒██▒
|
||||
██░███▒░▓▒██
|
||||
▒▒█░░▓░░▓░█▒██
|
||||
░▒▒▓▒░▓▒▓▒███▒▒█
|
||||
▓ ▓░░ ░▒ ██▓▒▓░▓
|
||||
░░ █░█░▓▓▒ ░▒ ░
|
||||
▒ ░█ █░░░░█ ░▓█
|
||||
░░▒█▓█░░▓▒░▓▒░░
|
||||
░▒ ▒▒░▓░░█▒█▓░░
|
||||
░ █░▒█░▒▓▒█▒▒▒░█░
|
||||
█ ░░░░░ ▒█ ▒░░
|
||||
▒░██▒██ ▒░ █▓▓
|
||||
░█ ░░░░██▓█▓░▓░
|
||||
▓░██▓░█▓▒ ▓▓█
|
||||
██ ▒█▒▒█▓█
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▓▒▒█▓███████▒▒
|
||||
██░█▒▓██░▓█ ░█▓░░ ███▒
|
||||
▒█▒▒▓██▓▓▓▒████▒░░███▓▒░ ██
|
||||
▓ ▓▓▓▓▓ ░██▒▓▓██
|
||||
▒░█▒████▒ ▒ ██▓█
|
||||
▒░░░▓▓█ █▓▒ ▓▒█░
|
||||
░▓▒▓▓▒▓ ▓░ ░▒ ▓▒▒█░
|
||||
▓▓▓░░▓░ █░▒▒░▒░ ░▒█░▒
|
||||
░ ▓██░ █▒█░█▓ ▒ ░░░
|
||||
░░░░█░░ █░▒ █▒▓█ ░█░█
|
||||
░ ░░▒█ █░ ▒▓▒ ▒█ ░░▒░
|
||||
░░ ▒▒▒░ ▓▒▒█▓ ▒░ ░░ ░
|
||||
░ ░ ░░▒ ░▒▒█▓░▒▓ ▒▒▒▒▒██▓█▓▒▒ ▒░▓░░
|
||||
█▒ ░░░ ░░███░█▓ ░░▓█ █░▒░░░░ ░░█░
|
||||
░▓█░▒▓▒▒ ░█▓░ ▒█ ░█░█▒▓██▒ ▓░▒▒▓
|
||||
█▒░░░█▒ ░ ░▒██ ██ ▒▓▓█░
|
||||
▒░░░░▒░ ░▒ ▓ ██░░▓
|
||||
▒▓█▒░░▒▒██ ▓░▒█▒▒ ▓▓▓
|
||||
█ █ ░░▓ ░▒ ▒▓█ ▒██░█
|
||||
█▒ ██░█▒ ░░▓█▒▒█████░▒███░▓▓
|
||||
██▒██░▓▒ █░████████ ███░
|
||||
░█▓▒█ ██▒▓▒▒▒▒▒████
|
||||
░ ░ ██ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▓▓▓█▒███████▒▒
|
||||
▒█ █░▓██░ ████
|
||||
██▒▓███ ▒█▒███▒░░███▓█░░██▒
|
||||
██▓▓▓▒▓ ▒██ ▓▒█░█▒ ▒▒
|
||||
▓ ▓███ █▓ █░▓▓▒▒█▒
|
||||
█ ▓██▓ ▓ ▓▓▒▒ ▒ ░█▓▒
|
||||
░█▓░░▓█░ ▓▓ ██▒ █▒ ░▓▓▒
|
||||
░▒▒▒▓█▓▓░ ▒▒█░▒▒▒░ ░ ▒▓▒█
|
||||
░▓░▒░▒▒ █░▒ █░ ░ ▒ ░░▒█
|
||||
░█░░░░█░ █ ░░█▓░▒░ ░▓ █
|
||||
░█ ░░ ░ ░▒▓ ░█ ▓░ ░░ ░
|
||||
░░░▓░░ ░ ▒██▓▓░ ▓ ░▓░░█░
|
||||
▒█ ░░░█░ ██▓▓░█▓░░ ▒██▒███▓▓█ ▒░░░█░
|
||||
▒░ █▓ █ ▓░█░▓ ▒░ █▓▒█ █░▒ ░ ▓█░▒░░
|
||||
▒ ░░░░█░ ██▓░░▒ ░██░░▓▓███ ░░░░░
|
||||
█░▒▒▒▒░ ░ █▓ ▒▒░▒░
|
||||
▒▒▒▓▒░█▒░▒ ▒▓░▓█▓██
|
||||
█▓ ░░▒█ ░█ ▒▓█▒█▓░░█
|
||||
▒ ██░▓▒ ░█▒ ▒█ ▒▓▒██▓░
|
||||
█▓ ███▓▒ ░█████▒█████░▒▓██░███
|
||||
█▒▒█▒█▒▒ █░█████ ██░█░▓
|
||||
░ █░███▒▒▒▒▒▒█▒██
|
||||
░ ░ ██ ░
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▓▒▓▓█████████▒▒
|
||||
█▓░████ ██▒
|
||||
▒▓██░█▓▓▓▓▒███░░░░░████▒▒▓███
|
||||
▒▓█▓▓ ▒░█▓█ ▒█ ██░░██
|
||||
▓░▓██░░█░ █▓▒██▓░▒
|
||||
░░▓░███░░ ██░▒ █ ░▒▒▒█
|
||||
░▒▓░██▒░ ▒▓▓▓░█ ░▒▒▒░▒██
|
||||
▓█░▒▒▓ ░ █░▓▒█▒▒ ▒▒ ▒▒░▒
|
||||
░░░░░▓░ █░▓▒░░█ ██▒█▒░
|
||||
░░▒░░▓▓ ▓█░▒█▒▒█ ░░▓ ░░░
|
||||
██░░░▓░ ░ ░░█▓░░ ▓ ░▓▒█
|
||||
░░░░▒░ ▓▒█████░ ▓▓░▒ ░
|
||||
▒ ▓░░█ ░ ▒█ ▓▓▓▓▓▓ ██▒▒██████▓███ ░▓░░▒░
|
||||
█▒ ░░░▒░ █▒█▓▓ ▓ █░░▒█ ██▒ ▒██ █░░░░
|
||||
░█▒▒░▓ ░░ █░▓█▓ ▒▒██░░▒▒██ ░░ ▓
|
||||
░█░█▓██▒▓ █▒▓▓░▓░█
|
||||
█▒█░▓░▒█▒▒ ░▓█▒▓▓░█░
|
||||
██ ░░░█ ░█ ▒█▒▓▓▓▒▓░
|
||||
▒▒▒█░▒█ ░█▒ ▓█▒░█░█▒█
|
||||
█▒█░██▒ ▒█████▒▒█▒███░▒▓█░█░▒▓░
|
||||
██ █░░▒▒ █░ ████ ██░▒▒██
|
||||
█ ▓██░░█▓▒▒▒▒▒▒▓███
|
||||
░ ██ ░
|
||||
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_11.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_11.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
███████▒
|
||||
▓ ▓░░░▒▒█
|
||||
▓ ▒▒░░▓▒█▓▒█
|
||||
░▒▒░░▒▓█▒▒▓▓
|
||||
▒ ▓▓▒░█▒█▓▒░░█
|
||||
░█░░░█▒▓▓░▒▓░░
|
||||
██ █░░░░░░▒░▒▒
|
||||
░ ░░▓░░▒▓ ░ ░
|
||||
▓ █░▓░░█▓█░▒░
|
||||
██ ▒░▓▒█ ▓░▒░▒
|
||||
█░▓ ░░░░▒▓░▒▒░
|
||||
▒▒▓▓░▒█▓██▓░░
|
||||
▒ █░▒▒▒▒░▓
|
||||
▒█ █░░█▒▓█░
|
||||
▒▒ ███▒█░
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
▒▒▒▓▓█████████▒▒
|
||||
▒▓██▓░█ ▓▒█ ██▒
|
||||
███░█▓█ █▒██▓██▒░░░█████▒ ██▒
|
||||
█ ▓█ █ ▓▓██░▒ █ ██▓█ ▒▒
|
||||
██░░██ █░ ██ ████▒
|
||||
▓▓▓░░█ ▓ ▓███▒ ▒▓ ▒▒ ░
|
||||
▓▒▓▓██▒░░ ▒▒░▒██░ █▒ ▒░ ░
|
||||
█▓░▒▒██░ ░▒▒▓██▓▒ █▒ ▒░ ░
|
||||
░░░░░█▓░ █▒▒█▒▒▒ ▒▓ ░░██
|
||||
▒░░█░░▓░ ▒█░▒ ▒ █ ░ ░░▒░
|
||||
░▒ ░ ▒ █▒▓▒ ▓ ░█▒░▓░
|
||||
░░░▒░ ▒ ▒█▒█▓ ▓█ █▓░░░░
|
||||
█░ ▒░▒ ░ ▓░█░▒ ▒░░ █▒▒▒█▒▒██▓███▒ ▒ ░░▒░
|
||||
█ ░░░ ░ ▒▓▓▓█░ ▓█ ▒░░▓██ ███ ▒░█░█░▒░▒█░
|
||||
▒█ ▒█▓ ░ ░░ ▓▓ █▓▒█░██▒▒████▓░░▓░▓░
|
||||
▒█░▓░ █▒ ▓▒▒▒█▒▓
|
||||
▒█░░▒▒▒█▒ ▒▓░▓█▓ ▓
|
||||
▒▓░░░▒█▒▒▒ ▒████▓░██
|
||||
██ ░░▓█ ▒██▒▒ ▒██ ░█▓░▒▓░
|
||||
██▒█░▒█▓█░█████▒▒█▒███░▒██░█ ▒█
|
||||
█▒░░▒▒ ▒ █░ ▓███ ██ █▒██░
|
||||
░░▓███░███▒▒▒▒▒▒▓████░
|
||||
░ █ ██ ░
|
||||
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_12.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_12.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
█████▓
|
||||
█▒░▒▓░█▒
|
||||
░▓▒██
|
||||
▓█░░░▒▒ ░
|
||||
░ █░░░░▓▓░
|
||||
░█▓▓█▒ ▒░
|
||||
░ ░▓▒░░▒
|
||||
░ ▓█▒░░
|
||||
██ ░▓░░█░░
|
||||
░ ▓░█▓█▒
|
||||
░▓ ░ ▒██▓
|
||||
█ █░ ▒█░
|
||||
▓ ██░██▒░
|
||||
█▒▓ █░▒░░
|
||||
▒ █░▒▓▓
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_13.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_13.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▓████
|
||||
░▒▒░░
|
||||
░░▒░
|
||||
░██░▒
|
||||
█ ░░
|
||||
▓▓░░
|
||||
█ ░░
|
||||
█ ░
|
||||
▓█ ▒░▓
|
||||
░ █▒░
|
||||
█░▓▓ ░░
|
||||
░▒▒▒░
|
||||
░██░▒
|
||||
█▒▒░▒
|
||||
█ ▓ ▒
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_14.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_14.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
████▓
|
||||
█▓▒▒▓▒
|
||||
░▒░░▓ ░
|
||||
░░▓░ ▒░█
|
||||
░░░▒ ░
|
||||
░█░░ █░
|
||||
░░░░ ▓ █
|
||||
░░▒░░ ▒
|
||||
░░░░
|
||||
▒▓▓ ▓▓
|
||||
▒░ █▓█░
|
||||
░█░░▒▒▒░
|
||||
▓ ░▒▒▒░
|
||||
░▒▓█▒▒▓
|
||||
▒█ █▒▓
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_15.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_15.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
█████░▒
|
||||
░█▒░░▒▓██
|
||||
▓▓░█▒▒░ █░
|
||||
░▓░ ▓▓█▓▒▒░
|
||||
░░▒ ▒▒░░▓ ▒░
|
||||
▒░░▓░░▓▓░
|
||||
░░ ░░░░░░█░
|
||||
░░▓░░█░░░ █▓░
|
||||
░░████░░░▒▓▓░
|
||||
░▒░▓▓░▒░█▓ ▓░
|
||||
░▓░░░░▒░ ░ ▓
|
||||
░██▓▒░░▒▓ ▒
|
||||
█░▒█ ▓▓▓░ ▓░
|
||||
░▒░░▒▒▓█▒▓
|
||||
▒▒█▒▒▒▒▓
|
||||
░░
|
||||
17
codex-rs/tui/frames/blocks/frame_16.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_16.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▒█ ███░▒
|
||||
▓▒░░█░░▒░▒▒
|
||||
░▓▓ ▒▓▒▒░░ █▒
|
||||
▓▓▓ ▓█▒▒░▒░░██░
|
||||
░░▓▒▓██▒░░█▓░░▒
|
||||
░░░█░█ ░▒▒ ░ ░▓░
|
||||
▒▒░ ▓░█░░░░▓█ █ ░
|
||||
░▓▓ ░░░░▓░░░ ▓ ░░
|
||||
▒▒░░░█░▓▒░░ ██ ▓
|
||||
█ ▒▒█▒▒▒█░▓▒░ █▒░
|
||||
░░░█ ▓█▒░▓ ▓▓░░░
|
||||
░░█ ░░ ░▓▓█ ▓
|
||||
▒░█ ░ ▓█▓▒█░
|
||||
▒░░ ▒█░▓▓█▒░
|
||||
█▓▓▒▒▓▒▒▓█
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_17.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_17.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
█▒███▓▓░█▒
|
||||
▒▓██░░░█▒█░█ ▒█
|
||||
██▒▓▒▒▒░██ ░░░▒ ▒
|
||||
▓░▓▒▓░ ▒░ █░▓▒░░░▒▒
|
||||
░▓▒ ░ ░ ▓▒▒▒▓▓ █
|
||||
░▒██▓░ █▓▓░ ▓█▒▓░▓▓
|
||||
█ ▓▓░ █▓▓░▒ █ ░░▓▒░
|
||||
▓ ▒░ ▓▓░░▓░█░░▒▓█
|
||||
█▓█▓▒▒▒█░▒▒░▒▒▓▒░░░ ░
|
||||
░ ▒▓▒▒░▓█▒▓░░▒ ▒███▒
|
||||
▒▒▒▓ ████▒▒░█▓▓▒ ▒█
|
||||
▒░░▒█ ░▓░░░ ▓
|
||||
▒▒▒ █▒▒ ███▓▒▒▓
|
||||
█ ░██▒▒█░▒▓█▓░█
|
||||
░█▓▓▒██░█▒██
|
||||
░
|
||||
17
codex-rs/tui/frames/blocks/frame_18.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_18.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▒▒█▒▒█▓░█▒
|
||||
▒█ ▒▓███░▒▒█ █▓▓▒
|
||||
▒▓▓░█ █▒ █ ▓▒ █▓▓▒ █
|
||||
█░░█▓█▒ █ █▒░▒▓▒░▒▓▒▒▒█
|
||||
▒▒▓▓ ▓░ ▒ █▒▒▓░▓░▒▒▓▒▒▒
|
||||
▓▒░ ██░▓▒▒▒▓███░█▓▓▒▓░▓░
|
||||
░░▒▓▓ █▓█▓░ ▒▓ █░▒░▒█
|
||||
▒▓░░ ▒▒ ░░▓▒ ░▓░
|
||||
▒ █▒▒▒▓▒▓█░░█░█▓▒█ ░█░░
|
||||
▒▒▒░█▒█ ░░▓▒▒▒▒░░░▒▓░░▒ █
|
||||
░▓░▒░ █████░ ▒▒▒▓░▓█▓░▓░
|
||||
▒▒ █▒█ ░░█ ▓█▒█
|
||||
▒▒██▒▒▓ ▒█▒▒▓▒█░
|
||||
█░▓████▒▒▒▒██▒▓▒██
|
||||
░░▒▓▒▒█▓█ ▓█
|
||||
░
|
||||
17
codex-rs/tui/frames/blocks/frame_19.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_19.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▒▒▒█░█▒▒░▓▒
|
||||
▒█░░░▒▓▒▒▒▒█▒█░███
|
||||
██▓▓▓ ░██░ ░█▓█░█▓▒
|
||||
▓▓░██▒░ ▒▒▒██▒░██
|
||||
░░▓░▓░ █░▒ ▓ ░▒ ░▒█
|
||||
░▒▓██ ▒░█░▓ ▓▓ █▓█░
|
||||
▒▒░░█ ▓█▒▓░██░ ▓▓▓█░
|
||||
░░░░ ░▓ ▒░ █ ░ ░░░
|
||||
░█░▒█▒▓▓▒▒▒░░░░██▓█░▓ ▒ ░░
|
||||
▒▓▓█░▒█▓▒██▒█░█ ▒▒ ▓▒▒▒█▓▓░▒
|
||||
█▒ ▓█░ ██ ▒▒▒▓░▓▓ ▓▓█
|
||||
▒▒▒█▒▒ ░▓▓▒▓▓█
|
||||
█ ▒▒░░██ █▓▒▓▓░▓░
|
||||
█ ▓░█▓░█▒▒▒▓▓█ ▓█░█
|
||||
░▓▒▓▓█▒█▓▒█▓▒
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_2.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_2.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓▒▓▒█▒▒▒██▒
|
||||
▒██▓█▓█░░░▒░░▒▒█░██▒
|
||||
█░█░▒██░█░░ ░ █▒█▓░░▓░█
|
||||
▒░▓▒▓████▒ ▓█▒░▓░█
|
||||
█▒ ▓█▒░▒▒▒▒▒ ▒█░▒░█
|
||||
█▓█ ░ ░█▒█▓▒█ ▒▒░█░
|
||||
█░██░ ▒▓░▓░▒░█ ▓ ░ ░
|
||||
░ ▒░ █░█░░▓█ ░█▓▓░
|
||||
█ ▒░ ▓░▒▒▒░ ▓░█████████░▒░░█
|
||||
▒▒█░ ▓░░█ ▓█ ░▒▒▒▒▒▒▓▓▒▒░█▓ ░
|
||||
▒▒▒ █ █▒▓▓░█ ░ ███████ ░██░░
|
||||
█▒▒▓▓█ ░ ██▓▓██
|
||||
▓▒▒▒░██ █▒▒█ ▒░
|
||||
░░▒▓▒▒ ██▓▓▒▓▓▓▒█░▒░░█
|
||||
░████░░▒▒▒▒░▓▓█
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_20.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_20.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▒█▒░░▒█▒█▒▒
|
||||
█▓▒ ▓█▒█▒▒▒░░▒▒█▒██
|
||||
██ ▒██ ░█ ░ ▒ ▒██░█▒
|
||||
▒░ ▒█░█ ▒██░▒▓█▒▒
|
||||
▒░ █░█ ▒▓ ▒░░▒█▒░░▒
|
||||
▓░█░█ ███▓░ ▓ █▒░░▒
|
||||
▓░▓█░ ██ ▓██▒ █▒░▓
|
||||
░▒▒▓░ ▓▓░ █ ░░ ░
|
||||
░▓░░▓█▒▓▒▒▒▒▒▒▒██▓▒▒▒▒█ ▓ ░▒
|
||||
█░▒░▒ ▓░░▒▒▒▒░▒ █▒▒ ░▒▒ █▓ ░░
|
||||
▒█▒▒█ █ ▒█▒░░█░ ▓▒
|
||||
█ ▒█▓█ ▒▓█▓░▓
|
||||
▒▒▒██░▒ █▓█░▓██
|
||||
▒█▓▓ ░█▒▓▓█▓ ░ ░█▓██
|
||||
░██░▒ ▒▒▒▒▒░█
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_21.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_21.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▒█▒█▒▒█▒██▒▒
|
||||
███░░▒▒█░▒░█▓▒░▓██▒
|
||||
▓█▒▒██▒ ░ ░▒░██▒░██
|
||||
██░▓ █ ▒█▓██▓██
|
||||
▓█▓█░ █░▓▒▒ ▒▒▒▒█
|
||||
▓ ▓░ ███▒▓▓ ▒▒▒█
|
||||
░█░░ ▒ ▓░█▓█ ▒▓▒
|
||||
░▒ ▒▓ ░█ ░ ░
|
||||
░ ░ ██▓▓▓▓▓███ ▒░█ ░█ ▓▓ ░
|
||||
░ ░▒ ░▒ ▒█░ ▒ ░█░█ ▓ ▓▓
|
||||
▓ ▓ ░░ █░ ██▒█▓ ▓░ █
|
||||
██ ▓▓▒ ▒█ ▓
|
||||
█▒ ▒▓▒ ▒▓▓██ █░
|
||||
█▒▒ █ ██▓░░▓▓▒█ ▓░
|
||||
███▓█▒▒▒▒█▒▓██░
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_22.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_22.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒██▒█▒▒█▒██▒
|
||||
▒█▓█░▓▒▓░▓▒░░▓░█▓██▒
|
||||
█▓█▓░▒██░ ░ █▒███▒▒██
|
||||
▓█░██ ██░░░▒█▒
|
||||
▒░░▓█ █▒▓░▒░▓▓▓█░
|
||||
▒░█▓░ █░▓░▓▒▓░ ▒░▒▒░
|
||||
░██▒▓ ░█░▒█▓█ ░░▓░
|
||||
░░▒░░ ░▒░░▒▒ ░▒░ ░
|
||||
░░█ █ █░▒▒▓▓▓▒██▒▒█░▒ ▒█ ▒░▓
|
||||
▒░▒ █▒▒▒█ ▓█ ░▓▓░ ▒█▓▒ ░██ ▓▒▒
|
||||
▒▒▒▒░ ██ ░ ░▓██▒▓▓▓ █░
|
||||
▒█▒▒▒█ ▒██ ░██
|
||||
█ █▓ ██▒ ▒▓██ █▒▓
|
||||
█▓███ █░▓▒█▓▓▓▒█ ███
|
||||
░ ░▒▓▒▒▒▓▒▒▓▒█░
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_23.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_23.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒██▒▒████▒█▒▒
|
||||
▒▒░█░▒▒█▒▒▒█░▒░█░█▒
|
||||
█ █░██▓█░ ░▓█░▒▓░░█
|
||||
▓▓░█▓▓░ ▒▓▓▒░░▓▒
|
||||
▓▓░░▓█ █▓████▓█▒░▒
|
||||
█▒░ ▓░ ▒█████▓██░░▒░█
|
||||
░░░ ░ ▓▓▓▓ ▒░░ ░██
|
||||
░▓░ ░ ░ ░█▒▒█ ░ █▓░
|
||||
▒ ▒ ░█░▓▒▒▒▒▒▓▒░▒█░▒ ▒▒ ░ ░░░
|
||||
░▒▒▒░ ▒ ▓░▒ ▒░▒▒█░ ▒▒░
|
||||
▓█░ ░ ░ █░▓▓▒░▒▓▒▓░
|
||||
█░░▒░▓ █▓░▒▒▓░
|
||||
▒ ░██▓▒▒ ▒▓ ▓█▓█▓
|
||||
▒▒▒█▓██▒░▒▒▒██ ▓▒██░
|
||||
░ █▒▒░▒▒█▒▒██░
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_24.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_24.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒░▒▓███▒▒█▒
|
||||
█ ▒▓ ░▒▒░▒▒██▒██
|
||||
█ █▓▒▓█ ░ ▓░▓█░███ ▒
|
||||
██▓▓█▓░▒█▒░░▓░ ▒█▒░▒▒█
|
||||
█ ▓▓▒▓█ ░ ▓▒▒░░░▒░██
|
||||
░█▒█▒░ ███▓ ▓░▓ ▓ ▒
|
||||
░ ░░ █▓▒█▓ ▓▒▒░▒▒░▒
|
||||
░ ▒░░ ░█▒▓▒▒░░▒▓▓░░░
|
||||
░▓ ░▓▓▓▓██░░░██▒██▒░ ░ ░░
|
||||
▒ ▓ █░▓██▓▓██░▓▒▒██░ ░█░
|
||||
▒ █▒░▒█ ░ ▒█▓█▒░▒▓█░
|
||||
▒ ▒██▒ ░ ▓▓▓
|
||||
▒▓█▒░░▓ ▒▒ ▒▓▓▒█
|
||||
▓▓██▒▒ ░░▓▒▒▓░▒▒▓░
|
||||
█▓▒██▓▒▒▒▒▒██
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_25.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_25.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒█▒█▓████▒
|
||||
█ ███░▒▓▒░█░░█
|
||||
▓░▓▓██ ▓░█▒▒▒░░░▒
|
||||
░██░ ▓ ▒░ ▒░██▒▓
|
||||
█▒▒▒█▓█▒▓▓▒░ ░▓▓▒▓█
|
||||
▒█░░░▒██▓▒░▓ ▓░█░▓▓░█
|
||||
░▓░█░ ░▒▒▓▒▒▓░▒▓▒ ░▒░
|
||||
░░░▓░▓ ░▒▒▒▓░▒▒░▒░░▒
|
||||
▒█▒░ ░▒▒▒▒▒▒█░░▒▒░██░▒
|
||||
▓▓ ░▓░█░▒░░▓█▒░▒█▒▓▒░
|
||||
▒░█▓▒░░ ██▓░▒░▓░░
|
||||
░▒ ░▓█▓▒▓██▓▒▓█▓▓░▓
|
||||
▒░▒░▒▒▒█▓▓█▒▓▒░░▓
|
||||
▒▓▓▒▒▒█▒░██ █░█
|
||||
░█ █▒██▒█░█
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_26.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_26.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓███ ██
|
||||
▓█░▓▓▒░█▓░█
|
||||
▓█ ░▓▒░▒ ▒█
|
||||
▓█ █░░░▒░░▒█▓▒
|
||||
░▒█▒░▓░ █▒▓▓░▒▓
|
||||
▒ ░▓▓▓ █▒▒ ▒▒▓
|
||||
░ ██▒░░▓░░▓▓ █
|
||||
▓▓ ▒░░░▒▒▒░░▓░░
|
||||
░ ▓▒█▓█░█▒▒▓▒░░
|
||||
▓▒░▓█░▒▒██▒▒█░
|
||||
░░ ▓░█ ▒█▓░█▒░░
|
||||
▒▒░░▓▒ ▓▓ ░░░
|
||||
█ █░▒ ▒░▓░▓█
|
||||
░ █▒▒ █▒██▓
|
||||
▒▓▓▒█░▒▒█
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_27.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_27.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▓█████
|
||||
░▓▓▓░▓▒
|
||||
▓█░ █░▓█░
|
||||
░░░▒░░▓░░
|
||||
░ ░░▒▓█▒
|
||||
░▒▓▒ ░░░░░
|
||||
▒ ░░▒█░░
|
||||
░ ░░░░▒ ░░
|
||||
░▓ ▓ ░█░░░░
|
||||
█▒ ▓ ▒░▒█░░
|
||||
░▓ ▒▒███▓█
|
||||
░░██░░▒▓░
|
||||
░▒▒█▒█▓░▒
|
||||
▒▒▒░▒▒▓▓
|
||||
█▒ ▒▒▓
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_28.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_28.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▓██▓
|
||||
░█▒░░
|
||||
▒ ▓░░
|
||||
░▓░█░
|
||||
░ ░░
|
||||
░ ▓ ░
|
||||
▒░░ ▒░
|
||||
░▓ ░
|
||||
▓▒ ▒░
|
||||
░░▓▓░░
|
||||
░ ▒░
|
||||
░▒█▒░
|
||||
░▒█░░
|
||||
█▒▒▓░
|
||||
░ ▓█░
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_29.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_29.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
██████
|
||||
█░█▓ █▒
|
||||
▒█░░ █ ░
|
||||
░░░░▒▒█▓
|
||||
▒ ░ ░ ░
|
||||
░█░░░ ▒▒
|
||||
░▒▒░░░ ▒
|
||||
░░▒░░
|
||||
░░░█░ ░
|
||||
▒░▒░░ ░
|
||||
█░░▓░▒ ▒
|
||||
░▓░░░ ▒░
|
||||
░░░░░░▒░
|
||||
░▒░█▓ ░█
|
||||
░░█ ▓█
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_3.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_3.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓▒▓██▒▒▒▒█▒
|
||||
▒██▓▒░░█░ ▒▒░▓▒▒░██▒
|
||||
█▓▓█▓░█ ░ ░ ░ ███▓▒░█
|
||||
▓█▓▒░▓██▒ ░▒█ ░░▒
|
||||
█▓█░▓▒▓░░█▒▒ ▒▒▒░░▒
|
||||
▓░▒▒▓ ▓█░▒▓▒▒ ░ ▒▒░
|
||||
▒█ ░ ██▒░▒ ░█ ▓█▓░█
|
||||
█▓░█░ █▓░ ▓▒░ ░▒░▒░
|
||||
▓ █░ ▓░██░░█▓░▒██▒▒▒██▒░▒ ▓░
|
||||
█▒▓▒█ ▓▓█▓▓▓░ ░█░▒▒█ ▒▓█▓▒░░▒░░
|
||||
█▒░ ░ ░░██ ███ ███▓▓▓█▓
|
||||
██░ ▒█ ░ ▓▒█▒▓▓
|
||||
▒▒▓▓█▒█ ██▓▓ █░█
|
||||
▒▒██▒██▒▒▓▒▓█▓▒█▓░▒█
|
||||
░███▒▓░▒▒▒▒░▓▓▒
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_30.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_30.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓ ████
|
||||
▒▓▓░░▒██▒▒
|
||||
█▒░█▒▒░██▒
|
||||
░░▒░▓░▒▒░▒ ▒█
|
||||
▒█░░░▒░█░█ ░
|
||||
░█░▒█ █░░░░▓░
|
||||
▒▓░░░▒▒ ▒▓▒░ ▒░
|
||||
░ ██▒░█░ ░▓ ░
|
||||
░▒ ▒░▒░▒▓░█ ░
|
||||
░░▒░▒▒░░ ██ ░
|
||||
▒░░▓▒▒█░░░█░░
|
||||
░█▓▓█▓█▒░░ ░
|
||||
▒░▒░░▓█░░█░▓
|
||||
█▒██▒▒▓░█▓█
|
||||
▒▓▓░▒▒▒▓█
|
||||
░░░░
|
||||
17
codex-rs/tui/frames/blocks/frame_31.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_31.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓▓████▒█
|
||||
▒██▓██▒ █▒███
|
||||
█░▒▓▓█▒▒░▓ ░▒█▒
|
||||
█░▓█▒▒█▓▒█▒▒░▒░░▒
|
||||
▒░░░░█▓█▒▒█ ▒░▓▒▒
|
||||
▓░▒░░▒░█ ▒▓██▓▓░█ ░
|
||||
▓░░ ░▒█░▒▓▒▓▓█░█░▓░
|
||||
▒▒█ ░░ ░▒ ░▒ ░░▒▓░
|
||||
░▒█▒░█▒░░░▓█░░░▒ ░
|
||||
░░░▓▓░░▒▒▒▒▒░▒░░ █
|
||||
▒█▒▓█░█ ▓███░▓░█░▒
|
||||
░░░▒▒▒█ ▒▒█ ░
|
||||
▓░█▒▒ █ ▓ ░█░▓░
|
||||
▓░▒░▓▒░░█░ █░░
|
||||
█ ▒░▒██▓▓▓█
|
||||
░░░░
|
||||
17
codex-rs/tui/frames/blocks/frame_32.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_32.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
█████▓▓░█▒
|
||||
▓█░██░▒░░██░░█
|
||||
▓▒█▒▒██▒▓▓░█░█▒███
|
||||
█▓▓░▒█░▓▓ ▓ █▒▒░██ █
|
||||
▓▓░█░█▒██░▓ █░█░▒▓▒█▒█
|
||||
▒▓▒▒█▒█░░▓░░█▒ ░█▓ █
|
||||
█░ ▓█░█▒░░██░█▒░▓▒▓▓░█▒
|
||||
░░░█▒ ▒░░ ▓█░▓▓▒ ▒░ ░
|
||||
▒░░▓▒ █▒░ ▒▒░███░░░▒░ ▒░
|
||||
█ ▒░░█▒█▒▒▒▒▒▒░░█░▓░▓▒
|
||||
█▒█░░▓ ░█ ███▒▓▓▓▓▓▓
|
||||
▒█░▒▒▒ █▒░▓█░
|
||||
███░░░█▒ ▒▓▒░▓ █
|
||||
▒▓▒ ░█░▓▒█░▒█ ▒▓
|
||||
░▓▒▒▒██▓█▒
|
||||
░░░
|
||||
17
codex-rs/tui/frames/blocks/frame_33.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_33.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒██▒█▒█▒░▓▒
|
||||
▒██░░▒█▒░▓░▓░█░█▓
|
||||
▒▓▒░████▒ ░ █▓░░█ █
|
||||
█▒▓░▓▒░█▒ █░░▒▒█
|
||||
▒▓░▓░░░▓▒▒▒ ░█▒▒▒
|
||||
▓▓█ ▒▒▒▒░▒█ ▓▒▓▒▒
|
||||
░░█ ▒██░▒░▒ ░█░░
|
||||
█░██ ███▒▓▒█ ▒ ░█
|
||||
░░░ ░ █░ ▓████▓▒▒█░░█▓▒░▒░
|
||||
▒▓░█ ▓▓█▓░░░▒▒▒▒▒░░█▒▒▒░░▓
|
||||
▒▒▒█ ░▓░▓ ▓ ███ ░░█▓▒░
|
||||
▒█▒██ █ ▓▓▓▓▒▓
|
||||
█▒ ███▓█ ▒█░█▓█▒█
|
||||
▒░ █▒█░█▓█▒ ▓█▒█░█
|
||||
▒▒██▒▒▒▒██▓▓
|
||||
░░░░
|
||||
17
codex-rs/tui/frames/blocks/frame_34.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_34.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒█▒████▒░█▒
|
||||
▒███▓▒▓░ ░██▒██▓█▒▒
|
||||
▒▓▓█░█ ▓░█░ ░▒▒▒█ ███
|
||||
█▓▒░█▒▓█▒ █░██▒▒
|
||||
▓▓░▒▓▓░ ░ █ ▒▒█▒▒
|
||||
█▓▒░░▓ ▒▒ ░▒█▒ ▒█▒░▒
|
||||
░█▒░▒ █▒▒█░▒▒ ░▓░▒
|
||||
▒░▒ ▓ ░█▒░▓ ░ ▓ ▒▒
|
||||
██▓▓ ▓▒▓▓ ▒▒▒██████░▒▒ ░▒░
|
||||
░░▒█▓██▒ ▓▓█░░░▒░▓▒▒▒█▓▒░░░░▒
|
||||
▓▒▒█ ░▒░█▒ ██░░░░▒ █▓█▒░█
|
||||
▓█▒▓▒▒▒ ▓▓▓░▓█
|
||||
▒█░░█▒▓█ ▒█▒ ▒▓█░
|
||||
▓▒▓░ ░██▓██▒█▒█░██▓█
|
||||
░▒▓▒▒▒▒▒▒▓▒█▒▒
|
||||
░░░
|
||||
17
codex-rs/tui/frames/blocks/frame_35.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_35.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒██▓▒███▒██▒
|
||||
██▒█▓░███ ░█░▓ ░█▒▒
|
||||
▒▓▓░▓██░▒█ ░ ░ █▒█▓ ░██
|
||||
█▓▓█▓█▓█▒ ██▒▒░▒
|
||||
▓▓░░▓▓▒ ▒██ ░▒█░█
|
||||
▓▓▓▓█░ █░▒ ▓▓█▒ ░▒▒░
|
||||
▒ ▓▓ ▒▒ ██▒▓ ░▒▒▒
|
||||
░░░▓ ▓▒▒▓▓█ ▓ ▓
|
||||
▓ █▒ █░░▓▓ ▓░▒▒▒▓▒▒█░░ ░░▒█
|
||||
░█▒▓█ ▓▓▓ ██▓░▓ ▒█▒▒▒▒▓ ░▓█ ░█
|
||||
▓░▒██▓▒▒░▓▒░ ░ ▒▒▒▒█▒▒█▓▓▒█░
|
||||
▓▒▒▓░ ▒▓█ █▒
|
||||
▒▓░▒▓█▓█ █▓▓▒███
|
||||
▒▒ ░█░▓▓░░█░▓▓█ ▒▓▓
|
||||
▒░▓▒▒▒▓▒▒███ ▒
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_36.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_36.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▒█▒████▒██▒
|
||||
▒▒ ▒█▓▓▓█▒█▓██ ███▒
|
||||
█▒█▒███▓█ ░░ ░ █░██░██░█
|
||||
▒░ ██▒▒▒▒ ██░▒ ░
|
||||
█▓▒▓▒█░▒░▒█▓ ▒▒▓█
|
||||
▓ █▓░ █▒ ░▓█ ▒▒█
|
||||
░ ▓ ░ ▒ ▒▒ ░▒░█
|
||||
░░▒░ ▒▒ ▒▓▓ ▒░ ░
|
||||
░█ ░ ▓▓ ██ ████▒█████▒ ░▒░░
|
||||
▒█░▒ █░▒▒▓░▓ ░░▒▒▒▒▒▒▒░░ ▒▓█░
|
||||
█ █░▒ █▒█▓▒ ██▒▒▒▒▒ ░█ ▓
|
||||
██ ▒▓▓ █▓░ ▓
|
||||
▒▓░░█░█ ███ ▓█░
|
||||
██▒ ██▒▒▓░▒█░▓ ▓ █▓██
|
||||
░██▓░▒██▒██████
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_4.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_4.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓▒▓█▒▒█▒██▒
|
||||
▒▓ ██░▓ ░▒▒▓█▓░ ▓██▒
|
||||
██▒░░░██ ░ ░▒░▒▒█░▓▒▒▒
|
||||
▓▓░█░ ▓██ ░██▒█▒
|
||||
▓░▓▒░▒░▒▓▒░█ ▒ ▒░█▒
|
||||
▓░░▒░ █▒░░▓█▒ █ ▒▒░█
|
||||
▒░▓░ ███▒█ ░█ █ ▓░
|
||||
░▓▒ █░▓█▒░░ ░░░
|
||||
▒░ ░▒ ▓░▓ ▒▓▓█░███▒▒▒▒██ ░░█
|
||||
░▒▓ ░ █▓▓▓█▒░░▒▒░█▓▒█▓▓▒▓░▓▓ ░
|
||||
░░▓█▒█▒▒█▒▓ ████████▒▓░░░░
|
||||
█░▒ ░▒░ █▒▓▓███
|
||||
▒▒█▓▒ █▒ ▒▓▒██▓░▓
|
||||
░░░▒▒██▒▓▓▒▓██▒██▒░█░
|
||||
█▒▒░▓░▒▒▒▒▒▓▓█░
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_5.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_5.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓▒▓▓█▒▒▒██▒
|
||||
▒█ █▓█▓░░█░▒█▓▒░ ██
|
||||
█▒▓▒█░█ ░ ▒▒░█▒ ███
|
||||
█░▓░▓░▓▒█ ▓▒░░░░▒
|
||||
█▒▓█▓▒▒█░▒▒█ ░ ▒░▒░▒
|
||||
░░░░▓ ▒▒░▒▓▓░▒ █▓░░
|
||||
░▓░ █ ░▒▒░▒ ░█ ██░█░█
|
||||
░▓░▒ █▒▒░▓▒░ █░▒░
|
||||
░█░▒█ ▓▒░ █░█▒▒░█░▒▒▒██▒ ░▓░
|
||||
▒▒░▒██▓██ ░ ▓▓▒▒▒█▒▓█▓░▓█░░
|
||||
▒█░░█░█▒▒▓█░ ██ █░▓░▒▓
|
||||
▒▒█▓▒▒ ░ ▓▒▓██▒
|
||||
▒▓█▒░▒█▒ ▒▒████▓█
|
||||
▒░█░███▒▓░▒▒██▒█▒░▓█
|
||||
▒▓█▒█ ▒▒▒▓▒███░
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_6.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_6.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓▒▓▓█▒▒██▒▒
|
||||
█▒▓▓█░▒██░██▓▒███▒
|
||||
███░░░█ ░ ░▓▒███▓▒▒
|
||||
▓█░█░█▒▒█ ▒█░░░░█
|
||||
█▒░░░█▒▒██▒ ▓▒▒░▒█
|
||||
▓▓▓░▓░▒█▓░▒▒░█ ▓▒▒▓░
|
||||
▒ █░░ ▒▒░▓▒▒ ▒█░▒░
|
||||
░ ░░░ ▒░▒░▓░░ ░█▒░░
|
||||
▒▓░▓░ ▓█░░█▓▓█▒░█░▒▒██▒▓▒▓░
|
||||
░░▒█▓▒▒▒▓█ ░▓▒██░░█▓▒▒▒░█░▒
|
||||
▓ ░ ▓░░░▓▓ █ ██ ░▒▒▓░
|
||||
█ ▓ ▓█░ █▓▒▓▓░░
|
||||
▓░▒▒███ ▒█▒▒▓███
|
||||
░ ░██ █ ▓░▒▒████ ▓▓█
|
||||
▒▓▓███▒▒▒░▒███
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_7.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_7.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▓░▓██▒▒██▒
|
||||
██░█▒░███▒▒▒▓ ░██
|
||||
█ █░░░█░ ░▒░░ █▓▒██
|
||||
▒▒░░░░▓█ ▒░▒█░▓█
|
||||
░█░█░░▒░▓▒█ ▓ █░░▒
|
||||
░ ▓░░ ░█▒▓░▒ █▓░░░
|
||||
░▒ ░ ▒▒░▒░▒░ ██▒░░
|
||||
▒ ▓░░ ▒█▓░█░░ █ ░░░
|
||||
▓ ░█ █ ▒▓░▒▓░░▓▓▒░░▒▓█▒░░
|
||||
░██░░▒▓░░▓█░▓▒░░▒▒█▒█▓▒░▒░
|
||||
▒ ▒▒▓█░█▒▓ ██████ ▒▓░░
|
||||
█▒ ▓▒▓▒░ █ ▓▓▓▓█
|
||||
█▓██▒▒▒▒ █▒░██▓██
|
||||
▒▒█▒░█▒▓░▒▒▒██░██▓
|
||||
░█ ░▓░▒▒█▒▓██
|
||||
|
||||
17
codex-rs/tui/frames/blocks/frame_8.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_8.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▒▒█▒▓██▒██▒
|
||||
█ █▓░░░█▒▒ ░ █
|
||||
▒░▒█░▓▓█ █ ░▓░█▒█▒█
|
||||
▒█▒█▓░██░ █ ▒▒░░▒
|
||||
█ ▓░▓█▒░▓▒ ▓█▒░░█
|
||||
░██░▒▒▒▒▒░▒█ ▒█░░░
|
||||
░█░░░ █▒▓▒░░░ ░▒░▓░█
|
||||
▒█░░▓ ░█▒▓░██▓ ▓░▓░░
|
||||
▒ ▒░░▒▒ ▓█▒░░▓█████▒░░░
|
||||
▒█▓▒▒░ █░█░░▓░▒▒▒░░▒█
|
||||
▓▓▒▒░▒░░░▓█▒█▒█ ▒█ ▓▒░
|
||||
██ ░▒░░░ ▓█▓▓▓█
|
||||
█▒▒█▒▒▒▒ ▒▓▒▒░█▓█
|
||||
▓▓█░██ ▓▓██▓▓▒█░░
|
||||
░░▒██▒░▒██▓▒░
|
||||
░░
|
||||
17
codex-rs/tui/frames/blocks/frame_9.txt
Normal file
17
codex-rs/tui/frames/blocks/frame_9.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
▓▒▒█▓██▒█
|
||||
▓█▒▓░░█ ▒ ▒▓▒▒
|
||||
▓ █░░▓█▒▒▒▓ ▒▒░█
|
||||
░░▓▓▒▒ ▒▒█░▒▒░██
|
||||
▓█ ▓▒█ ░██ █▓██▓█░░
|
||||
░ ░░░ ▒░▒▓▒▒ ░█░█░░░
|
||||
░ ░█▒░██░▒▒█ ▓█▓ ░░░
|
||||
░ ░▓▒█▒░░░▒▓▒▒▒░ ░░
|
||||
█░ ▓░ ░░░░█░░█░░░
|
||||
░▒░░░▒█░▒░▒░░░░▒▒░░░
|
||||
░▒▓▒▒░▓ ████░░ ▓▒░
|
||||
▒░░░▒█░ █▓ ▒▓░░
|
||||
▒█▒░▒▒ ▓▓▒▓░▓█
|
||||
▒▓ ▒▒░█▓█▒▓▓█░░
|
||||
█▓▒ █▒▒░▓█▓
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eeeedcccccccccoee
|
||||
oecxocccceeeedooeecceccce
|
||||
eoxeccceoexccxxcdcxcccccoe cce
|
||||
ocxoocecoocc oxxcccde co
|
||||
ecxooceoo cccxoeco
|
||||
oxxoocox oeoxxeee
|
||||
ooxoc xc xceeec edexoex
|
||||
ooxxccxe ceecxoxx eceexoex
|
||||
ccxxexc xcdeeeeox cocxeeo
|
||||
xecxeexx cexceoxxeo oxexx x
|
||||
oxdx ex ceod cxd cxxxdx
|
||||
c ee ox ceoxxc dc exxxx
|
||||
xexx o oxooc oxe eddcdccccccccco xdox x
|
||||
cxd xo eoxxcc oce oxxdeccccccccc xdexex
|
||||
eoxeo xe cxoe exe cxcoooooo x xxcxe
|
||||
eexxeexo ccccd ooeoocoo
|
||||
eeex ede dcdcoeoo
|
||||
exxxo cxee execxcexc
|
||||
coccxo cocc deccxcccodc
|
||||
cxcxxc eeoccexceeoooccccxcxccceoce
|
||||
cccccdoxxcdxocccdxxdccc eccc
|
||||
cccdxcxxdeeeeeeocdcce
|
||||
eeccccccce
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eeeedcccccccccoee
|
||||
oeoxoccccceoeooo ccceccce
|
||||
eoxxcxcedexccxxcdxxcccccde cce
|
||||
oxcoocecxocc cccede co
|
||||
ecxoocedoc ccccxoeco
|
||||
oxxooeox eoxxeee
|
||||
oxxcc xc edceeec cdcxocx
|
||||
ooxxcexe ceeeeoeo oecxxex
|
||||
ccxxoxc exxxeeee ecocxxeo
|
||||
xccxe x oexcceoxc xexx x
|
||||
cxoxcex ceoxc oco dxxxcx
|
||||
c eo cxo eoxxc odce xx x
|
||||
xexxccce dxooo doee eddcdccdcccccco o ox x
|
||||
cxo xe oxxcccoc c xecccccccccccc xdexex
|
||||
ecxeecxo cxoc exc oocdccexxxdddcc oooxexe
|
||||
eeexoexe cccc e ooeoxcoo
|
||||
oeexecece ecdcocoo
|
||||
eexxoocoee eodcxcexc
|
||||
cocxxe cocc eeccxccxedc
|
||||
cxcxxc ccoccxxceeooocccxxdxccceoce
|
||||
eccccdeoxxdcxccccxcdcccceccc
|
||||
cccxxccddeeeeeeocdcce
|
||||
eeccccccce
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eeeedcccccccccoee
|
||||
eeoxcccxceeoeooo eccxccce
|
||||
eoxxccceodcccxcddxxcccecde ceo
|
||||
oxxcxceecxcco cccede co
|
||||
ocxooeoxc ccecxocco
|
||||
oxxocexc ooeo ceexxeee
|
||||
oxooooxc cecoecd ecxoee
|
||||
oxox ox exccecoc eexdex
|
||||
xxxe xxe cxxdxoee cecxoxx
|
||||
xxex xxc ce xexeco exx x
|
||||
xxex xc ccxxd dxo xxxex
|
||||
oxod ec ecxxe exe e xxxxxe
|
||||
ccxx xx oooce xo decdcdccdcccccco ecxx x
|
||||
cxex cox exxoeoexc oexxcccccceccccc xeexex
|
||||
xexe eee eccoo oc eecxccxxxxddddc ocxxeoc
|
||||
exxd eee ecccc ocoocoo
|
||||
oxxe cxxe eodcococ
|
||||
ocxxe ecce eoxcocexc
|
||||
e eece exccoedx eeccxccxedc
|
||||
cxcxco ccxccxxceeoooccccxcxccceece
|
||||
exxcoeexxcdooxxcxxxdccccexcc
|
||||
cecxxxcdeeeeeeeocdcce
|
||||
eeccccccce
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eeedcccccccdooe
|
||||
eooxccccceeooe dxeccxccce
|
||||
ecxoxceoedccxxcddccccceedoeccco
|
||||
oocxceexcxcco cxcceo cce
|
||||
exoxcddcccoo cxcxe ce
|
||||
oxxecxoc oooe xcx eee
|
||||
oxxoexxe deeococd cecxeeco
|
||||
oxxoexco ecexeeeee coxoeee
|
||||
xxcexxce eoexxeecee ecx ex
|
||||
xxc cxc eecxxxoce cxxo oo
|
||||
exx xx coeee dx xxx xx
|
||||
xxx xxc oxxc ecoe xxxxxx
|
||||
ocx xxo deoxocxcoc ocdddccccccccco xxx xx
|
||||
xe xo xxoceoxc e xxocccccccccccccex excx x
|
||||
xxx cox cxx ooeec eecdccccoxxxxdddceeoxxooc
|
||||
xxe coe cccc eoooodx
|
||||
exe coco oxcocox
|
||||
exxo cocce eoxooceoc
|
||||
cxxxe cccccee edcxeoxddoe
|
||||
ecxxe ccxcxxccedoooccccxxxxceeece
|
||||
ccceoe cccdxxxxxxcccce eccc
|
||||
cccccodeeeeeeeeoddcce
|
||||
eccccccce
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eeeoccccccccooe
|
||||
oeocxccceeoxeooeccxcccoe
|
||||
odocceedcccxxcddccxxxoeeeccceo
|
||||
eocceodcccccx eccxecexocee
|
||||
occoxxccc ccxxxdecd
|
||||
exxodxc ooo cxxococo
|
||||
exxxoxoc xxceexo exd eee
|
||||
xxxox cxeococee cxx dxe
|
||||
xooxxo cxxexeecee cxd oxo
|
||||
xooxx eexxxeceeo cxx xxc
|
||||
xex xcx cxx ocdxc xx oe
|
||||
xee xco dcoocxocc cxc oe
|
||||
xo xxx eoocoxxc occcddcccccdcco cxcexx
|
||||
cxoxoeo oxcodecox coccccccocccccccx exxoox
|
||||
ceo xexe coeoedc xeccccccxxoxxxxc oeceex
|
||||
eeo eece cccce exexoccc
|
||||
cec ecxc oxoxcoxc
|
||||
cxdececxce eoxxcooxc
|
||||
cxdeceoxxceeo edoxxcxeoo
|
||||
cxxoeccxxxcxccddoooocccxxxcc ecc
|
||||
ecceee eccccxxxxxxcccc eococ
|
||||
cxcdxdoeeeeeeeeoddccc
|
||||
eccccccce
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eeeecdccccccoeee
|
||||
oeoxccceeedooeecccccccdoe
|
||||
odcxcoeddcxdccddccocxccecxceox
|
||||
oceeedococc oexeeccccce
|
||||
oc ooccocec ccxeceeec
|
||||
oe excoe oo edcoeoo
|
||||
o oxex ocecx eee xcee
|
||||
oe oxocx xodcoeee ee xexo
|
||||
ecoexeo cxexoecxe xo dxc
|
||||
x exxx cxdccoeee cx xcxx
|
||||
xxcxxe eeexc dxxc xxexo
|
||||
xocxxeo oco docoe xecxx
|
||||
excxxxe oooedxeo edccccddddddddoe xeexe
|
||||
coeexoeo ecccocc occcccccccccccxo exoxx
|
||||
xeexecx ecdooe xccccccxxexxcxo eeexeo
|
||||
xe xeoe ee ecoooo
|
||||
xeoecocex ooexceo e
|
||||
exocccoce eocoxxeoo
|
||||
cxdecedxccoeo eoocexxcocc
|
||||
ccxo ccxxxxcccooooocccxxcccedcoc
|
||||
cccee ccccccccxoodcce ecccee
|
||||
cccxxooeeeeeeeoocccc
|
||||
eccccccee
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eoecdcccccdeee
|
||||
eodxce c ccceccxcccodoe
|
||||
eoc eocccdccddccedoeocxcccco
|
||||
oc occeccec exceoecccexe
|
||||
oc eoccoe dcce eceee
|
||||
o doeo dceo coccdeox
|
||||
x oooe ecex ceccxeex
|
||||
x xode xxceco xxcxeox
|
||||
oe ox e eecee deocoxcd
|
||||
xoxxxo xoe cee ccx xecc
|
||||
xoxxeo ex cec ooxxxe
|
||||
xexcex cec ecc exxxxx
|
||||
xocoxc xoeccoo edcccdddcdcddce ec xxxx
|
||||
xoxcex exccexc xdeeccccccccccxoc xxcxoxo
|
||||
xocoeee eeode ccccecceeecccxo exocec c
|
||||
xecoeco oxeco o
|
||||
cxecoece eceecc o
|
||||
xe ecccce oocoeoeo
|
||||
cxecxeedccee ecceccdceoe
|
||||
cxeecexccxxeccdeeecccccocodoococ
|
||||
ccxoe cccccxcccxcccxccccoxce
|
||||
ecccdddeeeeeeoccxcccc
|
||||
ecccccceee
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eoexdcccccdeee
|
||||
odcce eccxcexo
|
||||
edce eocccxxcdddcece eecceco
|
||||
eoc ecccoo xeo ccdeco
|
||||
occeoc oe exc deeeee
|
||||
xoooo e oc cxoeeexoe
|
||||
xcoxcd e coccc ceccexoe
|
||||
oxxoc e oececd cooeoeox
|
||||
xeexoo eeeee cc x xxe
|
||||
xcdcx oeccoec ex cex o
|
||||
xdxxexc x e oeco dcecxxdc
|
||||
x xxxo xxcccc c cxcxxxo
|
||||
xx cxxe coo ocoeodcccdddccdcd occdxxo
|
||||
x xx x edxo oe cdddceeddddcexo xoxxo o
|
||||
xeeodc ece cdddxeeeeeeecc doexd o
|
||||
xeecec excx o o
|
||||
cxeexxce oxooec oe
|
||||
xoedco eoceoeo oe
|
||||
cxecdxxc e eeccxxc cec
|
||||
cxdcxcxxcxedcdeccccxxxceooexeoe
|
||||
cxcoxxxxccccccxdccoeeooeoc
|
||||
ccxccxxdxxxxeccxxccc
|
||||
ecccccce e
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eocdcddcccddeo
|
||||
eoocc ccxeecce
|
||||
edcxeoccccxcddccco eeccccc
|
||||
excdxcceccxo xeo eee co
|
||||
ocexcc od xo xeo ce
|
||||
ocoxcoe e dxe eeoexo
|
||||
ocoxcxde xeoe coece xcxe
|
||||
exeoc o oeeoe c o eee
|
||||
xoex c eoeeeee eceoxoex
|
||||
x xx x xeococo eoeoxceo
|
||||
cexxcc eexocooeo xxxocxx
|
||||
ocxxe cooccoxc o xxxxc
|
||||
xxxxcx exeexe eocdxdcddddc xoxcxx
|
||||
xoox e ceexo xecccddedddeo dcexxxxx
|
||||
cxxox ccccdexdxexc oxox c o
|
||||
xoeoecx ee dcxooc o
|
||||
xeexxoe oceoxo oe
|
||||
xxcceec excoo oooe
|
||||
cdeeccocx oxceocoeeo
|
||||
cxxcoccexcdxdoooccxxceooee cc
|
||||
cxxxxcxccccccccceoecceeoe
|
||||
eccxdeeeeeeoccdccocc
|
||||
ecccccce e
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eocccdcccdeeo
|
||||
eecccedoo cccccxccxeo
|
||||
oxcddccccccdccxo coec cee
|
||||
excxoceecc co oxeece
|
||||
oooxcc xe eeoo ee
|
||||
ooooo e e cexeoce
|
||||
xooo deeec e eeeoee
|
||||
xexx eecoceco oee oeex
|
||||
xxee ocooece o eeceeoe
|
||||
x xc ocxxoodeeo d xxooxx
|
||||
x ec eeecooedo x xxx xx
|
||||
xede cxo occ x exxxcx
|
||||
xooc x ocoxc oeccccccdcd cxxxexxx
|
||||
xxoxeo c oc xcccccccccee o xcexxx
|
||||
xdox x ecccccxdeexc xcxcxxxee
|
||||
cxccx x eeeee eo ooo x
|
||||
exxxd e oxex o
|
||||
exxeeecd oc oc oe
|
||||
cxxoxeec excooeoc o
|
||||
exxccdcxcecdeoocxxeecdxe oc
|
||||
ccecccccxcxcccededcceoc
|
||||
ccodeeeededccoceoce
|
||||
ccccee ce
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eocccccdcceee
|
||||
odcceoeeecccxxdcxcce
|
||||
oxcecccccxdccdeccxce eee
|
||||
ocoxcedcc ccce ce
|
||||
xecxe ocoxo ex
|
||||
xxcx eeoe ooec ex
|
||||
deox ceeexe coceeeoe
|
||||
xxxe xee xe oceoxx ee
|
||||
ecxx eee eec exexxxxx
|
||||
xxxx oxeoxeeeo ccxdxdoc
|
||||
oxxx exeoexoo xoxxxexx
|
||||
eoxx eeooc o e x xxxxxx
|
||||
xcxc eoeo oeecccccccc cexxeoox
|
||||
cooo co occcccccccxx x x xxxe
|
||||
xxoo eccccexdedxc ocxcxxxxx
|
||||
xooxoc e eeeee x eoxxxxc
|
||||
xxee ce xexeoxxox
|
||||
xeccece exeoooc x
|
||||
xxoxeec ocecooe eo
|
||||
ceccedoxcccooeoccoooce oc
|
||||
cce cccxxxxcceodece oc
|
||||
ccdeooeecccdcedcc
|
||||
ecccee e
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eocdcceccceee
|
||||
ooceooocccxcxd cce
|
||||
exxdccccxccdececod cc
|
||||
ococo xoee eeo
|
||||
oecoe eexdc xo
|
||||
oxc eeo eoexe oo
|
||||
xoo cxeo oedecee
|
||||
x x exeoeeo eo xx x
|
||||
oeex cxcoeexe oexxx x
|
||||
xxc eeexcxc xeoxd o
|
||||
cxc eoxoccx cxxxcxxx
|
||||
oxce oooxo xxxxexxx
|
||||
xxox ex ox eecccccccocxxxxooxx
|
||||
cxx x oxo cccccccceoox exoxxx
|
||||
xoceeoo occddxdcxoeoexxxxx o
|
||||
xxoec ex eeeeece xoxx cx
|
||||
xoeeoo oexc oxee
|
||||
eoxeeee ocoo o oc
|
||||
eoxeccco ocoodo oo
|
||||
eecxcceccoeeoceooee dc
|
||||
ceecccddxcceecexe oc
|
||||
ecoeeeooocddeeoce
|
||||
eccce ce
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
oedxcooccoo
|
||||
ocxdoecedxcdcceo
|
||||
ooxcccxcceeeee ce
|
||||
oxoco exee oex
|
||||
xxee xeee cex
|
||||
eec eoe eoxodoee
|
||||
xoxxxooc o ee ece
|
||||
e x coe e xdcee x
|
||||
oxxe oxxxeo x xeexxx
|
||||
xxe cxood c oocxoodo
|
||||
xxx xeexxx xoxxcoxx
|
||||
xxxe e ccc xexxxxxx
|
||||
xxoe xo eeccccc xexxxxxx
|
||||
xxcxoeo ccccccxe xcxxxxxx
|
||||
oxxcxe ccdxdcoc xcxxx ee
|
||||
xoccx ecxxx xxxex
|
||||
ccdx x ecoexxxxeo
|
||||
xxooeee xoo oxxox
|
||||
coxxecceo exoxoxc ooe
|
||||
cocececcceooeo od xe
|
||||
ceeccdxocedcoce eo
|
||||
cceeeeccdce eoe
|
||||
ecceeeece
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
eodccodecoe
|
||||
ocoocecoe cexo
|
||||
xoocccecoeoec ee
|
||||
dxoco cxoo ee
|
||||
xxe o exee ece
|
||||
xxceeee xdxcc xx
|
||||
ccxxeccc e cx cxoo
|
||||
xx xxxex o xx exe
|
||||
oox ooexe xxxo cx
|
||||
xxc xxxee xooxxex
|
||||
xxo cxoxe xoxdoe xoo
|
||||
xxo xdoecc eoexxxd xx
|
||||
xo xx eeecccceexxxxxxx
|
||||
xc ec cccccexxcexxxxxe
|
||||
xxo x eddexcxxd xx x
|
||||
oxx oo ecxxx xx cx
|
||||
xxcx eeoc xx ex
|
||||
xxxe xxooexxco
|
||||
xxce oxeexxxx o
|
||||
excdeceecoexc oox
|
||||
eecxcoeoexc oo
|
||||
cceeoceocoexc
|
||||
ccceccc
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
odccooecoe
|
||||
ooeeeoodccxo
|
||||
dxoceecxe cxo
|
||||
cxcoxexco coce
|
||||
xex eeoeee cod
|
||||
xeoeco xxexc cx
|
||||
xxxo x cxx edxxe
|
||||
eoco xxo ex x
|
||||
cxcxcc excexxo
|
||||
eoecedx xxcxxoox
|
||||
xoxddcx xxoccxox
|
||||
xococcx xxce xxx
|
||||
coexeeec xxoxxcxx
|
||||
dexcccxe xxd xx x
|
||||
cex d xxxxxxxex
|
||||
xxceco e oxxxx ox
|
||||
xxx xx e exxxx x
|
||||
exc e dxxx odoee
|
||||
xce x x eece xx
|
||||
exeecoeoox xxec
|
||||
ecoccodc co
|
||||
ceeoec ec
|
||||
ccecccc
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
dccoocco
|
||||
e exo ccoe
|
||||
oxxxoeceee
|
||||
oooxdx cxxx
|
||||
xxxoxco cxx
|
||||
xxexooxex ex
|
||||
xxocxxox xx
|
||||
xxccxxxxecc o
|
||||
xxoxxcoexxxex
|
||||
xxxxx xxx eex
|
||||
xxecc xccxcxx
|
||||
xxeex x cxoxx
|
||||
xxeexeeoxxxxc
|
||||
xxxxxxxxx xe
|
||||
xxexcx xxx xo
|
||||
xxexxxxxxxxcx
|
||||
xeooox o x
|
||||
xxoxxcdxxc
|
||||
oxxxexceexe
|
||||
xecxec xcxx
|
||||
d x ee oeec
|
||||
ccx ccodxx
|
||||
cccecce
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
cccoccco
|
||||
xexc ccdx
|
||||
xexc xeoe
|
||||
xxxeeecxo
|
||||
xooxocexx
|
||||
cco eeoex
|
||||
cocxocccx
|
||||
exex xoee
|
||||
exdeo ox
|
||||
xxxeeexxe
|
||||
xxxcoccxxx
|
||||
xxxxoodox
|
||||
xxxxxxexxe
|
||||
xxxxxxeexe
|
||||
xxxxxxxxxx
|
||||
xxoxxxxxcx
|
||||
xxxxxxxxex
|
||||
xxxxxxxxox
|
||||
xxcxeooxex
|
||||
exdxxocxee
|
||||
excx x x e
|
||||
cocc oco
|
||||
cccccce
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user