From 9d897621a7284f51821194e3b4945183f29e6249 Mon Sep 17 00:00:00 2001 From: Markov Date: Tue, 24 Feb 2026 11:19:24 +0100 Subject: [PATCH] fix: session_id generated at agent load (not lazy) --- src/config.ts | 49 +++++++++++++++++++------------------------------ src/router.ts | 6 +++--- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/src/config.ts b/src/config.ts index a23902a..b5a0f91 100644 --- a/src/config.ts +++ b/src/config.ts @@ -36,33 +36,6 @@ export interface AgentConfig { allowedPaths: string[]; /** Persistent session UUID — survives renames. Stored in agent.json. */ sessionId: string; - /** Internal: path to config file for lazy session_id write-back */ - _configPath: string | null; - /** Internal: parsed config data for write-back */ - _configData: Record; -} - -/** - * Ensure agent has a persistent session_id. - * Call lazily on first agent invocation, not at startup. - * Generates UUID and writes it back to agent.json. - */ -export function ensureSessionId(config: AgentConfig): string { - if (config.sessionId) return config.sessionId; - - const id = crypto.randomUUID(); - config.sessionId = id; - - if (config._configPath) { - try { - config._configData.session_id = id; - fs.writeFileSync(config._configPath, JSON.stringify(config._configData, null, 2) + '\n'); - } catch { - // Non-fatal - } - } - - return id; } const homeDir = os.homedir(); @@ -189,8 +162,24 @@ export function loadAgentConfig(): AgentConfig { apiKey: process.env.PICOGENT_API_KEY || process.env.ANTHROPIC_API_KEY || (file.api_key as string) || '', heartbeatIntervalSec: (file.heartbeat_interval_sec as number) || 30, allowedPaths: (file.allowed_paths as string[]) || [], - sessionId: (file.session_id as string) || '', - _configPath: configPath, - _configData: file, + sessionId: ensureSessionId(file, configPath), }; } + +/** + * Ensure agent.json has a persistent session_id. + * Generated on first load, persisted to config file. + */ +function ensureSessionId(file: Record, configPath: string | null): string { + if (file.session_id && typeof file.session_id === 'string') { + return file.session_id; + } + const id = crypto.randomUUID(); + if (configPath) { + try { + file.session_id = id; + fs.writeFileSync(configPath, JSON.stringify(file, null, 2) + '\n'); + } catch { /* non-fatal */ } + } + return id; +} diff --git a/src/router.ts b/src/router.ts index a316a97..10a7b84 100644 --- a/src/router.ts +++ b/src/router.ts @@ -4,7 +4,7 @@ import { runAgent } from './agent.js'; import { TrackerClient } from './tracker/client.js'; import { createTrackerTools } from './tools/index.js'; import type { ToolDefinition } from '@mariozechner/pi-coding-agent'; -import { ensureSessionId, type AgentConfig } from './config.js'; +import type { AgentConfig } from './config.js'; import type { TrackerEvent, TrackerTask } from './tracker/types.js'; export interface TaskTracker { @@ -86,7 +86,7 @@ export class EventRouter { let collectedText = ''; for await (const msg of runAgent(prompt, { workDir: this.config.workDir, - sessionId: ensureSessionId(this.config), + sessionId: this.config.sessionId, model: this.config.model, provider: this.config.provider, systemPrompt: this.config.prompt || undefined, @@ -158,7 +158,7 @@ export class EventRouter { let collectedText = ''; for await (const msg of runAgent(content, { workDir: this.config.workDir, - sessionId: ensureSessionId(this.config), + sessionId: this.config.sessionId, model: this.config.model, provider: this.config.provider, systemPrompt: this.config.prompt || undefined,