dev-sessions 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -0
- package/dist/backends/claude-tmux.d.ts +19 -0
- package/dist/backends/claude-tmux.js +162 -0
- package/dist/backends/claude-tmux.js.map +1 -0
- package/dist/backends/codex-appserver.d.ts +71 -0
- package/dist/backends/codex-appserver.js +839 -0
- package/dist/backends/codex-appserver.js.map +1 -0
- package/dist/champion-ids.d.ts +11 -0
- package/dist/champion-ids.js +51 -0
- package/dist/champion-ids.js.map +1 -0
- package/dist/cli.d.ts +33 -0
- package/dist/cli.js +307 -0
- package/dist/cli.js.map +1 -0
- package/dist/gateway/client.d.ts +31 -0
- package/dist/gateway/client.js +146 -0
- package/dist/gateway/client.js.map +1 -0
- package/dist/gateway/server.d.ts +27 -0
- package/dist/gateway/server.js +409 -0
- package/dist/gateway/server.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/session-manager.d.ts +36 -0
- package/dist/session-manager.js +407 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/session-store.d.ts +15 -0
- package/dist/session-store.js +143 -0
- package/dist/session-store.js.map +1 -0
- package/dist/transcript/claude-parser.d.ts +17 -0
- package/dist/transcript/claude-parser.js +203 -0
- package/dist/transcript/claude-parser.js.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
- package/skill/SKILL.md +141 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ClaudeTmuxBackend } from './backends/claude-tmux';
|
|
2
|
+
import { CodexAppServerBackend } from './backends/codex-appserver';
|
|
3
|
+
import { GatewaySessionManager } from './gateway/client';
|
|
4
|
+
import { SessionStore } from './session-store';
|
|
5
|
+
import { AgentTurnStatus, SessionCli, SessionMode, StoredSession, WaitResult } from './types';
|
|
6
|
+
export interface CreateSessionOptions {
|
|
7
|
+
path?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
cli?: SessionCli;
|
|
10
|
+
mode?: SessionMode;
|
|
11
|
+
model?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface WaitOptions {
|
|
14
|
+
timeoutSeconds?: number;
|
|
15
|
+
intervalSeconds?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class SessionManager {
|
|
18
|
+
private readonly store;
|
|
19
|
+
private readonly claudeBackend;
|
|
20
|
+
private readonly codexBackend;
|
|
21
|
+
constructor(store: SessionStore, claudeBackend: ClaudeTmuxBackend, codexBackend?: CodexAppServerBackend);
|
|
22
|
+
createSession(options: CreateSessionOptions): Promise<StoredSession>;
|
|
23
|
+
sendMessage(championId: string, message: string): Promise<void>;
|
|
24
|
+
killSession(championId: string): Promise<void>;
|
|
25
|
+
listSessions(): Promise<StoredSession[]>;
|
|
26
|
+
getLastAssistantTextBlocks(championId: string, count: number): Promise<string[]>;
|
|
27
|
+
getSessionStatus(championId: string): Promise<AgentTurnStatus>;
|
|
28
|
+
waitForSession(championId: string, options?: WaitOptions): Promise<WaitResult>;
|
|
29
|
+
private requireSession;
|
|
30
|
+
private findAvailableChampionId;
|
|
31
|
+
private sleep;
|
|
32
|
+
private hasActiveCodexSessions;
|
|
33
|
+
private hasAssistantResponseAtOrAfter;
|
|
34
|
+
}
|
|
35
|
+
export declare function shouldUseGatewaySessionManager(env?: NodeJS.ProcessEnv): boolean;
|
|
36
|
+
export declare function createDefaultSessionManager(env?: NodeJS.ProcessEnv): SessionManager | GatewaySessionManager;
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SessionManager = void 0;
|
|
7
|
+
exports.shouldUseGatewaySessionManager = shouldUseGatewaySessionManager;
|
|
8
|
+
exports.createDefaultSessionManager = createDefaultSessionManager;
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
|
+
const promises_1 = require("node:fs/promises");
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const champion_ids_1 = require("./champion-ids");
|
|
13
|
+
const claude_tmux_1 = require("./backends/claude-tmux");
|
|
14
|
+
const codex_appserver_1 = require("./backends/codex-appserver");
|
|
15
|
+
const client_1 = require("./gateway/client");
|
|
16
|
+
const session_store_1 = require("./session-store");
|
|
17
|
+
const claude_parser_1 = require("./transcript/claude-parser");
|
|
18
|
+
class SessionManager {
|
|
19
|
+
store;
|
|
20
|
+
claudeBackend;
|
|
21
|
+
codexBackend;
|
|
22
|
+
constructor(store, claudeBackend, codexBackend = new codex_appserver_1.CodexAppServerBackend()) {
|
|
23
|
+
this.store = store;
|
|
24
|
+
this.claudeBackend = claudeBackend;
|
|
25
|
+
this.codexBackend = codexBackend;
|
|
26
|
+
}
|
|
27
|
+
async createSession(options) {
|
|
28
|
+
const workspacePath = node_path_1.default.resolve(options.path ?? process.cwd());
|
|
29
|
+
const cli = options.cli ?? 'claude';
|
|
30
|
+
const championId = await this.findAvailableChampionId();
|
|
31
|
+
const timestamp = new Date().toISOString();
|
|
32
|
+
let session;
|
|
33
|
+
if (cli === 'codex') {
|
|
34
|
+
const model = options.model ?? 'gpt-5.3-codex';
|
|
35
|
+
const codexSession = await this.codexBackend.createSession(championId, workspacePath, model);
|
|
36
|
+
session = {
|
|
37
|
+
championId,
|
|
38
|
+
internalId: codexSession.threadId,
|
|
39
|
+
cli: 'codex',
|
|
40
|
+
mode: 'native',
|
|
41
|
+
path: workspacePath,
|
|
42
|
+
description: options.description,
|
|
43
|
+
status: 'active',
|
|
44
|
+
appServerPid: codexSession.appServerPid,
|
|
45
|
+
appServerPort: codexSession.appServerPort,
|
|
46
|
+
model: codexSession.model,
|
|
47
|
+
codexTurnInProgress: false,
|
|
48
|
+
lastAssistantMessages: [],
|
|
49
|
+
createdAt: timestamp,
|
|
50
|
+
lastUsed: timestamp
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const mode = options.mode ?? 'yolo';
|
|
55
|
+
const tmuxSessionName = (0, champion_ids_1.toTmuxSessionName)(championId);
|
|
56
|
+
const internalId = (0, node_crypto_1.randomUUID)();
|
|
57
|
+
await this.claudeBackend.createSession(tmuxSessionName, workspacePath, mode, internalId);
|
|
58
|
+
session = {
|
|
59
|
+
championId,
|
|
60
|
+
internalId,
|
|
61
|
+
cli: 'claude',
|
|
62
|
+
mode,
|
|
63
|
+
path: workspacePath,
|
|
64
|
+
description: options.description,
|
|
65
|
+
status: 'active',
|
|
66
|
+
createdAt: timestamp,
|
|
67
|
+
lastUsed: timestamp
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
await this.store.upsertSession(session);
|
|
71
|
+
return session;
|
|
72
|
+
}
|
|
73
|
+
async sendMessage(championId, message) {
|
|
74
|
+
const session = await this.requireSession(championId);
|
|
75
|
+
if (session.cli === 'codex') {
|
|
76
|
+
const turnStartTime = new Date().toISOString();
|
|
77
|
+
await this.store.updateSession(championId, {
|
|
78
|
+
lastUsed: turnStartTime,
|
|
79
|
+
status: 'active',
|
|
80
|
+
codexTurnInProgress: true,
|
|
81
|
+
lastTurnStatus: undefined,
|
|
82
|
+
lastTurnError: undefined
|
|
83
|
+
});
|
|
84
|
+
let sendResult;
|
|
85
|
+
try {
|
|
86
|
+
sendResult = await this.codexBackend.sendMessage(session.championId, session.internalId, message, {
|
|
87
|
+
workspacePath: session.path,
|
|
88
|
+
model: session.model
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
if (error instanceof Error) {
|
|
93
|
+
const latestSession = await this.store.getSession(championId);
|
|
94
|
+
if (latestSession?.cli === 'codex' && latestSession.codexTurnInProgress === true) {
|
|
95
|
+
await this.store.updateSession(championId, {
|
|
96
|
+
codexTurnInProgress: false,
|
|
97
|
+
lastTurnStatus: 'failed',
|
|
98
|
+
lastTurnError: error.message,
|
|
99
|
+
lastUsed: new Date().toISOString()
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
const nextAssistantMessages = sendResult.assistantMessage.length > 0
|
|
106
|
+
? [...(session.lastAssistantMessages ?? []), sendResult.assistantMessage]
|
|
107
|
+
: [...(session.lastAssistantMessages ?? [])];
|
|
108
|
+
const completionTime = new Date().toISOString();
|
|
109
|
+
const turnStillInProgress = sendResult.timedOut;
|
|
110
|
+
await this.store.updateSession(championId, {
|
|
111
|
+
internalId: sendResult.threadId,
|
|
112
|
+
appServerPid: sendResult.appServerPid,
|
|
113
|
+
appServerPort: sendResult.appServerPort,
|
|
114
|
+
lastUsed: completionTime,
|
|
115
|
+
status: 'active',
|
|
116
|
+
codexTurnInProgress: turnStillInProgress,
|
|
117
|
+
codexLastCompletedAt: turnStillInProgress ? session.codexLastCompletedAt : completionTime,
|
|
118
|
+
lastTurnStatus: sendResult.status,
|
|
119
|
+
lastTurnError: sendResult.errorMessage,
|
|
120
|
+
lastAssistantMessages: nextAssistantMessages
|
|
121
|
+
});
|
|
122
|
+
if (sendResult.timedOut || sendResult.status === 'interrupted') {
|
|
123
|
+
throw new Error(sendResult.errorMessage ?? `Codex turn timed out for ${championId}`);
|
|
124
|
+
}
|
|
125
|
+
if (sendResult.status === 'failed') {
|
|
126
|
+
const messageText = sendResult.errorMessage
|
|
127
|
+
? `Codex turn failed: ${sendResult.errorMessage}`
|
|
128
|
+
: 'Codex turn failed';
|
|
129
|
+
throw new Error(messageText);
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const tmuxSessionName = (0, champion_ids_1.toTmuxSessionName)(session.championId);
|
|
134
|
+
const sendTime = new Date().toISOString();
|
|
135
|
+
await this.claudeBackend.sendMessage(tmuxSessionName, message);
|
|
136
|
+
await this.store.updateSession(championId, {
|
|
137
|
+
lastUsed: sendTime,
|
|
138
|
+
status: 'active',
|
|
139
|
+
lastTurnStatus: undefined,
|
|
140
|
+
lastTurnError: undefined
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async killSession(championId) {
|
|
144
|
+
const session = await this.requireSession(championId);
|
|
145
|
+
if (session.cli === 'codex') {
|
|
146
|
+
await this.codexBackend.killSession(session.championId, session.appServerPid, session.internalId, session.appServerPort);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const tmuxSessionName = (0, champion_ids_1.toTmuxSessionName)(session.championId);
|
|
150
|
+
try {
|
|
151
|
+
await this.claudeBackend.killSession(tmuxSessionName);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (!(error instanceof Error) ||
|
|
155
|
+
!/failed to connect server|no server running|can't find session/i.test(error.message)) {
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
await this.store.deleteSession(championId);
|
|
161
|
+
if (session.cli === 'codex' && !(await this.hasActiveCodexSessions())) {
|
|
162
|
+
await this.codexBackend.stopAppServer();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async listSessions() {
|
|
166
|
+
const sessions = (await this.store.listSessions()).filter((session) => session.status === 'active');
|
|
167
|
+
const livenessChecks = await Promise.all(sessions.map(async (session) => ({
|
|
168
|
+
championId: session.championId,
|
|
169
|
+
exists: session.cli === 'codex'
|
|
170
|
+
? await this.codexBackend.sessionExists(session.championId, session.appServerPid, session.appServerPort)
|
|
171
|
+
: await this.claudeBackend.sessionExists((0, champion_ids_1.toTmuxSessionName)(session.championId))
|
|
172
|
+
})));
|
|
173
|
+
const deadSessions = sessions.filter((session) => livenessChecks.some((check) => check.championId === session.championId && !check.exists));
|
|
174
|
+
const deadCodexSessionIds = deadSessions
|
|
175
|
+
.filter((session) => session.cli === 'codex')
|
|
176
|
+
.map((session) => session.championId);
|
|
177
|
+
const deadNonCodexSessionIds = deadSessions
|
|
178
|
+
.filter((session) => session.cli !== 'codex')
|
|
179
|
+
.map((session) => session.championId);
|
|
180
|
+
if (deadCodexSessionIds.length > 0) {
|
|
181
|
+
await Promise.all(deadCodexSessionIds.map(async (deadSessionId) => {
|
|
182
|
+
await this.store.updateSession(deadSessionId, {
|
|
183
|
+
status: 'inactive',
|
|
184
|
+
codexTurnInProgress: false
|
|
185
|
+
});
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
if (deadNonCodexSessionIds.length > 0) {
|
|
189
|
+
await this.store.pruneSessions(deadNonCodexSessionIds);
|
|
190
|
+
}
|
|
191
|
+
return (await this.store.listSessions()).filter((session) => session.status === 'active');
|
|
192
|
+
}
|
|
193
|
+
async getLastAssistantTextBlocks(championId, count) {
|
|
194
|
+
const session = await this.requireSession(championId);
|
|
195
|
+
if (session.cli === 'codex') {
|
|
196
|
+
const safeCount = Math.max(1, count);
|
|
197
|
+
const sessionMessages = session.lastAssistantMessages ?? [];
|
|
198
|
+
if (sessionMessages.length > 0) {
|
|
199
|
+
return sessionMessages.slice(-safeCount);
|
|
200
|
+
}
|
|
201
|
+
return this.codexBackend.getLastAssistantMessages(championId, safeCount);
|
|
202
|
+
}
|
|
203
|
+
const transcriptPath = (0, claude_parser_1.getClaudeTranscriptPath)(session.path, session.internalId);
|
|
204
|
+
const transcriptEntries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
205
|
+
const blocks = (0, claude_parser_1.getAssistantTextBlocks)(transcriptEntries);
|
|
206
|
+
return blocks.slice(-Math.max(1, count));
|
|
207
|
+
}
|
|
208
|
+
async getSessionStatus(championId) {
|
|
209
|
+
const session = await this.requireSession(championId);
|
|
210
|
+
if (session.cli === 'codex') {
|
|
211
|
+
if (session.codexTurnInProgress) {
|
|
212
|
+
return 'working';
|
|
213
|
+
}
|
|
214
|
+
if (session.lastTurnStatus === 'failed') {
|
|
215
|
+
const suffix = session.lastTurnError ? `: ${session.lastTurnError}` : '';
|
|
216
|
+
throw new Error(`Codex turn failed${suffix}`);
|
|
217
|
+
}
|
|
218
|
+
return 'idle';
|
|
219
|
+
}
|
|
220
|
+
const transcriptPath = (0, claude_parser_1.getClaudeTranscriptPath)(session.path, session.internalId);
|
|
221
|
+
const transcriptEntries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
222
|
+
return (0, claude_parser_1.inferTranscriptStatus)(transcriptEntries);
|
|
223
|
+
}
|
|
224
|
+
async waitForSession(championId, options = {}) {
|
|
225
|
+
const session = await this.requireSession(championId);
|
|
226
|
+
if (session.cli === 'codex') {
|
|
227
|
+
const timeoutMs = Math.max(1, options.timeoutSeconds ?? 300) * 1000;
|
|
228
|
+
const intervalMs = Math.max(1, options.intervalSeconds ?? 2) * 1000;
|
|
229
|
+
const startTime = Date.now();
|
|
230
|
+
if (!session.codexTurnInProgress && session.lastTurnStatus === 'failed') {
|
|
231
|
+
const message = session.lastTurnError
|
|
232
|
+
? `Codex turn failed: ${session.lastTurnError}`
|
|
233
|
+
: 'Codex turn failed';
|
|
234
|
+
throw new Error(message);
|
|
235
|
+
}
|
|
236
|
+
await this.store.updateSession(championId, {
|
|
237
|
+
lastUsed: new Date().toISOString()
|
|
238
|
+
});
|
|
239
|
+
if (!session.codexTurnInProgress) {
|
|
240
|
+
if (session.lastTurnStatus === 'interrupted') {
|
|
241
|
+
return {
|
|
242
|
+
completed: false,
|
|
243
|
+
timedOut: true,
|
|
244
|
+
elapsedMs: timeoutMs
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
completed: true,
|
|
249
|
+
timedOut: false,
|
|
250
|
+
elapsedMs: 0
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
const deadline = startTime + timeoutMs;
|
|
254
|
+
while (Date.now() <= deadline) {
|
|
255
|
+
const latestSession = await this.requireSession(championId);
|
|
256
|
+
if (latestSession.cli !== 'codex') {
|
|
257
|
+
throw new Error(`Session ${championId} is no longer a Codex session`);
|
|
258
|
+
}
|
|
259
|
+
if (!latestSession.codexTurnInProgress) {
|
|
260
|
+
if (latestSession.lastTurnStatus === 'failed') {
|
|
261
|
+
const message = latestSession.lastTurnError
|
|
262
|
+
? `Codex turn failed: ${latestSession.lastTurnError}`
|
|
263
|
+
: 'Codex turn failed';
|
|
264
|
+
throw new Error(message);
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
completed: latestSession.lastTurnStatus !== 'interrupted',
|
|
268
|
+
timedOut: latestSession.lastTurnStatus === 'interrupted',
|
|
269
|
+
elapsedMs: Date.now() - startTime
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
await this.sleep(intervalMs);
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
completed: false,
|
|
276
|
+
timedOut: true,
|
|
277
|
+
elapsedMs: Date.now() - startTime
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
const transcriptPath = (0, claude_parser_1.getClaudeTranscriptPath)(session.path, session.internalId);
|
|
281
|
+
const timeoutMs = Math.max(1, options.timeoutSeconds ?? 300) * 1000;
|
|
282
|
+
const intervalMs = Math.max(1, options.intervalSeconds ?? 2) * 1000;
|
|
283
|
+
const startTime = Date.now();
|
|
284
|
+
const deadline = startTime + timeoutMs;
|
|
285
|
+
const latestSendMs = Date.parse(session.lastUsed);
|
|
286
|
+
const initialEntries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
287
|
+
const baselineAssistantCount = (0, claude_parser_1.countAssistantMessages)(initialEntries);
|
|
288
|
+
const baselineSystemCount = (0, claude_parser_1.countSystemEntries)(initialEntries);
|
|
289
|
+
let lastMtimeMs = -1;
|
|
290
|
+
let shouldReadTranscript = false;
|
|
291
|
+
let cachedEntries = initialEntries;
|
|
292
|
+
while (Date.now() <= deadline) {
|
|
293
|
+
try {
|
|
294
|
+
const fileStat = await (0, promises_1.stat)(transcriptPath);
|
|
295
|
+
if (fileStat.mtimeMs !== lastMtimeMs) {
|
|
296
|
+
lastMtimeMs = fileStat.mtimeMs;
|
|
297
|
+
shouldReadTranscript = true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
if (error.code !== 'ENOENT') {
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
shouldReadTranscript = true;
|
|
305
|
+
cachedEntries = [];
|
|
306
|
+
}
|
|
307
|
+
if (shouldReadTranscript) {
|
|
308
|
+
cachedEntries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
309
|
+
shouldReadTranscript = false;
|
|
310
|
+
}
|
|
311
|
+
const status = (0, claude_parser_1.inferTranscriptStatus)(cachedEntries);
|
|
312
|
+
const hasNewSystemEntry = (0, claude_parser_1.countSystemEntries)(cachedEntries) > baselineSystemCount;
|
|
313
|
+
const hasNewAssistant = (0, claude_parser_1.countAssistantMessages)(cachedEntries) > baselineAssistantCount;
|
|
314
|
+
const hasRecentAssistant = this.hasAssistantResponseAtOrAfter(cachedEntries, latestSendMs);
|
|
315
|
+
// Primary signal: a new 'system' entry marks the definitive end of a Claude Code turn.
|
|
316
|
+
// This avoids false positives from intermediate tool_use assistant entries.
|
|
317
|
+
if (hasNewSystemEntry && (hasNewAssistant || hasRecentAssistant)) {
|
|
318
|
+
await this.store.updateSession(championId, {
|
|
319
|
+
lastUsed: new Date().toISOString()
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
completed: true,
|
|
323
|
+
timedOut: false,
|
|
324
|
+
elapsedMs: Date.now() - startTime
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
// Fallback: if inferTranscriptStatus reports idle/waiting and we have new assistant
|
|
328
|
+
// entries, the turn is complete. This handles transcripts that may not have system entries.
|
|
329
|
+
if ((status === 'idle' || status === 'waiting_for_input') &&
|
|
330
|
+
(0, claude_parser_1.hasAssistantResponseAfterLatestUser)(cachedEntries) &&
|
|
331
|
+
(hasNewAssistant || hasRecentAssistant)) {
|
|
332
|
+
await this.store.updateSession(championId, {
|
|
333
|
+
lastUsed: new Date().toISOString()
|
|
334
|
+
});
|
|
335
|
+
return {
|
|
336
|
+
completed: true,
|
|
337
|
+
timedOut: false,
|
|
338
|
+
elapsedMs: Date.now() - startTime
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
await this.sleep(intervalMs);
|
|
342
|
+
}
|
|
343
|
+
return {
|
|
344
|
+
completed: false,
|
|
345
|
+
timedOut: true,
|
|
346
|
+
elapsedMs: Date.now() - startTime
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
async requireSession(championId) {
|
|
350
|
+
const session = await this.store.getSession(championId);
|
|
351
|
+
if (!session) {
|
|
352
|
+
throw new Error(`Session not found: ${championId}`);
|
|
353
|
+
}
|
|
354
|
+
return session;
|
|
355
|
+
}
|
|
356
|
+
async findAvailableChampionId(maxAttempts = 250) {
|
|
357
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
358
|
+
const candidate = (0, champion_ids_1.generateChampionId)();
|
|
359
|
+
if (await this.store.getSession(candidate)) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (await this.claudeBackend.sessionExists((0, champion_ids_1.toTmuxSessionName)(candidate))) {
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
return candidate;
|
|
366
|
+
}
|
|
367
|
+
throw new Error('Unable to allocate a unique champion ID');
|
|
368
|
+
}
|
|
369
|
+
async sleep(ms) {
|
|
370
|
+
await new Promise((resolve) => {
|
|
371
|
+
setTimeout(resolve, ms);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
async hasActiveCodexSessions() {
|
|
375
|
+
const sessions = await this.store.listSessions();
|
|
376
|
+
return sessions.some((session) => session.status === 'active' && session.cli === 'codex');
|
|
377
|
+
}
|
|
378
|
+
hasAssistantResponseAtOrAfter(entries, thresholdMs) {
|
|
379
|
+
if (!Number.isFinite(thresholdMs)) {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
return entries.some((entry) => {
|
|
383
|
+
if (entry.type?.toLowerCase() !== 'assistant') {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
const timestamp = entry.timestamp;
|
|
387
|
+
if (typeof timestamp !== 'string') {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
const parsed = Date.parse(timestamp);
|
|
391
|
+
return !Number.isNaN(parsed) && parsed >= thresholdMs;
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
exports.SessionManager = SessionManager;
|
|
396
|
+
function shouldUseGatewaySessionManager(env = process.env) {
|
|
397
|
+
return env.IS_SANDBOX === '1';
|
|
398
|
+
}
|
|
399
|
+
function createDefaultSessionManager(env = process.env) {
|
|
400
|
+
if (shouldUseGatewaySessionManager(env)) {
|
|
401
|
+
return new client_1.GatewaySessionManager({
|
|
402
|
+
baseUrl: (0, client_1.resolveGatewayBaseUrl)(env)
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
return new SessionManager((0, session_store_1.createDefaultSessionStore)(), new claude_tmux_1.ClaudeTmuxBackend(), new codex_appserver_1.CodexAppServerBackend());
|
|
406
|
+
}
|
|
407
|
+
//# sourceMappingURL=session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StoredSession } from './types';
|
|
2
|
+
export declare class SessionStore {
|
|
3
|
+
private readonly storePath;
|
|
4
|
+
constructor(storePath?: string);
|
|
5
|
+
get filePath(): string;
|
|
6
|
+
listSessions(): Promise<StoredSession[]>;
|
|
7
|
+
getSession(championId: string): Promise<StoredSession | undefined>;
|
|
8
|
+
upsertSession(session: StoredSession): Promise<void>;
|
|
9
|
+
updateSession(championId: string, partial: Partial<Omit<StoredSession, 'championId'>>): Promise<StoredSession | undefined>;
|
|
10
|
+
deleteSession(championId: string): Promise<boolean>;
|
|
11
|
+
pruneSessions(championIds: string[]): Promise<number>;
|
|
12
|
+
private readStore;
|
|
13
|
+
private writeStore;
|
|
14
|
+
}
|
|
15
|
+
export declare function createDefaultSessionStore(): SessionStore;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SessionStore = void 0;
|
|
7
|
+
exports.createDefaultSessionStore = createDefaultSessionStore;
|
|
8
|
+
const promises_1 = require("node:fs/promises");
|
|
9
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const CURRENT_VERSION = 1;
|
|
12
|
+
function getDefaultStorePath() {
|
|
13
|
+
return node_path_1.default.join(node_os_1.default.homedir(), '.dev-sessions', 'sessions.json');
|
|
14
|
+
}
|
|
15
|
+
function isStoredSession(value) {
|
|
16
|
+
if (!value || typeof value !== 'object') {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const candidate = value;
|
|
20
|
+
return (typeof candidate.championId === 'string' &&
|
|
21
|
+
typeof candidate.internalId === 'string' &&
|
|
22
|
+
(candidate.cli === 'claude' || candidate.cli === 'codex') &&
|
|
23
|
+
(candidate.mode === 'yolo' || candidate.mode === 'native' || candidate.mode === 'docker') &&
|
|
24
|
+
typeof candidate.path === 'string' &&
|
|
25
|
+
(candidate.description === undefined || typeof candidate.description === 'string') &&
|
|
26
|
+
(candidate.status === 'active' || candidate.status === 'inactive') &&
|
|
27
|
+
(candidate.appServerPid === undefined || Number.isInteger(candidate.appServerPid)) &&
|
|
28
|
+
(candidate.appServerPort === undefined || Number.isInteger(candidate.appServerPort)) &&
|
|
29
|
+
(candidate.model === undefined || typeof candidate.model === 'string') &&
|
|
30
|
+
(candidate.codexTurnInProgress === undefined || typeof candidate.codexTurnInProgress === 'boolean') &&
|
|
31
|
+
(candidate.codexLastCompletedAt === undefined || typeof candidate.codexLastCompletedAt === 'string') &&
|
|
32
|
+
(candidate.lastTurnStatus === undefined ||
|
|
33
|
+
candidate.lastTurnStatus === 'completed' ||
|
|
34
|
+
candidate.lastTurnStatus === 'failed' ||
|
|
35
|
+
candidate.lastTurnStatus === 'interrupted') &&
|
|
36
|
+
(candidate.lastTurnError === undefined || typeof candidate.lastTurnError === 'string') &&
|
|
37
|
+
(candidate.lastAssistantMessages === undefined ||
|
|
38
|
+
(Array.isArray(candidate.lastAssistantMessages) &&
|
|
39
|
+
candidate.lastAssistantMessages.every((message) => typeof message === 'string'))) &&
|
|
40
|
+
typeof candidate.createdAt === 'string' &&
|
|
41
|
+
typeof candidate.lastUsed === 'string');
|
|
42
|
+
}
|
|
43
|
+
class SessionStore {
|
|
44
|
+
storePath;
|
|
45
|
+
constructor(storePath = getDefaultStorePath()) {
|
|
46
|
+
this.storePath = storePath;
|
|
47
|
+
}
|
|
48
|
+
get filePath() {
|
|
49
|
+
return this.storePath;
|
|
50
|
+
}
|
|
51
|
+
async listSessions() {
|
|
52
|
+
const store = await this.readStore();
|
|
53
|
+
return [...store.sessions].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
54
|
+
}
|
|
55
|
+
async getSession(championId) {
|
|
56
|
+
const store = await this.readStore();
|
|
57
|
+
return store.sessions.find((session) => session.championId === championId);
|
|
58
|
+
}
|
|
59
|
+
async upsertSession(session) {
|
|
60
|
+
const store = await this.readStore();
|
|
61
|
+
const index = store.sessions.findIndex((candidate) => candidate.championId === session.championId);
|
|
62
|
+
if (index >= 0) {
|
|
63
|
+
store.sessions[index] = session;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
store.sessions.push(session);
|
|
67
|
+
}
|
|
68
|
+
await this.writeStore(store);
|
|
69
|
+
}
|
|
70
|
+
async updateSession(championId, partial) {
|
|
71
|
+
const store = await this.readStore();
|
|
72
|
+
const index = store.sessions.findIndex((candidate) => candidate.championId === championId);
|
|
73
|
+
if (index < 0) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const updatedSession = {
|
|
77
|
+
...store.sessions[index],
|
|
78
|
+
...partial,
|
|
79
|
+
championId: store.sessions[index].championId
|
|
80
|
+
};
|
|
81
|
+
store.sessions[index] = updatedSession;
|
|
82
|
+
await this.writeStore(store);
|
|
83
|
+
return updatedSession;
|
|
84
|
+
}
|
|
85
|
+
async deleteSession(championId) {
|
|
86
|
+
const store = await this.readStore();
|
|
87
|
+
const initialLength = store.sessions.length;
|
|
88
|
+
store.sessions = store.sessions.filter((candidate) => candidate.championId !== championId);
|
|
89
|
+
if (store.sessions.length === initialLength) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
await this.writeStore(store);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
async pruneSessions(championIds) {
|
|
96
|
+
if (championIds.length === 0) {
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
const ids = new Set(championIds);
|
|
100
|
+
const store = await this.readStore();
|
|
101
|
+
const initialLength = store.sessions.length;
|
|
102
|
+
store.sessions = store.sessions.filter((candidate) => !ids.has(candidate.championId));
|
|
103
|
+
const removed = initialLength - store.sessions.length;
|
|
104
|
+
if (removed > 0) {
|
|
105
|
+
await this.writeStore(store);
|
|
106
|
+
}
|
|
107
|
+
return removed;
|
|
108
|
+
}
|
|
109
|
+
async readStore() {
|
|
110
|
+
try {
|
|
111
|
+
const raw = await (0, promises_1.readFile)(this.storePath, 'utf8');
|
|
112
|
+
const parsed = JSON.parse(raw);
|
|
113
|
+
const sessions = Array.isArray(parsed.sessions)
|
|
114
|
+
? parsed.sessions.filter(isStoredSession)
|
|
115
|
+
: [];
|
|
116
|
+
return {
|
|
117
|
+
version: typeof parsed.version === 'number' ? parsed.version : CURRENT_VERSION,
|
|
118
|
+
sessions
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
if (error.code === 'ENOENT') {
|
|
123
|
+
return {
|
|
124
|
+
version: CURRENT_VERSION,
|
|
125
|
+
sessions: []
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async writeStore(store) {
|
|
132
|
+
await (0, promises_1.mkdir)(node_path_1.default.dirname(this.storePath), { recursive: true });
|
|
133
|
+
const tmpPath = `${this.storePath}.tmp`;
|
|
134
|
+
const payload = JSON.stringify(store, null, 2);
|
|
135
|
+
await (0, promises_1.writeFile)(tmpPath, payload, 'utf8');
|
|
136
|
+
await (0, promises_1.rename)(tmpPath, this.storePath);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.SessionStore = SessionStore;
|
|
140
|
+
function createDefaultSessionStore() {
|
|
141
|
+
return new SessionStore();
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AgentTurnStatus } from '../types';
|
|
2
|
+
export interface ClaudeTranscriptEntry {
|
|
3
|
+
type?: string;
|
|
4
|
+
message?: {
|
|
5
|
+
content?: unknown;
|
|
6
|
+
};
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
export declare function sanitizeWorkspacePath(workspacePath: string): string;
|
|
10
|
+
export declare function getClaudeTranscriptPath(workspacePath: string, internalId: string, homeDir?: string): string;
|
|
11
|
+
export declare function readClaudeTranscript(filePath: string): Promise<ClaudeTranscriptEntry[]>;
|
|
12
|
+
export declare function extractTextBlocks(content: unknown): string[];
|
|
13
|
+
export declare function getAssistantTextBlocks(entries: ClaudeTranscriptEntry[]): string[];
|
|
14
|
+
export declare function countAssistantMessages(entries: ClaudeTranscriptEntry[]): number;
|
|
15
|
+
export declare function countSystemEntries(entries: ClaudeTranscriptEntry[]): number;
|
|
16
|
+
export declare function inferTranscriptStatus(entries: ClaudeTranscriptEntry[]): AgentTurnStatus;
|
|
17
|
+
export declare function hasAssistantResponseAfterLatestUser(entries: ClaudeTranscriptEntry[]): boolean;
|