From 5031ba46f423fd49bcc98472bf7207c5e62b2189 Mon Sep 17 00:00:00 2001 From: Hako Date: Thu, 13 Aug 2026 22:33:27 +0900 Subject: [PATCH] fix(providers): link omo panes resumed with --session-id to their sessions extractExternalResumeSessionId matched only the pi-derived --resume|-r form for omo, but omo's canonical continuation flag is --session-id (its --resume takes no value and opens a picker) -- the same fact #43 established for the headless runtime in server/pi-cli.ts. A tmux pane started with `omo --session-id ` therefore never linked back to its transcript session. omo now tries --session-id first and keeps the --resume fallback; omp is unchanged and never accepts --session-id. --- .../services/external-cli-sessions.service.ts | 12 ++++++++++- .../external-cli-sessions.service.test.ts | 21 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/server/modules/providers/services/external-cli-sessions.service.ts b/server/modules/providers/services/external-cli-sessions.service.ts index ae7a4e5..fe767fa 100644 --- a/server/modules/providers/services/external-cli-sessions.service.ts +++ b/server/modules/providers/services/external-cli-sessions.service.ts @@ -44,6 +44,11 @@ const CURSOR_RESUME_SESSION_RE = /(?:^|\s)(?:--resume|resume)(?:=|\s+)([A-Za-z0- const OPENCODE_SESSION_RE = /(?:^|\s)--session(?:=|\s+)([A-Za-z0-9_-]{8,128})(?=\s|$)/; // Oh My Pi and omo are both pi-derived and accept the identical `--resume|-r` form. const PI_RESUME_SESSION_RE = /(?:^|\s)(?:--resume|-r)(?:=|\s+)([A-Za-z0-9_-]{8,128})(?=\s|$)/; +// omo's canonical continuation flag is `--session-id ` (its `--resume` takes +// no value and opens a picker, so no id ever appears in argv for that form). +// ChatMux itself resumes omo with `--session-id` in `server/pi-cli.ts`, so a +// pane started that way must link back to its transcript session. +const OMO_SESSION_ID_RE = /(?:^|\s)--session-id(?:=|\s+)([A-Za-z0-9_-]{8,128})(?=\s|$)/; const TRANSCRIPT_FILE_SESSION_ID_RE = /_([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i; const CODEX_ROLLOUT_FILE_RE = /^rollout-.*-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i; const MAX_RUNTIME_DESCRIPTORS = 2_048; @@ -202,7 +207,12 @@ export function extractExternalResumeSessionId( if (kind === 'codex') return extractCodexResumeThreadId(processArgs); if (kind === 'cursor') return processArgs.match(CURSOR_RESUME_SESSION_RE)?.[1] ?? null; if (kind === 'opencode') return processArgs.match(OPENCODE_SESSION_RE)?.[1] ?? null; - if (kind === 'omp' || kind === 'omo') return processArgs.match(PI_RESUME_SESSION_RE)?.[1] ?? null; + if (kind === 'omp') return processArgs.match(PI_RESUME_SESSION_RE)?.[1] ?? null; + if (kind === 'omo') { + return processArgs.match(OMO_SESSION_ID_RE)?.[1] + ?? processArgs.match(PI_RESUME_SESSION_RE)?.[1] + ?? null; + } return null; } diff --git a/server/modules/providers/tests/external-cli-sessions.service.test.ts b/server/modules/providers/tests/external-cli-sessions.service.test.ts index 3f6531d..e595e1b 100644 --- a/server/modules/providers/tests/external-cli-sessions.service.test.ts +++ b/server/modules/providers/tests/external-cli-sessions.service.test.ts @@ -754,6 +754,27 @@ test('extractExternalResumeSessionId recognizes every supported native resume fo assert.equal(extractExternalResumeSessionId('cursor', 'agent --version'), null); }); +// omo continues a session with `--session-id ` — the flag ChatMux itself +// uses in `server/pi-cli.ts`. Its `--resume` takes no value (interactive +// picker), so a pane resumed with `--session-id` must still link back to its +// transcript session. +test('extractExternalResumeSessionId links omo panes started with --session-id', () => { + assert.equal( + extractExternalResumeSessionId('omo', 'omo --session-id 019ff9fa-abab-78a3-83b0-67c261374f42'), + '019ff9fa-abab-78a3-83b0-67c261374f42', + ); + assert.equal( + extractExternalResumeSessionId('omo', 'node /home/user/bin/omo --session-id=019ff9fa-abab-78a3-83b0-67c261374f42'), + '019ff9fa-abab-78a3-83b0-67c261374f42', + ); + // pi-derived `--resume ` argv still links if a wrapper passes it through. + assert.equal(extractExternalResumeSessionId('omo', 'omo --resume 019f848f_ff71_77f0'), '019f848f_ff71_77f0'); + // The valueless picker form carries no id and must not match the prompt text. + assert.equal(extractExternalResumeSessionId('omo', 'omo --resume'), null); + // `--session-id` must never leak into the omp branch, which has no such flag. + assert.equal(extractExternalResumeSessionId('omp', 'omp --session-id 019f848f_ff71_77f0'), null); +}); + test('parseClaudeRuntimeSession accepts the PID-bound native Claude receipt', () => { const sessionId = '92869134-b4df-453e-b3a6-ed1d750d69d9';