mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-19 21:00:33 +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,6 +620,7 @@ fn run_opencode(cli: &CliConfig, args: &OpencodeArgs) -> Result<(), CliError> {
|
||||||
crate::daemon::ensure_running(cli, &args.host, args.port, token.as_deref())?;
|
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: daemon is healthy")?;
|
||||||
|
|
||||||
|
let attach_session_id = if args.session_title.is_some() || yolo {
|
||||||
write_stderr_line("gigacode startup: creating OpenCode session via /opencode/session")?;
|
write_stderr_line("gigacode startup: creating OpenCode session via /opencode/session")?;
|
||||||
let session_id = create_opencode_session(
|
let session_id = create_opencode_session(
|
||||||
&base_url,
|
&base_url,
|
||||||
|
|
@ -628,6 +629,11 @@ fn run_opencode(cli: &CliConfig, args: &OpencodeArgs) -> Result<(), CliError> {
|
||||||
yolo,
|
yolo,
|
||||||
)?;
|
)?;
|
||||||
write_stdout_line(&format!("OpenCode session: {session_id}"))?;
|
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");
|
let attach_url = format!("{base_url}/opencode");
|
||||||
write_stderr_line("gigacode startup: resolving OpenCode binary (installing if needed)")?;
|
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
|
opencode_cmd
|
||||||
.arg("attach")
|
.arg("attach")
|
||||||
.arg(&attach_url)
|
.arg(&attach_url)
|
||||||
.arg("--session")
|
|
||||||
.arg(&session_id)
|
|
||||||
.stdin(Stdio::inherit())
|
.stdin(Stdio::inherit())
|
||||||
.stdout(Stdio::inherit())
|
.stdout(Stdio::inherit())
|
||||||
.stderr(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() {
|
if let Some(token) = token.as_deref() {
|
||||||
opencode_cmd.arg("--password").arg(token);
|
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 {
|
async fn oc_session_list(State(state): State<Arc<OpenCodeAppState>>) -> impl IntoResponse {
|
||||||
let sessions = state.inner.session_manager().list_sessions().await;
|
let sessions = state.inner.session_manager().list_sessions().await;
|
||||||
let project_id = &state.opencode.default_project_id;
|
let project_id = &state.opencode.default_project_id;
|
||||||
let values: Vec<Value> = sessions
|
let mut values: Vec<Value> = sessions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| session_info_to_opencode_value(s, project_id))
|
.map(|s| session_info_to_opencode_value(s, project_id))
|
||||||
.collect();
|
.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)))
|
(StatusCode::OK, Json(json!(values)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3829,6 +3839,10 @@ async fn oc_session_get(
|
||||||
)
|
)
|
||||||
.into_response();
|
.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()
|
not_found("Session not found").into_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -291,6 +291,41 @@ describe("OpenCode-compatible Session API", () => {
|
||||||
expect(response.data?.title).toBe("Test");
|
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 () => {
|
it("should return error for non-existent session", async () => {
|
||||||
const response = await client.session.get({
|
const response = await client.session.get({
|
||||||
path: { id: "non-existent-session-id" },
|
path: { id: "non-existent-session-id" },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue