+
+ {
+ const tabId = Number(value);
+
+ if (Number.isInteger(tabId)) {
+ onSelectedTabChange(tabId);
+ }
+ }}
+ value={selectedTabId === undefined ? '' : String(selectedTabId)}
+ >
+ {inspectableTabs.length === 0 ? (
+
+ ) : (
+ <>
+ {selectedTabId === undefined ? : null}
+ {inspectableTabs.map(tab => (
+
+ ))}
+ >
+ )}
+
+
+ {tabDebuggerError === undefined ? null : (
+
{tabDebuggerError}
+ )}
+
+
+
+ {modelOptions.length === 0 ? (
+
+ ) : (
+ modelOptions.map(option => (
+
+ ))
+ )}
+
+
+ {thinkingOptions.length === 0 ? (
+
+ ) : (
+ thinkingOptions.map(option => (
+
+ ))
+ )}
+
+
+ {modelLoadError === undefined ? null : (
+
+
{modelLoadError}
+
+
+ )}
+
+ );
+};
diff --git a/apps/extension/entrypoints/sidepanel/agent-llm-turn-runner.ts b/apps/extension/entrypoints/sidepanel/agent-llm-turn-runner.ts
new file mode 100644
index 0000000000..6e40870bfc
--- /dev/null
+++ b/apps/extension/entrypoints/sidepanel/agent-llm-turn-runner.ts
@@ -0,0 +1,47 @@
+import type { AgentConversationEvent } from '@/src/shared/agent-conversation';
+import {
+ createEvalToolDefinition,
+ createSafeToolDefinitions,
+} from '@/src/shared/agent-llm-harness';
+import { runLlmTurn } from '@/src/shared/agent-llm-turn-runner-core';
+import { maxAgentToolRounds } from '@/src/shared/agent-tool-round-limit';
+import type { FetchLike } from '@/src/shared/auth';
+import { executeEvalToolCall } from './agent-eval-runtime';
+import { executeSafeToolCall } from './agent-safe-tool-runtime';
+import { toDangerousToolCallEvents } from './agent-tool-call-events';
+
+interface RunDangerousLlmTurnOptions {
+ readonly apiBaseUrl: string;
+ readonly appendEvents: (events: AgentConversationEvent[]) => void;
+ readonly conversationEvents: AgentConversationEvent[];
+ readonly fetch: FetchLike;
+ readonly model: string;
+ readonly organizationId?: string | undefined;
+ readonly selectedTabId: number;
+ readonly signal?: AbortSignal | undefined;
+ readonly supportsImages?: boolean;
+ readonly thinkingEffort?: string | undefined;
+ readonly token: string;
+ readonly updateAssistantMessage: (eventId: string, text: string) => void;
+ readonly updateThinkingBlock: (eventId: string, text: string) => void;
+}
+
+export const runDangerousLlmTurn = ({
+ selectedTabId,
+ supportsImages = false,
+ ...options
+}: RunDangerousLlmTurnOptions): Promise