Skip to content

Commit 4ef0ad0

Browse files
committed
refactor: unify CLI session flow and remove dead settings/OAuth paths
1 parent 139fbe6 commit 4ef0ad0

File tree

19 files changed

+285
-945
lines changed

19 files changed

+285
-945
lines changed

packages/agents/claude/client.ts

Lines changed: 8 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ import {
77
runCliJsonCommand,
88
type SessionEnvironment as RuntimeSessionEnvironment,
99
} from "../runtime/base";
10-
import { getOrCreateThreadSession } from "../runtime/thread-session";
10+
import { createCliThreadSessionManager } from "../runtime/cli-session";
1111
import type {
1212
OpenCodeMessage,
1313
OpenCodeMessageContext,
1414
OpenCodeOptions,
15-
OpenCodeSessionInfo,
1615
} from "../types";
1716

1817
export type SessionEnvironment = RuntimeSessionEnvironment;
@@ -50,52 +49,13 @@ function isValidUuid(value: string): boolean {
5049
return uuidRegex.test(value);
5150
}
5251

53-
export async function createSession(workingPath: string, env?: SessionEnvironment): Promise<string> {
54-
const sessionId = crypto.randomUUID();
55-
runtime.setSessionEnvironment(sessionId, env ?? {});
56-
newSessions.add(sessionId);
57-
log.info("Created Claude session", { sessionId, workingPath });
58-
return sessionId;
59-
}
60-
61-
export async function getOrCreateSession(
62-
channelId: string,
63-
threadId: string,
64-
workingPath: string,
65-
env: SessionEnvironment = {}
66-
): Promise<OpenCodeSessionInfo> {
67-
return getOrCreateThreadSession({
68-
channelId,
69-
threadId,
70-
providerId: "claudecode",
71-
workingPath,
72-
env,
73-
createSession,
74-
getSessionEnvironment: (sessionId) => runtime.getSessionEnvironment(sessionId),
75-
setSessionEnvironment: (sessionId, nextEnv) => {
76-
runtime.setSessionEnvironment(sessionId, nextEnv);
77-
},
78-
validateSessionId: isValidUuid,
79-
onInvalidSessionId: (existingSession) => {
80-
log.info("Invalid Claude session id found; generating new session", {
81-
channelId,
82-
threadId,
83-
workingPath,
84-
existingSession,
85-
});
86-
},
87-
onEnvironmentChanged: () => {
88-
log.info("Claude session environment changed; creating new session", {
89-
channelId,
90-
threadId,
91-
workingPath,
92-
});
93-
},
94-
onCreatingSession: () => {
95-
log.info("Creating new Claude session for thread", { channelId, threadId, workingPath });
96-
},
97-
});
98-
}
52+
export const { createSession, getOrCreateSession } = createCliThreadSessionManager({
53+
providerId: "claudecode",
54+
providerName: "Claude",
55+
runtime,
56+
newSessions,
57+
validateSessionId: isValidUuid,
58+
});
9959

