MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / QodexAgentRunner

Class QodexAgentRunner

src/bot/runner.ts:29–174  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

27 permissions: PermissionEngine;
28 cwd: string;
29}
30
31export class QodexAgentRunner implements AgentRunner {
32 private map = new SessionMap();
33 private modelByKey = new Map<string, string>(); // per-conversation model override (/model)
34 private autoByKey = new Map<string, boolean>(); // per-conversation auto-approve (/auto)
35 constructor(private deps: RunnerDeps) {}
36
37 async reset(convKey: string): Promise<void> {
38 await this.map.clear(convKey);
39 }
40
41 private modelFor(convKey: string): string {
42 return this.modelByKey.get(convKey) ?? this.deps.config.defaults.model;
43 }
44
45 /**
46 * Working root for this conversation. After `/continue` or `/resume` this is
47 * the session's cwd (the CLI project), not wherever `qodex bot` was launched.
48 */
49 private cwdFor(sessionId: string | undefined): string {
50 const sessionCwd = sessionId ? getSessionStore().loadSession(sessionId)?.meta.cwd : undefined;
51 return pickWorkingCwd({ sessionCwd, hostCwd: this.deps.cwd });
52 }
53
54 async status(convKey: string): Promise<RunnerStatus> {
55 const sessionId = (await this.map.get(convKey)) ?? undefined;
56 return { model: this.modelFor(convKey), cwd: this.cwdFor(sessionId), sessionId, auto: this.autoByKey.get(convKey) ?? false };
57 }
58
59 async setModel(convKey: string, model: string): Promise<string> {
60 this.modelByKey.set(convKey, model);
61 return model;
62 }
63
64 async setAuto(convKey: string, on: boolean): Promise<void> {
65 this.autoByKey.set(convKey, on);
66 }
67
68 async listSessions(convKey?: string, limit = 8): Promise<{ id: string; title: string; when: string }[]> {
69 const sid = convKey ? await this.map.get(convKey) : undefined;
70 return getSessionStore().listRecentSessions(limit, this.cwdFor(sid)).map(s => ({
71 id: s.id,
72 title: s.title?.trim() || `${s.turn_count} turn${s.turn_count === 1 ? '' : 's'}`,
73 when: relTime(s.updated_at),
74 }));
75 }
76
77 async listEpisodes(convKey?: string, limit = 8): Promise<{ when: string; prompt: string; summary: string }[]> {
78 const { readEpisodes } = await import('../context/episodic-memory.js');
79 const sid = convKey ? await this.map.get(convKey) : undefined;
80 const eps = await readEpisodes(this.cwdFor(sid));
81 return eps.slice(-limit).reverse().map(e => ({ when: relTime(e.ts), prompt: e.prompt, summary: e.summary }));
82 }
83
84 /** Rebind a conversation to a past session by full id OR short prefix (as shown by /sessions). */
85 async resume(convKey: string, idOrPrefix: string): Promise<boolean> {
86 const store = getSessionStore();

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected