mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 10:05:18 +00:00
fix: stop precreating opencode session and harden session lookup
This commit is contained in:
parent
fc7abd13f0
commit
48749ef3bf
3 changed files with 67 additions and 11 deletions
|
|
@ -620,14 +620,20 @@ fn run_opencode(cli: &CliConfig, args: &OpencodeArgs) -> Result<(), CliError> {
|
|||
crate::daemon::ensure_running(cli, &args.host, args.port, token.as_deref())?;
|
||||
write_stderr_line("gigacode startup: daemon is healthy")?;
|
||||
|
||||
write_stderr_line("gigacode startup: creating OpenCode session via /opencode/session")?;
|
||||
let session_id = create_opencode_session(
|
||||
&base_url,
|
||||
token.as_deref(),
|
||||
args.session_title.as_deref(),
|
||||
yolo,
|
||||
)?;
|
||||
write_stdout_line(&format!("OpenCode session: {session_id}"))?;
|
||||
let attach_session_id = if args.session_title.is_some() || yolo {
|
||||
write_stderr_line("gigacode startup: creating OpenCode session via /opencode/session")?;
|
||||
let session_id = create_opencode_session(
|
||||
&base_url,
|
||||
token.as_deref(),
|
||||
args.session_title.as_deref(),
|
||||
yolo,
|
||||
)?;
|
||||
write_stdout_line(&format!("OpenCode session: {session_id}"))?;
|
||||
Some(session_id)
|
||||
} else {
|
||||
write_stderr_line("gigacode startup: attaching OpenCode without precreating a session")?;
|
||||
None
|
||||
};
|
||||
|
||||
let attach_url = format!("{base_url}/opencode");
|
||||
write_stderr_line("gigacode startup: resolving OpenCode binary (installing if needed)")?;
|
||||
|
|
@ -640,11 +646,12 @@ fn run_opencode(cli: &CliConfig, args: &OpencodeArgs) -> Result<(), CliError> {
|
|||
opencode_cmd
|
||||
.arg("attach")
|
||||
.arg(&attach_url)
|
||||
.arg("--session")
|
||||
.arg(&session_id)
|
||||
.stdin(Stdio::inherit())
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit());
|
||||
if let Some(session_id) = attach_session_id.as_deref() {
|
||||
opencode_cmd.arg("--session").arg(session_id);
|
||||
}
|
||||
if let Some(token) = token.as_deref() {
|
||||
opencode_cmd.arg("--password").arg(token);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3796,10 +3796,20 @@ async fn oc_session_create(
|
|||
async fn oc_session_list(State(state): State<Arc<OpenCodeAppState>>) -> impl IntoResponse {
|
||||
let sessions = state.inner.session_manager().list_sessions().await;
|
||||
let project_id = &state.opencode.default_project_id;
|
||||
let values: Vec<Value> = sessions
|
||||
let mut values: Vec<Value> = sessions
|
||||
.iter()
|
||||
.map(|s| session_info_to_opencode_value(s, project_id))
|
||||
.collect();
|
||||
let mut seen_session_ids: HashSet<String> = sessions
|
||||
.iter()
|
||||
.map(|session| session.session_id.clone())
|
||||
.collect();
|
||||
let compat_sessions = state.opencode.sessions.lock().await;
|
||||
for (session_id, session) in compat_sessions.iter() {
|
||||
if seen_session_ids.insert(session_id.clone()) {
|
||||
values.push(session.to_value());
|
||||
}
|
||||
}
|
||||
(StatusCode::OK, Json(json!(values)))
|
||||
}
|
||||
|
||||
|
|
@ -3829,6 +3839,10 @@ async fn oc_session_get(
|
|||
)
|
||||
.into_response();
|
||||
}
|
||||
let sessions = state.opencode.sessions.lock().await;
|
||||
if let Some(session) = sessions.get(&session_id) {
|
||||
return (StatusCode::OK, Json(session.to_value())).into_response();
|
||||
}
|
||||
not_found("Session not found").into_response()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -291,6 +291,41 @@ describe("OpenCode-compatible Session API", () => {
|
|||
expect(response.data?.title).toBe("Test");
|
||||
});
|
||||
|
||||
it("should keep session.get available during first prompt after /new-style creation", async () => {
|
||||
const providers = await getProvidersViaHttp();
|
||||
const providerId = providers.connected.find(
|
||||
(provider) => provider !== "mock" && typeof providers.default?.[provider] === "string"
|
||||
);
|
||||
if (!providerId) {
|
||||
return;
|
||||
}
|
||||
const modelId = providers.default?.[providerId];
|
||||
if (!modelId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const created = await client.session.create({ body: { title: "Race Repro" } });
|
||||
const sessionId = created.data?.id!;
|
||||
expect(sessionId).toBeDefined();
|
||||
|
||||
const promptPromise = client.session.prompt({
|
||||
path: { id: sessionId },
|
||||
body: {
|
||||
model: { providerID: providerId, modelID: modelId },
|
||||
parts: [{ type: "text", text: "hello after /new" }],
|
||||
},
|
||||
});
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 25));
|
||||
|
||||
const getDuringPrompt = await client.session.get({ path: { id: sessionId } });
|
||||
expect(getDuringPrompt.error).toBeUndefined();
|
||||
expect(getDuringPrompt.data?.id).toBe(sessionId);
|
||||
|
||||
// Best-effort settle; this assertion focuses on availability during the in-flight turn.
|
||||
await promptPromise;
|
||||
});
|
||||
|
||||
it("should return error for non-existent session", async () => {
|
||||
const response = await client.session.get({
|
||||
path: { id: "non-existent-session-id" },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue