mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
fix(tui/input): normalize KeyEvent kind on non-enhanced terminals to restore typing on Git Bash/mintty (Windows)
This maps Release-only key events to Press when keyboard enhancement flags are unsupported, fixing unresponsive input and Ctrl+C on some Windows terminals. Closes #18. Closes #14.
This commit is contained in:
+5
-1
@@ -25,9 +25,13 @@ Help us improve by filing issues or submitting PRs (see the section below for ho
|
||||
Install globally:
|
||||
|
||||
```shell
|
||||
npm install -g @openai/codex
|
||||
npm install -g @just-every/code
|
||||
```
|
||||
|
||||
Note: The old package name `@just-every/coder` is deprecated and no longer
|
||||
receives updates. If you installed that in the past, please switch to
|
||||
`@just-every/code` to get the latest releases.
|
||||
|
||||
Next, set your OpenAI API key as an environment variable:
|
||||
|
||||
```shell
|
||||
|
||||
@@ -27,13 +27,12 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vscode/ripgrep": "^1.15.14"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.3.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@vscode/ripgrep": "^1.15.14",
|
||||
"@just-every/code-darwin-arm64": "0.2.56",
|
||||
"@just-every/code-darwin-x64": "0.2.56",
|
||||
"@just-every/code-linux-x64-musl": "0.2.56",
|
||||
|
||||
@@ -16,7 +16,7 @@ pub(crate) async fn chatgpt_get_request<T: DeserializeOwned>(
|
||||
init_chatgpt_token_from_auth(&config.codex_home).await?;
|
||||
|
||||
// Make direct HTTP request to ChatGPT backend API with the token
|
||||
let client = reqwest::Client::new();
|
||||
let client = codex_core::http_client::build_http_client();
|
||||
let url = format!("{chatgpt_base_url}{path}");
|
||||
|
||||
let token =
|
||||
|
||||
@@ -96,7 +96,7 @@ impl ModelClient {
|
||||
Self {
|
||||
config,
|
||||
auth_manager,
|
||||
client: reqwest::Client::new(),
|
||||
client: crate::http_client::build_http_client(),
|
||||
provider,
|
||||
session_id,
|
||||
effort,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Build a reqwest Client with optional extra root certificates loaded from
|
||||
/// common environment variables (SSL_CERT_FILE, REQUESTS_CA_BUNDLE,
|
||||
/// NODE_EXTRA_CA_CERTS). This helps environments using corporate/mitm proxies
|
||||
/// whose CAs are distributed via system config or user-provided files.
|
||||
pub fn build_http_client() -> reqwest::Client {
|
||||
let mut builder = reqwest::Client::builder();
|
||||
|
||||
// Helper to load a PEM or DER certificate file if it exists and is readable.
|
||||
fn load_cert(path: PathBuf) -> Option<reqwest::Certificate> {
|
||||
if !path.exists() || !path.is_file() {
|
||||
return None;
|
||||
}
|
||||
let bytes = fs::read(&path).ok()?;
|
||||
reqwest::Certificate::from_pem(&bytes)
|
||||
.or_else(|_| reqwest::Certificate::from_der(&bytes))
|
||||
.ok()
|
||||
}
|
||||
|
||||
// Single-file variables (common across ecosystems)
|
||||
for var in ["SSL_CERT_FILE", "REQUESTS_CA_BUNDLE", "NODE_EXTRA_CA_CERTS"] {
|
||||
if let Ok(val) = std::env::var(var) {
|
||||
if !val.trim().is_empty() {
|
||||
if let Some(cert) = load_cert(PathBuf::from(val)) {
|
||||
builder = builder.add_root_certificate(cert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Directory of certs (PEM/CRT). Iterate best-effort.
|
||||
if let Ok(dir) = std::env::var("SSL_CERT_DIR") {
|
||||
let path = PathBuf::from(dir);
|
||||
if path.is_dir() {
|
||||
if let Ok(rd) = fs::read_dir(path) {
|
||||
for entry in rd.flatten() {
|
||||
let p = entry.path();
|
||||
if p.extension().and_then(|s| s.to_str()).map(|s| matches!(s, "crt" | "pem" | "der")).unwrap_or(false) {
|
||||
if let Some(cert) = load_cert(p) {
|
||||
builder = builder.add_root_certificate(cert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.build().unwrap_or_else(|_| reqwest::Client::new())
|
||||
}
|
||||
@@ -69,6 +69,7 @@ pub mod user_agent;
|
||||
pub use rollout::list::ConversationsPage;
|
||||
mod user_notification;
|
||||
pub mod util;
|
||||
pub mod http_client;
|
||||
pub use apply_patch::CODEX_APPLY_PATCH_ARG1;
|
||||
pub use safety::get_platform_sandbox;
|
||||
// Use our local protocol definitions to preserve custom events and input items.
|
||||
|
||||
@@ -325,7 +325,7 @@ async fn exchange_code_for_tokens(
|
||||
refresh_token: String,
|
||||
}
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let client = codex_core::http_client::build_http_client();
|
||||
let resp = client
|
||||
.post(format!("{issuer}/oauth/token"))
|
||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||
@@ -494,7 +494,7 @@ async fn obtain_api_key(issuer: &str, client_id: &str, id_token: &str) -> io::Re
|
||||
struct ExchangeResp {
|
||||
access_token: String,
|
||||
}
|
||||
let client = reqwest::Client::new();
|
||||
let client = codex_core::http_client::build_http_client();
|
||||
let resp = client
|
||||
.post(format!("{issuer}/oauth/token"))
|
||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
@@ -363,7 +363,14 @@ impl App<'_> {
|
||||
widget.on_commit_tick();
|
||||
}
|
||||
}
|
||||
AppEvent::KeyEvent(key_event) => {
|
||||
AppEvent::KeyEvent(mut key_event) => {
|
||||
// On terminals that do not support keyboard enhancement flags
|
||||
// (notably some Windows Git Bash/mintty setups), crossterm may
|
||||
// report only Release events. Normalize such events to Press so
|
||||
// keys register consistently.
|
||||
if !self.enhanced_keys_supported {
|
||||
key_event = KeyEvent::new(key_event.code, key_event.modifiers);
|
||||
}
|
||||
// Reset double‑Esc timer on any non‑Esc key
|
||||
if !matches!(key_event.code, KeyCode::Esc) {
|
||||
self.last_esc_time = None;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
Homebrew (macOS)
|
||||
|
||||
This repository now includes a helper script to generate a Homebrew formula
|
||||
from the latest GitHub release artifacts. Publishing to Homebrew requires a
|
||||
tap repository (for example, `just-every/homebrew-tap`). Once a tap exists,
|
||||
you can generate and publish the formula like so:
|
||||
|
||||
1) Generate the formula for the latest version:
|
||||
|
||||
```
|
||||
scripts/generate-homebrew-formula.sh
|
||||
```
|
||||
|
||||
2) Copy the generated `Code.rb` into your tap repo under `Formula/Code.rb`
|
||||
and update the `url`/`sha256` if needed.
|
||||
|
||||
3) Users can then install with:
|
||||
|
||||
```
|
||||
brew tap just-every/tap
|
||||
brew install code
|
||||
```
|
||||
|
||||
Notes
|
||||
|
||||
- The formula expects release assets named like:
|
||||
- `code-aarch64-apple-darwin.tar.gz`
|
||||
- `code-x86_64-apple-darwin.tar.gz`
|
||||
- The CLI is installed as `code` and `coder` shims for compatibility.
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Generate a minimal Homebrew formula from the latest GitHub release.
|
||||
# Writes Formula/Code.rb into the repo root (not a tap); you can copy it
|
||||
# into a tap repo to publish.
|
||||
|
||||
owner_repo="just-every/code"
|
||||
version="${1:-$(jq -r .version codex-cli/package.json)}"
|
||||
|
||||
assets=(
|
||||
"code-aarch64-apple-darwin.tar.gz"
|
||||
"code-x86_64-apple-darwin.tar.gz"
|
||||
)
|
||||
|
||||
mkdir -p Formula
|
||||
cat > Formula/Code.rb <<'RUBY'
|
||||
class Code < Formula
|
||||
desc "Terminal coding agent"
|
||||
homepage "https://github.com/just-every/code"
|
||||
RUBY
|
||||
|
||||
echo " version \"v${version}\"" >> Formula/Code.rb
|
||||
|
||||
cat >> Formula/Code.rb <<'RUBY'
|
||||
on_macos do
|
||||
if Hardware::CPU.arm?
|
||||
url "__URL_ARM64__"
|
||||
sha256 "__SHA_ARM64__"
|
||||
else
|
||||
url "__URL_X64__"
|
||||
sha256 "__SHA_X64__"
|
||||
end
|
||||
end
|
||||
|
||||
def install
|
||||
bin.install Dir["code-*"].first => "code"
|
||||
# Provide a compatibility shim
|
||||
(bin/"coder").write <<~EOS
|
||||
#!/bin/bash
|
||||
exec "#{bin}/code" "$@"
|
||||
EOS
|
||||
end
|
||||
|
||||
test do
|
||||
system "#{bin}/code", "--help"
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
for a in "${assets[@]}"; do
|
||||
url="https://github.com/${owner_repo}/releases/download/v${version}/${a}"
|
||||
tmp="/tmp/${a}"
|
||||
echo "Downloading ${url}..." >&2
|
||||
curl -fsSL "${url}" -o "${tmp}"
|
||||
sha=$(shasum -a 256 "${tmp}" | awk '{print $1}')
|
||||
if [[ "${a}" == *"aarch64-apple-darwin"* ]]; then
|
||||
sed -i.bak "s#__URL_ARM64__#${url}#" Formula/Code.rb
|
||||
sed -i.bak "s#__SHA_ARM64__#${sha}#" Formula/Code.rb
|
||||
else
|
||||
sed -i.bak "s#__URL_X64__#${url}#" Formula/Code.rb
|
||||
sed -i.bak "s#__SHA_X64__#${sha}#" Formula/Code.rb
|
||||
fi
|
||||
done
|
||||
|
||||
rm -f Formula/Code.rb.bak
|
||||
echo "Wrote Formula/Code.rb for v${version}" >&2
|
||||
|
||||
Reference in New Issue
Block a user