10060
function extractJsonPayload(output: string): string {
10161
const trimmed = output.trim();

packages/agents/codex/client.ts

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,19 @@ import {
88
runCliJsonCommand,
99
type SessionEnvironment as RuntimeSessionEnvironment,
1010
} from "../runtime/base";
11-
import { getOrCreateThreadSession } from "../runtime/thread-session";
11+
import { createCliThreadSessionManager } from "../runtime/cli-session";
1212
import type {
1313
OpenCodeMessage,
1414
OpenCodeMessageContext,
1515
OpenCodeOptions,
16-
OpenCodeSessionInfo,
1716
} from "../types";
1817

1918
const runtime = new CliAgentRuntime("Codex");
19+
export const { createSession, getOrCreateSession } = createCliThreadSessionManager({
20+
providerId: "codex",
21+
providerName: "Codex",
22+
runtime,
23+
});
2024

2125
export type SessionEnvironment = RuntimeSessionEnvironment;
2226

@@ -153,43 +157,6 @@ function parseCodexResponse(output: string): {
153157
return { text, threadId };
154158
}
155159

156-
export async function createSession(workingPath: string, env?: SessionEnvironment): Promise<string> {
157-
const sessionId = crypto.randomUUID();
158-
runtime.setSessionEnvironment(sessionId, env ?? {});
159-
log.info("Created Codex session", { sessionId, workingPath });
160-
return sessionId;
161-
}
162-
163-
export async function getOrCreateSession(
164-
channelId: string,
165-
threadId: string,
166-
workingPath: string,
167-
env: SessionEnvironment = {}
168-
): Promise<OpenCodeSessionInfo> {
169-
return getOrCreateThreadSession({
170-
channelId,
171-
threadId,
172-
providerId: "codex",
173-
workingPath,
174-
env,
175-
createSession,
176-
getSessionEnvironment: (sessionId) => runtime.getSessionEnvironment(sessionId),
177-
setSessionEnvironment: (sessionId, nextEnv) => {
178-
runtime.setSessionEnvironment(sessionId, nextEnv);
179-
},
180-
onEnvironmentChanged: () => {
181-
log.info("Codex session environment changed; creating new session", {
182-
channelId,
183-
threadId,
184-
workingPath,
185-
});
186-
},
187-
onCreatingSession: () => {
188-
log.info("Creating new Codex session for thread", { channelId, threadId, workingPath });
189-
},
190-
});
191-
}
192-
193160
export async function sendMessage(
194161
channelId: string,
195162
sessionId: string,

packages/agents/gemini/client.ts

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ import {
88
runCliJsonCommand,
99
type SessionEnvironment as RuntimeSessionEnvironment,
1010
} from "../runtime/base";
11-
import { getOrCreateThreadSession } from "../runtime/thread-session";
11+
import { createCliThreadSessionManager } from "../runtime/cli-session";
1212
import type {
1313
OpenCodeMessage,
1414
OpenCodeMessageContext,
1515
OpenCodeOptions,
16-
OpenCodeSessionInfo,
1716
} from "../types";
1817

1918
export type SessionEnvironment = RuntimeSessionEnvironment;
@@ -39,6 +38,12 @@ type GeminiJsonRecord = {
3938

4039
const runtime = new CliAgentRuntime("Gemini");
4140
const newSessions = new Set<string>();
41+
export const { createSession, getOrCreateSession } = createCliThreadSessionManager({
42+
providerId: "gemini",
43+
providerName: "Gemini",
44+
runtime,
45+
newSessions,
46+
});
4247

4348
function resolveGeminiBinary(): string {
4449
if (typeof Bun !== "undefined" && Bun.which("gemini")) return "gemini";
@@ -158,44 +163,6 @@ function parseGeminiResponse(output: string): {
158163
return { text, sessionId };
159164
}
160165

161-
export async function createSession(workingPath: string, env?: SessionEnvironment): Promise<string> {
162-
const sessionId = crypto.randomUUID();
163-
runtime.setSessionEnvironment(sessionId, env ?? {});
164-
newSessions.add(sessionId);
165-
log.info("Created Gemini session", { sessionId, workingPath });
166-
return sessionId;
167-
}
168-
169-
export async function getOrCreateSession(
170-
channelId: string,
171-
threadId: string,
172-
workingPath: string,
173-
env: SessionEnvironment = {}
174-
): Promise<OpenCodeSessionInfo> {
175-
return getOrCreateThreadSession({
176-
channelId,
177-
threadId,
178-
providerId: "gemini",
179-
workingPath,
180-
env,
181-
createSession,
182-
getSessionEnvironment: (sessionId) => runtime.getSessionEnvironment(sessionId),
183-
setSessionEnvironment: (sessionId, nextEnv) => {
184-
runtime.setSessionEnvironment(sessionId, nextEnv);
185-
},
186-
onEnvironmentChanged: () => {
187-
log.info("Gemini session environment changed; creating new session", {
188-
channelId,
189-
threadId,
190-
workingPath,
191-
});
192-
},
193-
onCreatingSession: () => {
194-
log.info("Creating new Gemini session for thread", { channelId, threadId, workingPath });
195-
},
196-
});
197-
}
198-
199166
export async function sendMessage(
200167
channelId: string,
201168
sessionId: string,

packages/agents/goose/client.ts

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ import {
88
runCliJsonCommand,
99
type SessionEnvironment as RuntimeSessionEnvironment,
1010
} from "../runtime/base";
11-
import { getOrCreateThreadSession } from "../runtime/thread-session";
11+
import { createCliThreadSessionManager } from "../runtime/cli-session";
1212
import type {
1313
OpenCodeMessage,
1414
OpenCodeMessageContext,
1515
OpenCodeOptions,
16-
OpenCodeSessionInfo,
1716
} from "../types";
1817

1918
export type SessionEnvironment = RuntimeSessionEnvironment;
@@ -43,6 +42,12 @@ type GooseJsonRecord = {
4342

4443
const runtime = new CliAgentRuntime("Goose");
4544
const newSessions = new Set<string>();
45+
export const { createSession, getOrCreateSession } = createCliThreadSessionManager({
46+
providerId: "goose",
47+
providerName: "Goose",
48+
runtime,
49+
newSessions,
50+
});
4651

4752
function resolveGooseBinary(): string {
4853
if (typeof Bun !== "undefined" && Bun.which("goose")) return "goose";
@@ -192,44 +197,6 @@ export function parseGooseResponse(output: string): {
192197
return { text, sessionId };
193198
}
194199

195-
export async function createSession(workingPath: string, env?: SessionEnvironment): Promise<string> {
196-
const sessionId = crypto.randomUUID();
197-
runtime.setSessionEnvironment(sessionId, env ?? {});
198-
newSessions.add(sessionId);
199-
log.info("Created Goose session", { sessionId, workingPath });
200-
return sessionId;
201-
}
202-
203-
export async function getOrCreateSession(
204-
channelId: string,
205-
threadId: string,
206-
workingPath: string,
207-
env: SessionEnvironment = {}
208-
): Promise<OpenCodeSessionInfo> {
209-
return getOrCreateThreadSession({
210-
channelId,
211-
threadId,
212-
providerId: "goose",
213-
workingPath,
214-
env,
215-
createSession,
216-
getSessionEnvironment: (sessionId) => runtime.getSessionEnvironment(sessionId),
217-
setSessionEnvironment: (sessionId, nextEnv) => {
218-
runtime.setSessionEnvironment(sessionId, nextEnv);
219-
},
220-
onEnvironmentChanged: () => {
221-
log.info("Goose session environment changed; creating new session", {
222-
channelId,
223-
threadId,
224-
workingPath,
225-
});
226-
},
227-
onCreatingSession: () => {
228-
log.info("Creating new Goose session for thread", { channelId, threadId, workingPath });
229-
},
230-
});
231-
}
232-
233200
export async function sendMessage(
234201
channelId: string,
235202
sessionId: string,

packages/agents/kilo/client.ts

Lines changed: 10 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ import {
88
runCliJsonCommand,
99
type SessionEnvironment as RuntimeSessionEnvironment,
1010
} from "../runtime/base";
11-
import { getOrCreateThreadSession } from "../runtime/thread-session";
11+
import { createCliThreadSessionManager } from "../runtime/cli-session";
1212
import type {
1313
OpenCodeMessage,
1414
OpenCodeMessageContext,
1515
OpenCodeOptions,
16-
OpenCodeSessionInfo,
1716
} from "../types";
1817

1918
export type SessionEnvironment = RuntimeSessionEnvironment;
@@ -82,6 +81,15 @@ function isValidKiloSessionId(value: string): boolean {
8281
return value.startsWith("ses");
8382
}
8483

84+
export const { createSession, getOrCreateSession } = createCliThreadSessionManager({
85+
providerId: "kilo",
86+
providerName: "Kilo",
87+
runtime,
88+
newSessions,
89+
sessionIdFactory: buildKiloSessionId,
90+
validateSessionId: isValidKiloSessionId,
91+
});
92+
8593
function buildModelArg(model?: OpenCodeOptions["model"]): string | undefined {
8694
if (!model?.modelID) return undefined;
8795
const providerID = model.providerID?.trim() || "openai";
@@ -282,53 +290,6 @@ function extractKiloFinalResponse(output: string): string {
282290
return text || cleaned.trim();
283291
}
284292

285-
export async function createSession(workingPath: string, env?: SessionEnvironment): Promise<string> {
286-
const sessionId = buildKiloSessionId();
287-
runtime.setSessionEnvironment(sessionId, env ?? {});
288-
newSessions.add(sessionId);
289-
log.info("Created Kilo session", { sessionId, workingPath });
290-
return sessionId;
291-
}
292-
293-
export async function getOrCreateSession(
294-
channelId: string,
295-
threadId: string,
296-
workingPath: string,
297-
env: SessionEnvironment = {}
298-
): Promise<OpenCodeSessionInfo> {
299-
return getOrCreateThreadSession({
300-
channelId,
301-
threadId,
302-
providerId: "kilo",
303-
workingPath,
304-
env,
305-
createSession,
306-
getSessionEnvironment: (sessionId) => runtime.getSessionEnvironment(sessionId),
307-
setSessionEnvironment: (sessionId, nextEnv) => {
308-
runtime.setSessionEnvironment(sessionId, nextEnv);
309-
},
310-
validateSessionId: isValidKiloSessionId,
311-
onInvalidSessionId: (existingSession) => {
312-
log.info("Invalid Kilo session id found; generating new session", {
313-
channelId,
314-
threadId,
315-
workingPath,
316-
existingSession,
317-
});
318-
},
319-
onEnvironmentChanged: () => {
320-
log.info("Kilo session environment changed; creating new session", {
321-
channelId,
322-
threadId,
323-
workingPath,
324-
});
325-
},
326-
onCreatingSession: () => {
327-
log.info("Creating new Kilo session for thread", { channelId, threadId, workingPath });
328-
},
329-
});
330-
}
331-
332293
export async function sendMessage(
333294
channelId: string,
334295
sessionId: string,

0 commit comments

Comments
 (0)