some stuff IDK how to do ts

This commit is contained in:
lda committed 2026-05-27 03:08:54 +07:00 Verified
1 parent 6a547bceb9
commit ff4a93d967
16 files changed
+1107 -220

No files matched your search

+21 -10
View File
@@ -11,33 +11,44 @@ rand.workspace = true
tokio.workspace = true
# can this not show up
winapi = { version = "=0.3.9", features = ["std"] } # because CODEX toolchain is lowk different
icu_calendar = "=2.1.1" # you have to understand i had to look at the codex-rs lockfile for this bs
winapi = { version = "^0.3.9", features = ["std"] } # because CODEX toolchain is lowk different
# 23898 on openai/codex i filed it hehehe
[[bin]]
name = "bin2"
path = "src/bin2.rs"
[dependencies.codex-backend-client]
git = "https://github.com/openai/codex.git"
rev = "326e31ab65dcbdf70c4a034b7adc5c8bd335d996" # today is a good day to update the rev
rev = "0e9d2221789734dc08313243ecbdc7cc20ee48d1" # today is a good day to update the rev
[dependencies.codex-login]
git = "https://github.com/openai/codex.git"
rev = "326e31ab65dcbdf70c4a034b7adc5c8bd335d996"
rev = "0e9d2221789734dc08313243ecbdc7cc20ee48d1"
[dependencies.codex-config]
git = "https://github.com/openai/codex.git"
rev = "326e31ab65dcbdf70c4a034b7adc5c8bd335d996"
rev = "0e9d2221789734dc08313243ecbdc7cc20ee48d1"
[dependencies.codex-core]
git = "https://github.com/openai/codex.git"
rev = "326e31ab65dcbdf70c4a034b7adc5c8bd335d996"
rev = "0e9d2221789734dc08313243ecbdc7cc20ee48d1"
[dependencies.codex-protocol]
git = "https://github.com/openai/codex.git"
rev = "326e31ab65dcbdf70c4a034b7adc5c8bd335d996"
rev = "0e9d2221789734dc08313243ecbdc7cc20ee48d1"
[dependencies.codex-app-server-protocol]
git = "https://github.com/openai/codex.git"
rev = "0e9d2221789734dc08313243ecbdc7cc20ee48d1"
# codexport shit
# from codex-rs/Cargo.toml
[patch.crates-io]
# [patch.crates-io]
# crossterm = { git = "https://github.com/nornagon/crossterm", rev = "87db8bfa6dc99427fd3b071681b07fc31c6ce995" }
# ratatui = { git = "https://github.com/nornagon/ratatui", rev = "9b2ad1298408c45918ee9f8241a6f95498cdbed2" }
tokio-tungstenite = { git = "https://github.com/openai-oss-forks/tokio-tungstenite", rev = "132f5b39c862e3a970f731d709608b3e6276d5f6" }
tungstenite = { git = "https://github.com/openai-oss-forks/tungstenite-rs", rev = "9200079d3b54a1ff51072e24d81fd354f085156f" }
# tokio-tungstenite = { git = "https://github.com/openai-oss-forks/tokio-tungstenite", rev = "132f5b39c862e3a970f731d709608b3e6276d5f6" }
# tungstenite = { git = "https://github.com/openai-oss-forks/tungstenite-rs", rev = "9200079d3b54a1ff51072e24d81fd354f085156f" }
+25
View File
@@ -0,0 +1,25 @@
use anyhow::Context;
/// inspect a live auth.json file and print out the account info and quota info. this is to help with debugging and understanding the auth.json file and the auth manager.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let arg1 = std::env::args().nth(1).context("non supplied")?;
let file_content = std::fs::read_to_string(arg1).context("failed to read file")?;
let auth_json: codexport::AuthDotJson =
serde_json::from_str(&file_content).context("failed to parse auth json")?;
let (auth_mgr, _path) = codexport::auth_mgr_from_auth_json(auth_json).await.context("failed to create auth manager from auth json")?;
let backend = codexport::backend_client_from_auth_mgr(&auth_mgr).await.context("failed to create backend client from auth manager")?;
let codex_auth = auth_mgr.auth().await.context("failed to get auth info from auth manager")?;
let account_id = codex_auth.get_account_id().context("failed to get account id from auth info")?;
let cgpt_id = codex_auth.get_chatgpt_user_id().context("failed to get chatgpt user id from auth info")?;
let email = codex_auth.get_account_email().context("failed to get account email from auth info")?;
// let quota = codexport::quota(&backend).await.context("failed to get quota")?;
let quota = backend.get_rate_limits_many().await.context("failed to get rate limits")?;
println!("email: {email}");
println!("account_id: {account_id}");
println!("cgpt_id: {cgpt_id}");
println!("quota: {quota:#?}");
Ok(())
}
+142 -40
View File
@@ -9,8 +9,11 @@
use std::{path::Path, sync::Arc};
use anyhow::Context;
pub use codex_app_server_protocol::AuthMode;
use codex_backend_client::Client as BackendClient;
use codex_core::config::Config; // this package takes 14 thousand years to compile; cant do Anything about it
use codex_core::config::Config;
// this package takes 14 thousand years to compile; cant do Anything about it
use codex_login::AuthCredentialsStoreMode;
pub use codex_login::AuthDotJson;
pub use codex_login::AuthManager as CodexAuthManager;
use codex_login::AuthManager;
@@ -24,22 +27,26 @@ pub struct Huge {
// this uses config
async fn stock_backend_client() -> anyhow::Result<Huge> {
let config = Config::load_with_cli_overrides(Vec::new())
.await
.context("Failed to load config")?;
let config = default_config().await.context("Failed to load config")?;
let auth_manager =
AuthManager::shared_from_config(&config, /*enable_codex_api_key_env*/ false).await;
let client = backend_client_from_auth_mgr_and_default_config(&auth_manager).await?;
let client = backend_client(&auth_manager, None).await?;
Ok(Huge {
config,
auth_manager,
client,
})
}
/// this uses config
pub async fn backend_client_from_auth_mgr_and_default_config(
pub async fn backend_client(
auth_mgr: &AuthManager,
base_url: Option<String>,
) -> anyhow::Result<BackendClient> {
let base_url = if let Some(url) = base_url {
url
} else {
"https://chatgpt.com/backend-api".to_string()
};
let auth = auth_mgr
.auth()
.await
@@ -47,26 +54,29 @@ pub async fn backend_client_from_auth_mgr_and_default_config(
// Important: only ChatGPT-style auth modes can hit the Codex backend (“wham” or “api/codex”)
anyhow::ensure!(auth.uses_codex_backend(), "Need ChatGPT/Codex-backend auth");
let config = Config::load_with_cli_overrides(Vec::new())
.await
.context("Failed to load config")?;
let client = BackendClient::from_auth(config.chatgpt_base_url.clone(), &auth)?;
Ok(client)
}
pub async fn backend_client_from_auth_mgr(auth_mgr: &AuthManager) -> anyhow::Result<BackendClient> {
let base_url = "https://chatgpt.com/backend-api".to_string();
let auth = auth_mgr
.auth()
.await
.ok_or_else(|| anyhow::anyhow!("Not logged in; run `codex login`"))?;
anyhow::ensure!(auth.uses_codex_backend(), "Need ChatGPT/Codex-backend auth");
let client = BackendClient::from_auth(base_url, &auth)?;
Ok(client)
}
use codex_protocol::account::PlanType as AccountPlanType;
pub use codex_protocol::protocol::RateLimitSnapshot as RateLimit; // wym snapshot
async fn default_base_url() -> Result<String, anyhow::Error> {
let config = default_config().await.context("Failed to load config")?;
let base_url = config.chatgpt_base_url;
Ok(base_url)
}
async fn default_config() -> anyhow::Result<Config> {
Ok(Config::load_with_cli_overrides(Vec::new()).await?)
}
pub async fn backend_client_from_auth_mgr(auth_mgr: &AuthManager) -> anyhow::Result<BackendClient> {
let base_url = "https://chatgpt.com/backend-api".to_string();
backend_client(auth_mgr, Some(base_url)).await
}
pub use codex_protocol::account::PlanType as AccountPlanType;
pub use codex_protocol::protocol::RateLimitReachedType;
pub use codex_protocol::protocol::RateLimitSnapshot as RateLimit;
pub use codex_protocol::protocol::RateLimitWindow; // wym snapshot
pub async fn quota(client: &BackendClient) -> anyhow::Result<RateLimit> {
let quota = client.get_rate_limits().await?;
@@ -92,15 +102,20 @@ use codex_login::{CLIENT_ID, ServerOptions, run_login_server};
/// - this way you CAN logout using the auth manager.
///
/// tips: use a random codex_home for the ephemeral store if you want to login multiple times in the same process... why would you do that? idk, but hey, you do you. use the [random_path_generator] function below for that.
pub async fn chatgpt_login_to_auth_json(codex_home: &Path) -> Result<Option<AuthDotJson>> {
let store = codex_login::AuthCredentialsStoreMode::Ephemeral;
pub async fn chatgpt_login_to_auth_json(
codex_home: &Path,
port: Option<u16>,
) -> Result<Option<AuthDotJson>> {
let store = AuthCredentialsStoreMode::Ephemeral;
let mut opts = ServerOptions::new(
codex_home.to_path_buf(),
CLIENT_ID.to_string(), // oh hell nah son
None,
store,
);
// if let some(port) = port { opts.port = port; } // if we decide to put port in the args later, this is how we would do it. for now, it is hardcoded to 1455, which is fine.
if let Some(port) = port {
opts.port = port;
}
// run login server, what does it do?
// first it does some bs
@@ -133,6 +148,7 @@ pub async fn chatgpt_login_to_auth_json(codex_home: &Path) -> Result<Option<Auth
opts.open_browser = false;
let server = run_login_server(opts)?;
eprintln!("Open this URL to login:\n\n{}\n", server.auth_url);
// rewriting the topmost function with our logic could help if we want to do something custom with the server, but for now, this is good enough. we can just block until the server is done, which means the login flow is done, and the auth.json is saved in the ephemeral store.
server.block_until_done().await?;
@@ -140,6 +156,9 @@ pub async fn chatgpt_login_to_auth_json(codex_home: &Path) -> Result<Option<Auth
codex_login::load_auth_dot_json(codex_home, store).context("can not load saved auth.json")
}
/// get rate limit! the [RateLimit] struct has a lot of info, including the
/// plan type, and the actual limits and usage. this is a good way to check if
/// your login worked, and what plan you have.
pub async fn get_rate_limit() -> anyhow::Result<RateLimit> {
let huge = stock_backend_client().await?;
quota(&huge.client).await
@@ -156,21 +175,23 @@ pub async fn use_login_server(
.into_path_buf(),
};
let cih = || codex_home.clone();
let auth_json = chatgpt_login_to_auth_json(&cih())
let auth_json = chatgpt_login_to_auth_json(&cih(), None)
.await?
.context("no auth json found")?;
// explicitly check if there is an auth.json, because if there isn't, then the auth manager will just be empty and not logged in, which is not what we want. we want to know if the login failed.
let auth_mgr = auth_manager(&cih(), codex_login::AuthCredentialsStoreMode::Ephemeral).await;
let auth_mgr = auth_manager(&cih(), AuthCredentialsStoreMode::Ephemeral).await;
auth_mgr.auth().await.ok_or_else(|| {
anyhow::anyhow!("Login failed; no auth found in auth manager after login")
})?; // this would never reach since we checked for auth.json. but just in case, we check again.
Ok((auth_mgr, auth_json))
}
use codex_config::types::AuthCredentialsStoreMode;
use std::path::PathBuf;
/// lightweight helper to construct an auth manager from codex home and store mode. use this if you already have an auth.json in the ephemeral store, or if you want to use the same login across multiple auth managers in the same process (by using the same codex home).
/// lightweight helper to construct an auth manager from codex home and store
/// mode. use this if you already have an auth.json in the ephemeral store, or
/// if you want to use the same login across multiple auth managers in the same
/// process (by using the same codex home).
pub async fn auth_manager(
codex_home: &Path,
store_mode: AuthCredentialsStoreMode,
@@ -184,38 +205,58 @@ pub async fn auth_manager(
.await
}
/// use this so ephemeral store key is different; idk why you need to login multiple times per session and not just dumping the auth.json to a folder somewhere but hey, you do you
pub fn random_ass_codex_home(real_codex_home: &Path, yo: &str) -> PathBuf {
real_codex_home.join(yo)
}
/// use to get a COMPLETELY random path.
pub fn random_path_generator(name: Option<String>) -> PathBuf {
PathBuf::from_iter(
std::iter::repeat_with(|| rand::random::<u64>().to_string())
.take(3)
.take(5) // you would NEVER get the same path as me
.chain(name),
)
}
/// Creates an authentication manager from a pre-existing auth.json.
///
/// THIS USES ephemeral store. It will not write to disk. To write to disk,
/// recommended action is to serde::to_string the auth json, then save it to
/// disk yourself.
///
/// ```ignore
/// let mgr, _ = auth_mgr_from_auth_json(auth_json).await?;
/// let mgr = auth_mgr_from_auth_json(auth_json).await?;
/// // build backend client from mgr
/// ```
///
/// this may:
/// - keep a random auth_json inside the ephemeral map for the rest of the process.
pub async fn auth_mgr_from_auth_json(
auth_json: AuthDotJson,
) -> Result<(Arc<AuthManager>, PathBuf)> {
let store_mode = codex_login::AuthCredentialsStoreMode::Ephemeral;
let path = random_path_generator(None);
let path = random_path_generator(id_from_auth_json(&auth_json).ok());
// load auth.json
codex_login::save_auth(&path, &auth_json, store_mode)?;
let store_mode = save_auth_json_ephemeral(&path, auth_json)?;
// this must finish its work
// volatile ahh - codex login use a static map to do ts; alright sure
let auth_manager = AuthManager::shared(path.clone(), false, store_mode, None).await; // C ahh arguments
Ok((auth_manager, path))
}
pub fn save_auth_json_ephemeral(
home_path: &Path,
auth_json: AuthDotJson,
) -> Result<AuthCredentialsStoreMode, anyhow::Error> {
let store_mode = AuthCredentialsStoreMode::Ephemeral;
codex_login::save_auth(home_path, &auth_json, store_mode)?;
Ok(store_mode)
}
pub fn save_auth_json_file(
home_path: &Path,
auth_json: AuthDotJson,
) -> Result<AuthCredentialsStoreMode, anyhow::Error> {
let store_mode = AuthCredentialsStoreMode::File;
codex_login::save_auth(home_path, &auth_json, store_mode)?;
Ok(store_mode)
}
/// quota should bundle with plan type. but for now, we can get the plan type separately like this.
pub async fn get_plan(auth_mgr: &AuthManager) -> anyhow::Result<Option<AccountPlanType>> {
let plan = auth_mgr
@@ -225,3 +266,64 @@ pub async fn get_plan(auth_mgr: &AuthManager) -> anyhow::Result<Option<AccountPl
.account_plan_type();
Ok(plan)
}
// this is basically a logout; the auth manager didnt know it yet.
// the instant authmanager reaches reload or something, it will not see the
// file, and thus be logged out.
pub async fn remove_auth_json_from_store(
store_mode: AuthCredentialsStoreMode,
codex_home: &Path,
) -> anyhow::Result<bool> {
codex_login::auth::logout(codex_home, store_mode)
.context("Failed to remove auth.json from store")
}
pub async fn delete_auth_json(path: &Path) -> anyhow::Result<()> {
remove_auth_json_from_store(AuthCredentialsStoreMode::Ephemeral, path).await?;
Ok(())
}
/// oohhh this doesnt support anything but chatgpt auth for now, rough! when i
/// see more auth types, ill add support for them. but for now, this is good
/// enough for my use case.
pub fn id_from_auth_json(auth_json: &AuthDotJson) -> anyhow::Result<String> {
// since i dont know a lot about the auth.json file, ill do this for now.
if Some(AuthMode::Chatgpt) == auth_json.auth_mode {
Ok((auth_json.tokens.as_ref())
.map(|t| t.account_id.as_ref())
.ok_or_else(|| anyhow::anyhow!("accessToken not found in auth_data"))?
.ok_or_else(|| anyhow::anyhow!("account_id not found in tokens"))?
.to_string())
} else {
Err(anyhow::anyhow!(
"unsupported auth mode: {:?}",
auth_json.auth_mode
))
}
}
pub async fn id_from_auth_mgr(auth_mgr: &AuthManager) -> anyhow::Result<String> {
let auth = auth_mgr
.auth()
.await
.context("Failed to get auth info")?
.get_account_id()
.ok_or_else(|| anyhow::anyhow!("account_id not found in auth info"))?;
Ok(auth.to_string())
}
/// helper if you use our other functions
///
/// this pulls from the ephemeral store.
pub fn ephemeral_auth_json(path: &Path) -> anyhow::Result<AuthDotJson> {
auth_json(path, AuthCredentialsStoreMode::Ephemeral)
}
pub fn file_auth_json(path: &Path) -> anyhow::Result<AuthDotJson> {
auth_json(path, AuthCredentialsStoreMode::File)
}
pub fn auth_json(path: &Path, store_mode: AuthCredentialsStoreMode) -> anyhow::Result<AuthDotJson> {
codex_login::load_auth_dot_json(path, store_mode)?
.ok_or_else(|| anyhow::anyhow!("Failed to load auth.json from path"))
}
+2 -2
View File
@@ -1,9 +1,9 @@
use codexport::chatgpt_login_to_auth_json;
mod bin2;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let random_home = codexport::random_path_generator(Some("me".to_string()));
let auth_json = chatgpt_login_to_auth_json(&random_home).await?;
let auth_json = chatgpt_login_to_auth_json(&random_home, None).await?;
let mgr = codexport::auth_manager(
&random_home,
codex_config::types::AuthCredentialsStoreMode::Ephemeral,