mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 23:19:43 +02:00
feat: auto-name sessions from first prompt
This commit is contained in:
@@ -1103,6 +1103,7 @@ export function registerSessionRoutes(
|
||||
workingDir,
|
||||
mode,
|
||||
name: body.name || '',
|
||||
nameSource: body.name ? undefined : 'auto',
|
||||
mux: ctx.mux,
|
||||
useMux: true,
|
||||
niceConfig: globalNice,
|
||||
@@ -3333,6 +3334,7 @@ export function registerSessionRoutes(
|
||||
const session = new Session({
|
||||
workingDir: resolvedCasePath,
|
||||
name: sessionName ? sessionName.slice(0, MAX_SESSION_NAME_LENGTH) : '',
|
||||
nameSource: sessionName ? undefined : 'auto',
|
||||
mux: ctx.mux,
|
||||
useMux: true,
|
||||
mode: mode,
|
||||
|
||||
@@ -1620,6 +1620,7 @@ export class WebServer extends EventEmitter {
|
||||
getStore: () => this.store,
|
||||
registerAttachment: (id: string, filePath: string, source: 'external' | 'codex-generated') =>
|
||||
this.registerAttachment(id, filePath, source),
|
||||
updateSessionName: (id: string, name: string) => this.mux.updateSessionName(id, name),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2768,6 +2769,7 @@ export class WebServer extends EventEmitter {
|
||||
workingDir: muxSession.workingDir,
|
||||
mode: muxSession.mode,
|
||||
name: sessionName,
|
||||
nameSource: savedState?.nameSource,
|
||||
// When the session FIRST started, not when this server booted.
|
||||
// Without it every recovered session was restamped `Date.now()` on
|
||||
// each restart, so a week-old pane read as "created 2m ago" on the
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Extracted from server.ts for modularity. Provides:
|
||||
* - `SessionListenerRefs` interface (named listener references for leak-free cleanup)
|
||||
* - `createSessionListeners()` — builds all 25 listener handlers via dependency injection
|
||||
* - `createSessionListeners()` — builds all session listener handlers via dependency injection
|
||||
* - `attachSessionListeners()` / `detachSessionListeners()` — symmetric attach/detach
|
||||
*
|
||||
* The detach function deduplicates a pattern that was previously copy-pasted 3 times
|
||||
@@ -29,6 +29,7 @@ import { getLifecycleLog } from '../session-lifecycle-log.js';
|
||||
import { fileStreamManager } from '../file-stream-manager.js';
|
||||
import { sessionWaits } from './session-wait-registry.js';
|
||||
import { approvalInbox } from './approval-inbox.js';
|
||||
import { deriveAutoSessionName } from '../session-auto-name.js';
|
||||
|
||||
/** Stored listener references for session cleanup (prevents memory leaks) */
|
||||
export interface SessionListenerRefs {
|
||||
@@ -63,6 +64,7 @@ export interface SessionListenerRefs {
|
||||
bashToolEnd: (tool: ActiveBashTool) => void;
|
||||
bashToolsUpdate: (tools: ActiveBashTool[]) => void;
|
||||
attachmentRequested: (event: { path: string; source: 'external' | 'codex-generated' }) => void;
|
||||
promptSubmitted: (prompt: string) => void;
|
||||
}
|
||||
|
||||
/** Dependencies injected by WebServer — keeps listener creation decoupled from server internals. */
|
||||
@@ -83,10 +85,11 @@ interface SessionListenerDeps {
|
||||
cleanupRespawnOnExit(sessionId: string): void;
|
||||
getStore(): import('../state-store.js').StateStore;
|
||||
registerAttachment(sessionId: string, filePath: string, source: 'external' | 'codex-generated'): Promise<void>;
|
||||
updateSessionName(sessionId: string, name: string): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates all 26 session listener handlers, capturing dependencies via closure.
|
||||
* Creates all session listener handlers, capturing dependencies via closure.
|
||||
* Call `attachSessionListeners()` after to wire them to the session.
|
||||
*/
|
||||
export function createSessionListeners(session: Session, deps: SessionListenerDeps): SessionListenerRefs {
|
||||
@@ -451,6 +454,15 @@ export function createSessionListeners(session: Session, deps: SessionListenerDe
|
||||
console.error(`[Attachment] Failed to register ${event.path} for ${session.id}:`, err);
|
||||
});
|
||||
},
|
||||
|
||||
/** Assigns a bounded local title from the first real task prompt. */
|
||||
promptSubmitted: (prompt: string) => {
|
||||
const name = deriveAutoSessionName(prompt);
|
||||
if (!name || !session.applyAutoName(name)) return;
|
||||
deps.updateSessionName(session.id, session.name);
|
||||
deps.persistSessionState(session);
|
||||
deps.broadcast(SseEvent.SessionUpdated, deps.getSessionStateWithRespawn(session));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -487,6 +499,7 @@ export function attachSessionListeners(session: Session, refs: SessionListenerRe
|
||||
session.on('bashToolEnd', refs.bashToolEnd);
|
||||
session.on('bashToolsUpdate', refs.bashToolsUpdate);
|
||||
session.on('attachmentRequested', refs.attachmentRequested);
|
||||
session.on('promptSubmitted', refs.promptSubmitted);
|
||||
}
|
||||
|
||||
/** Detach all listeners from a session (prevents memory leaks from closure references). */
|
||||
@@ -522,4 +535,5 @@ export function detachSessionListeners(session: Session, refs: SessionListenerRe
|
||||
session.off('bashToolEnd', refs.bashToolEnd);
|
||||
session.off('bashToolsUpdate', refs.bashToolsUpdate);
|
||||
session.off('attachmentRequested', refs.attachmentRequested);
|
||||
session.off('promptSubmitted', refs.promptSubmitted);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user