fix: harden AI subtitle fix response parsing

This commit is contained in:
2026-03-08 16:01:40 -07:00
parent 8e319a417d
commit 93cd688625
22 changed files with 641 additions and 55 deletions

View File

@@ -201,7 +201,7 @@ function createDeps(overrides: Partial<CliCommandServiceDeps> = {}) {
return { deps, calls, osd };
}
test('handleCliCommand ignores --start for second-instance when overlay runtime is already initialized', () => {
test('handleCliCommand reconnects MPV for second-instance --start when overlay runtime is already initialized', () => {
const { deps, calls } = createDeps({
isOverlayRuntimeInitialized: () => true,
});
@@ -209,11 +209,9 @@ test('handleCliCommand ignores --start for second-instance when overlay runtime
handleCliCommand(args, 'second-instance', deps);
assert.ok(calls.includes('log:Ignoring --start because SubMiner is already running.'));
assert.equal(
calls.some((value) => value.includes('connectMpvClient')),
false,
);
assert.ok(calls.includes('setMpvClientSocketPath:/tmp/subminer.sock'));
assert.equal(calls.some((value) => value.includes('connectMpvClient')), true);
assert.equal(calls.some((value) => value.includes('initializeOverlayRuntime')), false);
});
test('handleCliCommand processes --start for second-instance when overlay runtime is not initialized', () => {

View File

@@ -259,10 +259,9 @@ export function handleCliCommand(
deps.setLogLevel?.(args.logLevel);
}
const ignoreSecondInstanceStart =
const reuseSecondInstanceStart =
source === 'second-instance' && args.start && deps.isOverlayRuntimeInitialized();
const shouldStart =
(!ignoreSecondInstanceStart && args.start) || args.toggle || args.toggleVisibleOverlay;
const shouldStart = args.start || args.toggle || args.toggleVisibleOverlay;
const needsOverlayRuntime = commandNeedsOverlayRuntime(args);
const shouldInitializeOverlayRuntime = needsOverlayRuntime || args.start;
@@ -285,8 +284,8 @@ export function handleCliCommand(
return;
}
if (ignoreSecondInstanceStart) {
deps.log('Ignoring --start because SubMiner is already running.');
if (reuseSecondInstanceStart) {
deps.log('Reusing running SubMiner instance for --start.');
}
if (shouldInitializeOverlayRuntime && !deps.isOverlayRuntimeInitialized()) {

View File

@@ -6,6 +6,7 @@ import {
OverlayShortcutRuntimeDeps,
runOverlayShortcutLocalFallback,
} from './overlay-shortcut-handler';
import { shouldActivateOverlayShortcuts } from './overlay-shortcut';
function makeShortcuts(overrides: Partial<ConfiguredShortcuts> = {}): ConfiguredShortcuts {
return {
@@ -279,3 +280,36 @@ test('runOverlayShortcutLocalFallback returns false when no action matches', ()
assert.equal(result, false);
assert.equal(called, false);
});
test('shouldActivateOverlayShortcuts disables macOS overlay shortcuts when tracked mpv is unfocused', () => {
assert.equal(
shouldActivateOverlayShortcuts({
overlayRuntimeInitialized: true,
isMacOSPlatform: true,
trackedMpvWindowFocused: false,
}),
false,
);
});
test('shouldActivateOverlayShortcuts keeps macOS overlay shortcuts active when tracked mpv is focused', () => {
assert.equal(
shouldActivateOverlayShortcuts({
overlayRuntimeInitialized: true,
isMacOSPlatform: true,
trackedMpvWindowFocused: true,
}),
true,
);
});
test('shouldActivateOverlayShortcuts preserves non-macOS behavior', () => {
assert.equal(
shouldActivateOverlayShortcuts({
overlayRuntimeInitialized: true,
isMacOSPlatform: false,
trackedMpvWindowFocused: false,
}),
true,
);
});

View File

@@ -27,6 +27,20 @@ export interface OverlayShortcutLifecycleDeps {
cancelPendingMineSentenceMultiple: () => void;
}
export function shouldActivateOverlayShortcuts(args: {
overlayRuntimeInitialized: boolean;
isMacOSPlatform: boolean;
trackedMpvWindowFocused: boolean;
}): boolean {
if (!args.overlayRuntimeInitialized) {
return false;
}
if (!args.isMacOSPlatform) {
return true;
}
return args.trackedMpvWindowFocused;
}
export function registerOverlayShortcuts(
shortcuts: ConfiguredShortcuts,
handlers: OverlayShortcutHandlers,