Add Codex JSON sessions and usage limits
This commit is contained in:
1 parent
0862b47f76
commit
6a0202b1b5
14 files changed
+1173
-52
No files matched your search
@@ -101,6 +101,83 @@ pub enum Transport {
|
||||
}
|
||||
|
||||
impl Transport {
|
||||
/// Exchanges newline-delimited JSON requests with a short-lived stdio
|
||||
/// server. `initial` is written first; after its response arrives,
|
||||
/// `requests` is written and the response bearing `wanted_id` is returned.
|
||||
///
|
||||
/// This is the shape Codex's app-server requires for a usage read: an
|
||||
/// initialize round trip must finish before the initialized notification
|
||||
/// and account request are accepted.
|
||||
pub fn request_json_blocking(
|
||||
&self,
|
||||
launch: &Launch,
|
||||
initial: &serde_json::Value,
|
||||
requests: &[serde_json::Value],
|
||||
wanted_id: u64,
|
||||
) -> Result<serde_json::Value> {
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
|
||||
let host = match self {
|
||||
Self::Here => None,
|
||||
Self::Ssh { ssh, .. } => Some(ssh),
|
||||
};
|
||||
let mut command = crate::ssh::command(
|
||||
host,
|
||||
&launch.program,
|
||||
&launch.args,
|
||||
launch.cwd.as_deref(),
|
||||
launch.forward,
|
||||
);
|
||||
command
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped());
|
||||
let mut child = command
|
||||
.spawn()
|
||||
.with_context(|| format!("couldn't run \"{}\" {}", launch.program, self.describe()))?;
|
||||
let mut stdin = child.stdin.take().context("the JSON server has no stdin")?;
|
||||
let stdout = child
|
||||
.stdout
|
||||
.take()
|
||||
.context("the JSON server has no stdout")?;
|
||||
writeln!(stdin, "{initial}")?;
|
||||
stdin.flush()?;
|
||||
let mut reader = BufReader::new(stdout);
|
||||
let mut line = String::new();
|
||||
loop {
|
||||
line.clear();
|
||||
if reader.read_line(&mut line)? == 0 {
|
||||
anyhow::bail!("the JSON server exited before initialization completed");
|
||||
}
|
||||
let Ok(value) = serde_json::from_str::<serde_json::Value>(&line) else {
|
||||
continue;
|
||||
};
|
||||
if value.get("id").and_then(serde_json::Value::as_u64)
|
||||
== initial.get("id").and_then(serde_json::Value::as_u64)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
for request in requests {
|
||||
writeln!(stdin, "{request}")?;
|
||||
}
|
||||
stdin.flush()?;
|
||||
loop {
|
||||
line.clear();
|
||||
if reader.read_line(&mut line)? == 0 {
|
||||
anyhow::bail!("the JSON server exited before answering request {wanted_id}");
|
||||
}
|
||||
let Ok(value) = serde_json::from_str::<serde_json::Value>(&line) else {
|
||||
continue;
|
||||
};
|
||||
if value.get("id").and_then(serde_json::Value::as_u64) == Some(wanted_id) {
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
return Ok(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The transport a setup describes; a setup with no `ssh` is here.
|
||||
pub fn for_setup(setup: &crate::config::SetupConfig) -> Self {
|
||||
match &setup.ssh {
|
||||
|
||||
Reference in new issue
Block a user