@btraut/browser-bridge 0.7.3 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -1
- package/README.md +49 -4
- package/dist/api.js +3922 -3239
- package/dist/api.js.map +4 -4
- package/dist/index.js +1027 -142
- package/dist/index.js.map +4 -4
- package/extension/dist/background.js +853 -23
- package/extension/dist/background.js.map +3 -3
- package/extension/dist/content.js +84 -2
- package/extension/dist/content.js.map +2 -2
- package/extension/dist/options-ui.js +59 -1
- package/extension/dist/options-ui.js.map +2 -2
- package/extension/manifest.json +17 -5
- package/package.json +1 -1
- package/skills/browser-bridge/skill.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts", "../../shared/src/errors.ts", "../../shared/src/schemas.ts", "../src/cli-output.ts", "../src/core-client.ts", "../src/cli-runtime.ts", "../src/commands/artifacts.ts", "../src/commands/dialog.ts", "../src/commands/diagnostics.ts", "../src/locator.ts", "../src/commands/drive.ts", "../src/commands/inspect.ts", "../../mcp-adapter/src/core-client.ts", "../../mcp-adapter/src/tools.ts", "../../mcp-adapter/src/server.ts", "../src/tui.ts", "../src/installer/mcp-install.ts", "../src/installer/cursor-mcp.ts", "../src/commands/mcp.ts", "../../core/src/server.ts", "../../core/src/routes/session.ts", "../../core/src/inspect/service.ts", "../../core/src/artifacts.ts", "../../core/src/extension-bridge.ts", "../../core/src/drive.ts", "../../core/src/page-state-script.ts", "../../core/src/diagnostics.ts", "../../core/src/routes/diagnostics.ts", "../src/
|
|
4
|
-
"sourcesContent": ["import { Command } from 'commander';\nimport { registerArtifactsCommands } from './commands/artifacts';\nimport { registerDialogCommands } from './commands/dialog';\nimport { registerDiagnosticsCommands } from './commands/diagnostics';\nimport { registerDriveCommands } from './commands/drive';\nimport { registerInspectCommands } from './commands/inspect';\nimport { registerMcpCommand } from './commands/mcp';\nimport { registerOpenArtifactsCommand } from './commands/open-artifacts';\nimport { registerSessionCommands } from './commands/session';\nimport { registerSkillCommands } from './commands/skill';\nimport { registerInstallCommand } from './commands/install';\n\nconst program = new Command();\n\nprogram\n .name('browser-bridge')\n .description('Browser Bridge CLI')\n .option('--host <host>', 'Core host (default: 127.0.0.1)')\n .option('--port <port>', 'Core port (default: 3210)')\n .option('--json', 'Output JSON')\n .option('--no-daemon', 'Disable auto-starting Core');\n\nregisterSessionCommands(program);\nregisterDriveCommands(program);\nregisterInspectCommands(program);\nregisterArtifactsCommands(program);\nregisterDiagnosticsCommands(program);\nregisterDialogCommands(program);\nregisterOpenArtifactsCommand(program);\nregisterMcpCommand(program);\nregisterSkillCommands(program);\nregisterInstallCommand(program);\n\nvoid program.parseAsync(process.argv);\n", "import { z } from 'zod';\n\n// Keep error codes stable; add new codes without renaming existing ones.\nexport const ErrorCodeSchema = z.enum([\n 'UNKNOWN',\n 'INVALID_ARGUMENT',\n 'NOT_FOUND',\n 'ALREADY_EXISTS',\n 'FAILED_PRECONDITION',\n 'UNAUTHORIZED',\n 'FORBIDDEN',\n 'PERMISSION_REQUIRED',\n 'PERMISSION_DENIED',\n 'PERMISSION_PROMPT_TIMEOUT',\n 'CONFLICT',\n 'TIMEOUT',\n 'CANCELLED',\n 'UNAVAILABLE',\n 'RATE_LIMITED',\n 'NOT_IMPLEMENTED',\n 'INTERNAL',\n 'SESSION_NOT_FOUND',\n 'SESSION_CLOSED',\n 'SESSION_BROKEN',\n 'DRIVE_UNAVAILABLE',\n 'INSPECT_UNAVAILABLE',\n 'EXTENSION_DISCONNECTED',\n 'DEBUGGER_IN_USE',\n 'ATTACH_DENIED',\n 'TAB_NOT_FOUND',\n 'NOT_SUPPORTED',\n 'LOCATOR_NOT_FOUND',\n 'NAVIGATION_FAILED',\n 'EVALUATION_FAILED',\n 'ARTIFACT_IO_ERROR',\n]);\n\nexport type ErrorCode = z.infer<typeof ErrorCodeSchema>;\n\nexport const ErrorInfoSchema = z.object({\n code: ErrorCodeSchema,\n message: z.string(),\n retryable: z.boolean(),\n details: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type ErrorInfo = z.infer<typeof ErrorInfoSchema>;\n\nexport const ErrorEnvelopeSchema = z.object({\n ok: z.literal(false),\n error: ErrorInfoSchema,\n});\n\nexport type ErrorEnvelope = z.infer<typeof ErrorEnvelopeSchema>;\n\nexport const successEnvelopeSchema = <T extends z.ZodTypeAny>(result: T) =>\n z.object({\n ok: z.literal(true),\n result,\n });\n\nexport const apiEnvelopeSchema = <T extends z.ZodTypeAny>(result: T) =>\n z.union([successEnvelopeSchema(result), ErrorEnvelopeSchema]);\n\nexport type SuccessEnvelope<T> = {\n ok: true;\n result: T;\n};\n\nexport type ApiEnvelope<T> = SuccessEnvelope<T> | ErrorEnvelope;\n", "import { z } from 'zod';\nimport { ErrorInfoSchema } from './errors';\n\nexport const LocatorRoleSchema = z.object({\n name: z.string(),\n value: z.string().optional(),\n});\n\nexport const LocatorSchema = z\n .object({\n ref: z.string().min(1).optional(),\n testid: z.string().min(1).optional(),\n css: z.string().min(1).optional(),\n text: z.string().min(1).optional(),\n role: LocatorRoleSchema.optional(),\n })\n .refine(\n (value) =>\n Boolean(\n value.ref || value.testid || value.css || value.text || value.role\n ),\n {\n message: 'Locator must include at least one selector.',\n }\n );\n\nexport const OpResultSchema = z.object({\n ok: z.literal(true),\n message: z.string().optional(),\n warnings: z.array(z.string()).optional(),\n});\n\nexport const SessionStateSchema = z.enum([\n 'INIT',\n 'DRIVE_READY',\n 'INSPECT_READY',\n 'READY',\n 'DEGRADED_DRIVE',\n 'DEGRADED_INSPECT',\n 'BROKEN',\n 'CLOSED',\n]);\n\nexport const SessionInfoSchema = z.object({\n session_id: z.string(),\n state: SessionStateSchema,\n created_at: z.string().datetime().optional(),\n});\n\nexport const SessionPlaneStatusSchema = z.object({\n connected: z.boolean(),\n last_seen_at: z.string().datetime().optional(),\n error: ErrorInfoSchema.optional(),\n});\n\nexport const SessionStatusSchema = z.object({\n session_id: z.string(),\n state: SessionStateSchema,\n drive: SessionPlaneStatusSchema.optional(),\n inspect: SessionPlaneStatusSchema.optional(),\n updated_at: z.string().datetime().optional(),\n});\n\nexport const RecoverResultSchema = z.object({\n session_id: z.string(),\n recovered: z.boolean(),\n state: SessionStateSchema,\n message: z.string().optional(),\n});\n\nexport const DiagnosticCheckSchema = z.object({\n name: z.string(),\n ok: z.boolean(),\n message: z.string().optional(),\n details: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const DiagnosticReportSchema = z.object({\n ok: z.boolean(),\n session_id: z.string().optional(),\n checks: z.array(DiagnosticCheckSchema).optional(),\n sessions: z\n .object({\n count: z.number().finite().optional(),\n max_age_ms: z.number().finite().optional(),\n max_idle_ms: z.number().finite().optional(),\n })\n .optional(),\n extension: z\n .object({\n connected: z.boolean().optional(),\n version: z.string().optional(),\n last_seen_at: z.string().datetime().optional(),\n })\n .optional(),\n debugger: z\n .object({\n attached: z.boolean().optional(),\n idle_timeout_ms: z.number().finite().optional(),\n console_buffer_size: z.number().finite().optional(),\n network_buffer_size: z.number().finite().optional(),\n last_error: ErrorInfoSchema.optional(),\n })\n .optional(),\n artifacts: z\n .object({\n root_dir: z.string().optional(),\n })\n .optional(),\n recovery: z\n .object({\n last_attempt: z\n .object({\n session_id: z.string(),\n recovered: z.boolean(),\n state: SessionStateSchema,\n message: z.string().optional(),\n at: z.string(),\n })\n .optional(),\n attempts: z\n .array(\n z.object({\n session_id: z.string(),\n recovered: z.boolean(),\n state: SessionStateSchema,\n message: z.string().optional(),\n at: z.string(),\n })\n )\n .optional(),\n success_count: z.number().finite().optional(),\n failure_count: z.number().finite().optional(),\n success_rate: z.number().finite().optional(),\n recent_failure_count: z.number().finite().optional(),\n loop_detected: z.boolean().optional(),\n })\n .optional(),\n warnings: z.array(z.string()).optional(),\n notes: z.array(z.string()).optional(),\n});\n\nexport const SessionIdSchema = z.object({\n session_id: z.string().min(1),\n});\n\nexport const SessionCreateInputSchema = z.object({}).strict().default({});\nexport const SessionCreateOutputSchema = SessionInfoSchema;\n\nexport const SessionStatusInputSchema = SessionIdSchema;\nexport const SessionStatusOutputSchema = SessionStatusSchema;\n\nexport const SessionRecoverInputSchema = SessionIdSchema;\nexport const SessionRecoverOutputSchema = RecoverResultSchema;\n\nexport const SessionCloseInputSchema = SessionIdSchema;\nexport const SessionCloseOutputSchema = z.object({\n ok: z.boolean(),\n});\n\nexport const DriveWaitConditionSchema = z.object({\n kind: z.enum(['locator_visible', 'text_present', 'url_matches']),\n value: z.string().min(1),\n});\n\nexport const DriveNavigateInputSchema = z.object({\n session_id: z.string().min(1),\n url: z.string().min(1),\n tab_id: z.number().finite().optional(),\n wait: z.enum(['none', 'domcontentloaded']).default('domcontentloaded'),\n});\nexport const DriveNavigateOutputSchema = OpResultSchema;\n\nexport const DriveGoBackInputSchema = z.object({\n session_id: z.string().min(1),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveGoBackOutputSchema = OpResultSchema;\n\nexport const DriveGoForwardInputSchema = z.object({\n session_id: z.string().min(1),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveGoForwardOutputSchema = OpResultSchema;\n\nexport const DriveBackInputSchema = DriveGoBackInputSchema;\nexport const DriveBackOutputSchema = OpResultSchema;\n\nexport const DriveForwardInputSchema = DriveGoForwardInputSchema;\nexport const DriveForwardOutputSchema = OpResultSchema;\n\nexport const DriveClickInputSchema = z.object({\n session_id: z.string().min(1),\n locator: LocatorSchema,\n tab_id: z.number().finite().optional(),\n click_count: z.number().finite().optional(),\n});\nexport const DriveClickOutputSchema = OpResultSchema;\n\nexport const DriveHoverInputSchema = z.object({\n session_id: z.string().min(1),\n locator: LocatorSchema,\n delay_ms: z.number().min(0).max(10000).optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveHoverOutputSchema = z.object({\n format: z.literal('html'),\n snapshot: z.string(),\n});\n\nexport const DriveSelectInputSchema = z\n .object({\n session_id: z.string().min(1),\n locator: LocatorSchema,\n value: z.string().min(1).optional(),\n text: z.string().min(1).optional(),\n index: z.number().int().min(0).optional(),\n tab_id: z.number().finite().optional(),\n })\n .refine((value) => value.value || value.text || value.index !== undefined, {\n message: 'Either value, text, or index must be provided.',\n path: ['select'],\n });\nexport const DriveSelectOutputSchema = OpResultSchema;\n\nexport const DriveTypeInputSchema = z.object({\n session_id: z.string().min(1),\n locator: LocatorSchema.optional(),\n text: z.string().min(1),\n tab_id: z.number().finite().optional(),\n clear: z.boolean().default(false),\n submit: z.boolean().default(false),\n});\nexport const DriveTypeOutputSchema = OpResultSchema;\n\nexport const DriveFillFormFieldSchema = z\n .object({\n selector: z.string().min(1).optional(),\n locator: LocatorSchema.optional(),\n value: z.union([z.string(), z.boolean()]),\n type: z\n .enum(['auto', 'text', 'select', 'checkbox', 'radio', 'contentEditable'])\n .default('auto'),\n submit: z.boolean().default(false),\n })\n .refine((value) => Boolean(value.selector || value.locator), {\n message: 'fill_form field requires selector or locator.',\n path: ['selector'],\n });\n\nexport const DriveFillFormInputSchema = z.object({\n session_id: z.string().min(1),\n fields: z.array(DriveFillFormFieldSchema).min(1),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveFillFormOutputSchema = z.object({\n filled: z.number().finite(),\n attempted: z.number().finite(),\n errors: z.array(z.string()).optional(),\n});\n\nexport const DriveDragInputSchema = z.object({\n session_id: z.string().min(1),\n from: LocatorSchema,\n to: LocatorSchema,\n steps: z.number().min(1).max(50).default(12),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveDragOutputSchema = OpResultSchema;\n\nexport const DriveHandleDialogInputSchema = z.object({\n session_id: z.string().min(1),\n action: z.enum(['accept', 'dismiss']),\n promptText: z.string().optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveHandleDialogOutputSchema = OpResultSchema;\n\nexport const DialogAcceptInputSchema = SessionIdSchema.extend({\n promptText: z.string().optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DialogAcceptOutputSchema = OpResultSchema;\n\nexport const DialogDismissInputSchema = SessionIdSchema.extend({\n tab_id: z.number().finite().optional(),\n});\nexport const DialogDismissOutputSchema = OpResultSchema;\n\nexport const DriveKeyModifiersSchema = z.object({\n ctrl: z.boolean().optional(),\n alt: z.boolean().optional(),\n shift: z.boolean().optional(),\n meta: z.boolean().optional(),\n});\n\nexport const DriveKeyPressInputSchema = z.object({\n session_id: z.string().min(1),\n key: z.string().min(1),\n modifiers: DriveKeyModifiersSchema.optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveKeyPressOutputSchema = OpResultSchema;\n\nexport const DriveKeyModifierSchema = z.enum(['ctrl', 'alt', 'shift', 'meta']);\n\nexport const DriveKeyInputSchema = z.object({\n session_id: z.string().min(1),\n key: z.string().min(1),\n modifiers: z.array(DriveKeyModifierSchema).optional(),\n repeat: z.number().int().min(1).max(50).optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveKeyOutputSchema = OpResultSchema;\n\nexport const DriveScrollInputSchema = z\n .object({\n session_id: z.string().min(1),\n delta_x: z.number().finite().optional(),\n delta_y: z.number().finite().optional(),\n top: z.number().finite().optional(),\n left: z.number().finite().optional(),\n behavior: z.enum(['auto', 'smooth']).optional(),\n tab_id: z.number().finite().optional(),\n })\n .refine(\n (value) =>\n value.delta_x !== undefined ||\n value.delta_y !== undefined ||\n value.top !== undefined ||\n value.left !== undefined,\n {\n message: 'scroll requires delta_x/delta_y or top/left.',\n path: ['scroll'],\n }\n );\nexport const DriveScrollOutputSchema = OpResultSchema;\n\nexport const DriveWaitForInputSchema = z.object({\n session_id: z.string().min(1),\n condition: DriveWaitConditionSchema,\n timeout_ms: z.number().finite().optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveWaitForOutputSchema = OpResultSchema;\n\nexport const DriveTabInfoSchema = z.object({\n tab_id: z.number().finite(),\n window_id: z.number().finite(),\n url: z.string().min(1),\n title: z.string(),\n active: z.boolean().optional(),\n last_active_at: z.string().datetime().optional(),\n});\n\nexport const DriveTabListInputSchema = SessionIdSchema;\nexport const DriveTabListOutputSchema = z.object({\n tabs: z.array(DriveTabInfoSchema),\n});\n\nexport const DriveTabActivateInputSchema = z.object({\n session_id: z.string().min(1),\n tab_id: z.number().finite(),\n});\nexport const DriveTabActivateOutputSchema = OpResultSchema;\n\nexport const DriveTabCloseInputSchema = z.object({\n session_id: z.string().min(1),\n tab_id: z.number().finite(),\n});\nexport const DriveTabCloseOutputSchema = OpResultSchema;\n\nexport const InspectDomFormatSchema = z.enum(['ax', 'html']);\nexport const InspectConsistencySchema = z.enum(['best_effort', 'quiesce']);\n\nexport const TargetHintSchema = z.object({\n url: z.string().min(1).optional(),\n title: z.string().min(1).optional(),\n last_active_at: z.string().optional(),\n lastActiveAt: z.string().optional(),\n});\n\nexport const FormFieldInfoSchema = z.object({\n name: z.string(),\n type: z.string(),\n value: z.string(),\n options: z.array(z.string()).optional(),\n});\n\nexport const FormInfoSchema = z.object({\n selector: z.string(),\n action: z.string().optional(),\n method: z.string().optional(),\n fields: z.array(FormFieldInfoSchema),\n});\n\nexport const StorageEntrySchema = z.object({\n key: z.string(),\n value: z.string(),\n});\n\nexport const PageStateSchema = z.object({\n forms: z.array(FormInfoSchema),\n localStorage: z.array(StorageEntrySchema),\n sessionStorage: z.array(StorageEntrySchema),\n cookies: z.array(StorageEntrySchema),\n warnings: z.array(z.string()).optional(),\n});\n\nexport const DomSnapshotSchema = z\n .object({\n format: InspectDomFormatSchema,\n snapshot: z.unknown(),\n })\n .passthrough();\n\nexport const InspectDomSnapshotInputSchema = z.object({\n session_id: z.string().min(1),\n format: InspectDomFormatSchema.default('ax'),\n consistency: InspectConsistencySchema.default('best_effort'),\n interactive: z.boolean().default(false),\n compact: z.boolean().default(false),\n // Used primarily to bound large AX trees for LLM/agent consumption.\n // CLI passes this as a string, so coerce for convenience.\n max_nodes: z.coerce.number().int().positive().max(50000).optional(),\n selector: z.string().min(1).optional(),\n target: TargetHintSchema.optional(),\n});\nexport const InspectDomSnapshotOutputSchema = DomSnapshotSchema;\n\nexport const DomDiffResultSchema = z.object({\n added: z.array(z.string()),\n removed: z.array(z.string()),\n changed: z.array(z.string()),\n summary: z.string(),\n});\n\nexport const InspectDomDiffInputSchema = SessionIdSchema;\nexport const InspectDomDiffOutputSchema = DomDiffResultSchema;\n\nexport const InspectFindRoleInputSchema = SessionIdSchema.extend({\n kind: z.literal('role'),\n role: z.string().min(1),\n name: z.string().min(1).optional(),\n target: TargetHintSchema.optional(),\n});\n\nexport const InspectFindTextInputSchema = SessionIdSchema.extend({\n kind: z.literal('text'),\n text: z.string().min(1),\n target: TargetHintSchema.optional(),\n});\n\nexport const InspectFindLabelInputSchema = SessionIdSchema.extend({\n kind: z.literal('label'),\n label: z.string().min(1),\n target: TargetHintSchema.optional(),\n});\n\nexport const InspectFindInputSchema = z.discriminatedUnion('kind', [\n InspectFindRoleInputSchema,\n InspectFindTextInputSchema,\n InspectFindLabelInputSchema,\n]);\n\nexport const InspectFindMatchSchema = z.object({\n ref: z.string(),\n role: z.string().optional(),\n name: z.string().optional(),\n});\n\nexport const InspectFindOutputSchema = z.object({\n matches: z.array(InspectFindMatchSchema),\n warnings: z.array(z.string()).optional(),\n});\n\nexport const InspectPageStateInputSchema = SessionIdSchema.extend({\n target: TargetHintSchema.optional(),\n});\nexport const InspectPageStateOutputSchema = PageStateSchema;\n\nexport const InspectExtractContentFormatSchema = z.enum([\n 'markdown',\n 'text',\n 'article_json',\n]);\n\nexport const InspectExtractContentInputSchema = SessionIdSchema.extend({\n format: InspectExtractContentFormatSchema.default('markdown'),\n include_metadata: z.boolean().default(true),\n target: TargetHintSchema.optional(),\n});\n\nexport const InspectExtractContentOutputSchema = z.object({\n content: z.string(),\n title: z.string().optional(),\n byline: z.string().optional(),\n excerpt: z.string().optional(),\n siteName: z.string().optional(),\n warnings: z.array(z.string()).optional(),\n});\n\nexport const InspectConsoleListInputSchema = SessionIdSchema.extend({\n target: TargetHintSchema.optional(),\n});\n// Console output may expand over time; include a stable core + allow passthrough.\nexport const ConsoleSourceLocationSchema = z\n .object({\n url: z.string().optional(),\n // 1-based line/column for human readability.\n line: z.number().int().positive().optional(),\n column: z.number().int().positive().optional(),\n })\n .passthrough();\n\nexport const ConsoleStackFrameSchema = z\n .object({\n functionName: z.string().optional(),\n url: z.string().optional(),\n // 1-based line/column for human readability.\n line: z.number().int().positive().optional(),\n column: z.number().int().positive().optional(),\n })\n .passthrough();\n\nexport const ConsoleRemoteObjectSchema = z\n .object({\n type: z.string().optional(),\n subtype: z.string().optional(),\n description: z.string().optional(),\n value: z.unknown().optional(),\n unserializableValue: z.string().optional(),\n })\n .passthrough();\n\nexport const ConsoleEntrySchema = z\n .object({\n level: z.string().optional(),\n text: z.string().optional(),\n timestamp: z.string().datetime().optional(),\n source: ConsoleSourceLocationSchema.optional(),\n stack: z.array(ConsoleStackFrameSchema).optional(),\n exception: ConsoleRemoteObjectSchema.optional(),\n args: z.array(ConsoleRemoteObjectSchema).optional(),\n })\n .passthrough();\nexport const ConsoleListSchema = z\n .object({\n entries: z.array(ConsoleEntrySchema),\n })\n .passthrough();\nexport const InspectConsoleListOutputSchema = ConsoleListSchema;\n\nexport const ArtifactInfoSchema = z.object({\n artifact_id: z.string(),\n path: z.string(),\n mime: z.string(),\n});\n\nexport const InspectNetworkHarInputSchema = SessionIdSchema.extend({\n target: TargetHintSchema.optional(),\n});\nexport const InspectNetworkHarOutputSchema = ArtifactInfoSchema;\n\nexport const InspectEvaluateInputSchema = z.object({\n session_id: z.string().min(1),\n expression: z.string().min(1).optional(),\n target: TargetHintSchema.optional(),\n});\n// Evaluate output is implementation-defined; allow passthrough fields.\nexport const EvaluateResultSchema = z\n .object({\n value: z.unknown().optional(),\n exception: z.unknown().optional(),\n })\n .passthrough();\nexport const InspectEvaluateOutputSchema = EvaluateResultSchema;\n\nexport const InspectPerformanceMetricsInputSchema = SessionIdSchema.extend({\n target: TargetHintSchema.optional(),\n});\n// Performance metrics output shape may expand; allow passthrough metadata.\nexport const PerformanceMetricSchema = z\n .object({\n name: z.string(),\n value: z.number().finite(),\n })\n .passthrough();\nexport const PerformanceMetricsSchema = z\n .object({\n metrics: z.array(PerformanceMetricSchema),\n })\n .passthrough();\nexport const InspectPerformanceMetricsOutputSchema = PerformanceMetricsSchema;\n\nexport const ArtifactsScreenshotInputSchema = z.object({\n session_id: z.string().min(1),\n target: z.enum(['viewport', 'full']).default('viewport'),\n fullPage: z.boolean().default(false),\n selector: z.string().min(1).optional(),\n format: z.enum(['png', 'jpeg', 'webp']).default('png'),\n quality: z.number().min(0).max(100).optional(),\n});\nexport const ArtifactsScreenshotOutputSchema = ArtifactInfoSchema;\n\nexport const HealthCheckInputSchema = z.object({});\nexport const HealthCheckOutputSchema = z\n .object({\n started_at: z.string().min(1),\n uptime_ms: z.number().finite().nonnegative(),\n memory: z\n .object({\n rss: z.number().finite().nonnegative(),\n heapTotal: z.number().finite().nonnegative(),\n heapUsed: z.number().finite().nonnegative(),\n external: z.number().finite().nonnegative(),\n arrayBuffers: z.number().finite().nonnegative().optional(),\n })\n .passthrough(),\n sessions: z\n .object({\n active: z.number().finite().nonnegative(),\n })\n .passthrough(),\n extension: z\n .object({\n connected: z.boolean(),\n last_seen_at: z.string().min(1).optional(),\n })\n .passthrough(),\n })\n .passthrough();\n\nexport const DiagnosticsDoctorInputSchema = z.object({\n session_id: z.string().min(1).optional(),\n});\nexport const DiagnosticsDoctorOutputSchema = DiagnosticReportSchema;\n", "import {\n ErrorEnvelope,\n ErrorInfo,\n ApiEnvelope,\n} from '@btraut/browser-bridge-shared';\nimport { ZodError, z } from 'zod';\nimport { CoreClientError } from './core-client';\n\ntype OutputOptions = {\n json: boolean;\n};\n\nexport class CliError extends Error {\n readonly info: ErrorInfo;\n\n constructor(info: ErrorInfo) {\n super(info.message);\n this.info = info;\n }\n}\n\nexport const parseInput = <T>(schema: z.ZodType<T>, payload: unknown): T => {\n const result = schema.safeParse(payload);\n if (result.success) {\n return result.data;\n }\n\n const [issue] = result.error.issues;\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message: issue?.message ?? 'Invalid input.',\n retryable: false,\n details: { issues: result.error.issues },\n });\n};\n\nexport const outputEnvelope = (\n envelope: ApiEnvelope<unknown>,\n options: OutputOptions\n): void => {\n if (options.json) {\n console.log(JSON.stringify(envelope, null, 2));\n return;\n }\n\n if (envelope.ok) {\n if (typeof envelope.result === 'string') {\n console.log(envelope.result);\n return;\n }\n\n console.log(JSON.stringify(envelope.result, null, 2));\n return;\n }\n\n console.error(`${envelope.error.code}: ${envelope.error.message}`);\n if (envelope.error.details) {\n console.error(JSON.stringify(envelope.error.details, null, 2));\n }\n};\n\nconst toErrorInfo = (error: unknown): ErrorInfo => {\n if (error instanceof CliError) {\n return error.info;\n }\n\n if (error instanceof CoreClientError) {\n return error.info;\n }\n\n if (error instanceof ZodError) {\n const [issue] = error.issues;\n return {\n code: 'INVALID_ARGUMENT',\n message: issue?.message ?? 'Invalid input.',\n retryable: false,\n details: { issues: error.issues },\n };\n }\n\n if (error instanceof Error) {\n return {\n code: 'INTERNAL',\n message: error.message,\n retryable: false,\n };\n }\n\n return {\n code: 'INTERNAL',\n message: 'Unknown error.',\n retryable: false,\n };\n};\n\nexport const outputError = (error: unknown, options: OutputOptions): void => {\n const info = toErrorInfo(error);\n const envelope: ErrorEnvelope = { ok: false, error: info };\n\n if (options.json) {\n console.log(JSON.stringify(envelope, null, 2));\n return;\n }\n\n console.error(`${info.code}: ${info.message}`);\n if (info.details) {\n console.error(JSON.stringify(info.details, null, 2));\n }\n};\n", "import { ApiEnvelope, ErrorInfo } from '@btraut/browser-bridge-shared';\nimport { spawn } from 'node:child_process';\nimport { resolve } from 'node:path';\nimport { setTimeout as delay } from 'node:timers/promises';\n\ntype FetchLike = typeof fetch;\n\ntype SpawnLike = typeof spawn;\n\nexport class CoreClientError extends Error {\n readonly info: ErrorInfo;\n\n constructor(info: ErrorInfo) {\n super(info.message);\n this.name = 'CoreClientError';\n this.info = info;\n }\n}\n\nexport type CoreClientOptions = {\n host?: string;\n port?: number | string;\n ensureDaemon?: boolean;\n timeoutMs?: number;\n fetchImpl?: FetchLike;\n spawnImpl?: SpawnLike;\n};\n\nexport type CoreClient = {\n baseUrl: string;\n ensureReady: () => Promise<void>;\n post: <T>(path: string, body?: unknown) => Promise<ApiEnvelope<T>>;\n};\n\nconst DEFAULT_HOST = '127.0.0.1';\nconst DEFAULT_PORT = 3210;\n// Must be long enough to accommodate user-approval prompts in the extension.\nconst DEFAULT_TIMEOUT_MS = 30000;\nconst HEALTH_RETRY_MS = 250;\nconst HEALTH_ATTEMPTS = 20;\n\nconst resolveHost = (host?: string): string => {\n const candidate =\n host?.trim() ||\n process.env.BROWSER_BRIDGE_CORE_HOST ||\n process.env.BROWSER_VISION_CORE_HOST;\n if (candidate && candidate.length > 0) {\n return candidate;\n }\n return DEFAULT_HOST;\n};\n\nconst resolvePort = (port?: number | string): number => {\n const candidate =\n port ??\n (process.env.BROWSER_BRIDGE_CORE_PORT\n ? Number.parseInt(process.env.BROWSER_BRIDGE_CORE_PORT, 10)\n : process.env.BROWSER_VISION_CORE_PORT\n ? Number.parseInt(process.env.BROWSER_VISION_CORE_PORT, 10)\n : undefined);\n\n if (candidate === undefined || candidate === null) {\n return DEFAULT_PORT;\n }\n\n const parsed =\n typeof candidate === 'number' ? candidate : Number.parseInt(candidate, 10);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`Invalid port: ${String(candidate)}`);\n }\n\n return parsed;\n};\n\nconst resolveTimeoutMs = (timeoutMs?: number): number => {\n const candidate =\n timeoutMs ??\n (process.env.BROWSER_BRIDGE_CORE_TIMEOUT_MS\n ? Number.parseInt(process.env.BROWSER_BRIDGE_CORE_TIMEOUT_MS, 10)\n : process.env.BROWSER_VISION_CORE_TIMEOUT_MS\n ? Number.parseInt(process.env.BROWSER_VISION_CORE_TIMEOUT_MS, 10)\n : undefined);\n\n if (candidate === undefined || candidate === null) {\n return DEFAULT_TIMEOUT_MS;\n }\n\n const parsed = typeof candidate === 'number' ? candidate : Number(candidate);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`Invalid timeoutMs: ${String(candidate)}`);\n }\n\n return Math.floor(parsed);\n};\n\nconst normalizePath = (path: string): string =>\n path.startsWith('/') ? path : `/${path}`;\n\nexport const createCoreClient = (\n options: CoreClientOptions = {}\n): CoreClient => {\n const host = resolveHost(options.host);\n const port = resolvePort(options.port);\n const baseUrl = `http://${host}:${port}`;\n const timeoutMs = resolveTimeoutMs(options.timeoutMs);\n const fetchImpl = options.fetchImpl ?? fetch;\n const spawnImpl = options.spawnImpl ?? spawn;\n const ensureDaemon = options.ensureDaemon ?? true;\n\n const requestJson = async <T>(\n method: 'GET' | 'POST',\n path: string,\n body?: unknown\n ): Promise<T> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n let response: Response;\n try {\n response = await fetchImpl(`${baseUrl}${normalizePath(path)}`, {\n method,\n headers: {\n 'content-type': 'application/json',\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (error) {\n if (\n controller.signal.aborted ||\n (error instanceof Error && error.name === 'AbortError')\n ) {\n throw new CoreClientError({\n code: 'TIMEOUT',\n message: `Core request timed out after ${timeoutMs}ms.`,\n retryable: true,\n details: {\n timeout_ms: timeoutMs,\n base_url: baseUrl,\n path: normalizePath(path),\n },\n });\n }\n throw error;\n }\n\n const raw = await response.text();\n if (!raw) {\n throw new Error(`Empty response from Core (${response.status}).`);\n }\n\n try {\n return JSON.parse(raw) as T;\n } catch (error) {\n const message =\n error instanceof Error ? error.message : 'Unknown JSON parse error';\n throw new Error(`Failed to parse Core response: ${message}`);\n }\n } finally {\n clearTimeout(timeout);\n }\n };\n\n const checkHealth = async (): Promise<boolean> => {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n let response: Response;\n try {\n response = await fetchImpl(`${baseUrl}/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n } catch (error) {\n if (\n controller.signal.aborted ||\n (error instanceof Error && error.name === 'AbortError')\n ) {\n return false;\n }\n throw error;\n }\n if (!response.ok) {\n return false;\n }\n const data = (await response.json().catch(() => null)) as {\n ok?: boolean;\n } | null;\n return Boolean(data?.ok);\n } finally {\n clearTimeout(timeout);\n }\n } catch {\n return false;\n }\n };\n\n const spawnDaemon = (): void => {\n const coreEntry = resolve(__dirname, 'api.js');\n const script = `const { startCoreServer } = require(${JSON.stringify(\n coreEntry\n )});\\nstartCoreServer({ host: ${JSON.stringify(\n host\n )}, port: ${port} })\\n .catch((err) => { console.error(err); process.exit(1); });`;\n\n const child = spawnImpl(process.execPath, ['-e', script], {\n detached: true,\n stdio: 'ignore',\n env: {\n ...process.env,\n BROWSER_BRIDGE_CORE_HOST: host,\n BROWSER_BRIDGE_CORE_PORT: String(port),\n BROWSER_VISION_CORE_HOST: host,\n BROWSER_VISION_CORE_PORT: String(port),\n },\n });\n\n child.unref();\n };\n\n const ensureCoreRunning = async (): Promise<void> => {\n if (await checkHealth()) {\n return;\n }\n\n spawnDaemon();\n\n for (let attempt = 0; attempt < HEALTH_ATTEMPTS; attempt += 1) {\n await delay(HEALTH_RETRY_MS);\n if (await checkHealth()) {\n return;\n }\n }\n\n throw new Error(`Core daemon failed to start on ${host}:${port}.`);\n };\n\n let ensurePromise: Promise<void> | null = null;\n const ensureReady = async (): Promise<void> => {\n if (!ensureDaemon) {\n return;\n }\n if (!ensurePromise) {\n ensurePromise = ensureCoreRunning();\n }\n await ensurePromise;\n };\n\n const post = async <T>(\n path: string,\n body?: unknown\n ): Promise<ApiEnvelope<T>> => {\n await ensureReady();\n return requestJson<ApiEnvelope<T>>('POST', path, body);\n };\n\n return { baseUrl, ensureReady, post };\n};\n", "import { Command } from 'commander';\nimport { ApiEnvelope } from '@btraut/browser-bridge-shared';\nimport { createCoreClient, CoreClient } from './core-client';\nimport { outputEnvelope, outputError } from './cli-output';\n\ntype GlobalOptions = {\n host?: string;\n port?: number | string;\n json?: boolean;\n daemon?: boolean;\n};\n\nconst getRootCommand = (command: Command): Command => {\n let current: Command = command;\n while (current.parent) {\n current = current.parent;\n }\n return current;\n};\n\nexport const getGlobalOptions = (command: Command): GlobalOptions => {\n const root = getRootCommand(command);\n return root.opts<GlobalOptions>();\n};\n\nexport const createClientFromCommand = (command: Command): CoreClient => {\n const options = getGlobalOptions(command);\n return createCoreClient({\n host: options.host,\n port: options.port,\n ensureDaemon: options.daemon !== false,\n });\n};\n\nexport const runCommand = async <T>(\n command: Command,\n work: (client: CoreClient, options: GlobalOptions) => Promise<ApiEnvelope<T>>\n): Promise<void> => {\n const options = getGlobalOptions(command);\n const client = createClientFromCommand(command);\n\n try {\n const envelope = await work(client, options);\n outputEnvelope(envelope, { json: Boolean(options.json) });\n if (!envelope.ok) {\n process.exitCode = 1;\n }\n } catch (error) {\n outputError(error, { json: Boolean(options.json) });\n process.exitCode = 1;\n }\n};\n\nexport const runLocal = async (\n command: Command,\n work: (options: GlobalOptions) => Promise<ApiEnvelope<unknown>>\n): Promise<void> => {\n const options = getGlobalOptions(command);\n\n try {\n const envelope = await work(options);\n outputEnvelope(envelope, { json: Boolean(options.json) });\n if (!envelope.ok) {\n process.exitCode = 1;\n }\n } catch (error) {\n outputError(error, { json: Boolean(options.json) });\n process.exitCode = 1;\n }\n};\n", "import { Command } from 'commander';\nimport { ArtifactsScreenshotInputSchema } from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nconst parseNumber = (value: unknown): number | undefined => {\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n};\n\nexport const registerArtifactsCommands = (program: Command): void => {\n const artifacts = program\n .command('artifacts')\n .description('Artifact commands');\n\n artifacts\n .command('screenshot')\n .description('Request a screenshot artifact')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--target <target>', 'Screenshot target (viewport, full)')\n .option('--full-page', 'Capture full page (alias for --target full)')\n .option(\n '--selector <selector>',\n 'Capture a specific element by CSS selector'\n )\n .option('--format <format>', 'Screenshot format (png, jpeg, webp)')\n .option('--quality <quality>', 'Screenshot quality (0-100) for jpeg/webp')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(ArtifactsScreenshotInputSchema, {\n session_id: options.sessionId,\n target: options.target,\n fullPage: Boolean(options.fullPage),\n selector: options.selector,\n format: options.format,\n quality: parseNumber(options.quality),\n });\n return client.post('/artifacts/screenshot', payload);\n });\n });\n};\n", "import { Command } from 'commander';\nimport {\n DialogAcceptInputSchema,\n DialogDismissInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nconst parseNumber = (value: unknown): number | undefined => {\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n};\n\nexport const registerDialogCommands = (program: Command): void => {\n const dialog = program.command('dialog').description('Dialog commands');\n\n dialog\n .command('accept')\n .description('Accept a JavaScript dialog')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--prompt-text <text>', 'Prompt text for prompt() dialogs')\n .option('--tab-id <id>', 'Tab identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DialogAcceptInputSchema, {\n session_id: options.sessionId,\n promptText: options.promptText,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/dialog/accept', payload);\n });\n });\n\n dialog\n .command('dismiss')\n .description('Dismiss a JavaScript dialog')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DialogDismissInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/dialog/dismiss', payload);\n });\n });\n};\n", "import { Command } from 'commander';\nimport {\n DiagnosticsDoctorInputSchema,\n HealthCheckInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nexport const registerDiagnosticsCommands = (program: Command): void => {\n const diagnostics = program\n .command('diagnostics')\n .description('Diagnostics commands');\n\n diagnostics\n .command('doctor')\n .description('Run diagnostics')\n .option('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DiagnosticsDoctorInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/diagnostics/doctor', payload);\n });\n });\n\n diagnostics\n .command('health-check')\n .description('Run a lightweight health check')\n .action(async (_options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(HealthCheckInputSchema, {});\n return client.post('/health_check', payload);\n });\n });\n};\n", "import { CliError } from './cli-output';\n\ntype LocatorRoleInput = {\n name: string;\n value?: string;\n};\n\nexport type LocatorInput = {\n ref?: string;\n testid?: string;\n css?: string;\n text?: string;\n role?: LocatorRoleInput;\n};\n\ntype LocatorOptions = {\n locatorRef?: string;\n locatorTestid?: string;\n locatorCss?: string;\n locatorText?: string;\n locatorRole?: string;\n locatorRoleValue?: string;\n};\n\nexport const buildLocator = (\n options: LocatorOptions\n): LocatorInput | undefined => {\n const locator: LocatorInput = {};\n\n if (options.locatorRef) {\n locator.ref = options.locatorRef;\n }\n\n if (options.locatorTestid) {\n locator.testid = options.locatorTestid;\n }\n\n if (options.locatorCss) {\n locator.css = options.locatorCss;\n }\n\n if (options.locatorText) {\n locator.text = options.locatorText;\n }\n\n if (options.locatorRoleValue && !options.locatorRole) {\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message: 'locator-role-value requires locator-role to be set.',\n retryable: false,\n details: { field: 'locator.role.value' },\n });\n }\n\n if (options.locatorRole) {\n locator.role = {\n name: options.locatorRole,\n ...(options.locatorRoleValue ? { value: options.locatorRoleValue } : {}),\n };\n }\n\n if (\n !locator.ref &&\n !locator.testid &&\n !locator.css &&\n !locator.text &&\n !locator.role\n ) {\n return undefined;\n }\n\n return locator;\n};\n\nexport const requireLocator = (options: LocatorOptions): LocatorInput => {\n const locator = buildLocator(options);\n if (!locator) {\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message: 'Locator must include at least one selector.',\n retryable: false,\n details: { field: 'locator' },\n });\n }\n return locator;\n};\n", "import { Command } from 'commander';\nimport {\n DriveClickInputSchema,\n DriveDragInputSchema,\n DriveFillFormInputSchema,\n DriveBackInputSchema,\n DriveForwardInputSchema,\n DriveGoBackInputSchema,\n DriveGoForwardInputSchema,\n DriveHandleDialogInputSchema,\n DriveHoverInputSchema,\n DriveSelectInputSchema,\n DriveKeyInputSchema,\n DriveKeyPressInputSchema,\n DriveNavigateInputSchema,\n DriveScrollInputSchema,\n DriveTabActivateInputSchema,\n DriveTabCloseInputSchema,\n DriveTabListInputSchema,\n DriveTypeInputSchema,\n DriveWaitForInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\nimport { buildLocator, requireLocator } from '../locator';\n\nconst parseNumber = (value: unknown): number | undefined => {\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n};\n\nconst parseJson = (value: string, label: string): unknown => {\n try {\n return JSON.parse(value);\n } catch {\n throw new Error(`${label} must be valid JSON.`);\n }\n};\n\nexport const registerDriveCommands = (program: Command): void => {\n const drive = program.command('drive').description('Drive commands');\n\n drive\n .command('navigate')\n .description('Navigate to a URL')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--url <url>', 'URL to navigate to')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--wait <mode>', 'Wait mode (none, domcontentloaded)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveNavigateInputSchema, {\n session_id: options.sessionId,\n url: options.url,\n tab_id: parseNumber(options.tabId),\n wait: options.wait,\n });\n return client.post('/drive/navigate', payload);\n });\n });\n\n drive\n .command('go-back')\n .description('Go back in browser history')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveGoBackInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/go_back', payload);\n });\n });\n\n drive\n .command('back')\n .description('Go back in browser history')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveBackInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/back', payload);\n });\n });\n\n drive\n .command('go-forward')\n .description('Go forward in browser history')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveGoForwardInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/go_forward', payload);\n });\n });\n\n drive\n .command('forward')\n .description('Go forward in browser history')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveForwardInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/forward', payload);\n });\n });\n\n drive\n .command('click')\n .description('Click an element')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--locator-ref <ref>', 'Locator ref (e.g., @e1)')\n .option('--locator-testid <id>', 'Locator test id')\n .option('--locator-css <selector>', 'Locator CSS selector')\n .option('--locator-text <text>', 'Locator text')\n .option('--locator-role <role>', 'Locator role name')\n .option('--locator-role-value <value>', 'Locator role value')\n .option('--click-count <count>', 'Click count')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const locator = requireLocator({\n locatorRef: options.locatorRef,\n locatorTestid: options.locatorTestid,\n locatorCss: options.locatorCss,\n locatorText: options.locatorText,\n locatorRole: options.locatorRole,\n locatorRoleValue: options.locatorRoleValue,\n });\n const payload = parseInput(DriveClickInputSchema, {\n session_id: options.sessionId,\n locator,\n tab_id: parseNumber(options.tabId),\n click_count: parseNumber(options.clickCount),\n });\n return client.post('/drive/click', payload);\n });\n });\n\n drive\n .command('hover')\n .description('Hover over an element')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--locator-ref <ref>', 'Locator ref (e.g., @e1)')\n .option('--locator-testid <id>', 'Locator test id')\n .option('--locator-css <selector>', 'Locator CSS selector')\n .option('--locator-text <text>', 'Locator text')\n .option('--locator-role <role>', 'Locator role name')\n .option('--locator-role-value <value>', 'Locator role value')\n .option('--delay-ms <ms>', 'Delay after hover in milliseconds')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const locator = requireLocator({\n locatorRef: options.locatorRef,\n locatorTestid: options.locatorTestid,\n locatorCss: options.locatorCss,\n locatorText: options.locatorText,\n locatorRole: options.locatorRole,\n locatorRoleValue: options.locatorRoleValue,\n });\n const payload = parseInput(DriveHoverInputSchema, {\n session_id: options.sessionId,\n locator,\n delay_ms: parseNumber(options.delayMs),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/hover', payload);\n });\n });\n\n drive\n .command('select')\n .description('Select an option in a dropdown')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--locator-ref <ref>', 'Locator ref (e.g., @e1)')\n .option('--locator-testid <id>', 'Locator test id')\n .option('--locator-css <selector>', 'Locator CSS selector')\n .option('--locator-text <text>', 'Locator text')\n .option('--locator-role <role>', 'Locator role name')\n .option('--locator-role-value <value>', 'Locator role value')\n .option('--value <value>', 'Option value attribute')\n .option('--text <text>', 'Option visible text')\n .option('--index <index>', 'Option index (0-based)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const locator = requireLocator({\n locatorRef: options.locatorRef,\n locatorTestid: options.locatorTestid,\n locatorCss: options.locatorCss,\n locatorText: options.locatorText,\n locatorRole: options.locatorRole,\n locatorRoleValue: options.locatorRoleValue,\n });\n const payload = parseInput(DriveSelectInputSchema, {\n session_id: options.sessionId,\n locator,\n value: options.value,\n text: options.text,\n index: parseNumber(options.index),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/select', payload);\n });\n });\n\n drive\n .command('type')\n .description('Type into a field')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--text <text>', 'Text to enter')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--locator-ref <ref>', 'Locator ref (e.g., @e1)')\n .option('--locator-testid <id>', 'Locator test id')\n .option('--locator-css <selector>', 'Locator CSS selector')\n .option('--locator-text <text>', 'Locator text')\n .option('--locator-role <role>', 'Locator role name')\n .option('--locator-role-value <value>', 'Locator role value')\n .option('--clear', 'Clear input before typing')\n .option('--submit', 'Submit after typing')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const locator = buildLocator({\n locatorRef: options.locatorRef,\n locatorTestid: options.locatorTestid,\n locatorCss: options.locatorCss,\n locatorText: options.locatorText,\n locatorRole: options.locatorRole,\n locatorRoleValue: options.locatorRoleValue,\n });\n const payload = parseInput(DriveTypeInputSchema, {\n session_id: options.sessionId,\n locator,\n text: options.text,\n tab_id: parseNumber(options.tabId),\n clear: Boolean(options.clear),\n submit: Boolean(options.submit),\n });\n return client.post('/drive/type', payload);\n });\n });\n\n drive\n .command('fill-form')\n .description('Fill multiple form fields')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--fields <json>', 'JSON array of fields to fill')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const fields = parseJson(options.fields, 'fields');\n const payload = parseInput(DriveFillFormInputSchema, {\n session_id: options.sessionId,\n fields,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/fill_form', payload);\n });\n });\n\n drive\n .command('drag')\n .description('Drag an element to a target')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--from-locator-ref <ref>', 'Source locator ref (e.g., @e1)')\n .option('--from-locator-testid <id>', 'Source locator test id')\n .option('--from-locator-css <selector>', 'Source locator CSS selector')\n .option('--from-locator-text <text>', 'Source locator text')\n .option('--from-locator-role <role>', 'Source locator role name')\n .option('--from-locator-role-value <value>', 'Source locator role value')\n .option('--to-locator-ref <ref>', 'Target locator ref (e.g., @e1)')\n .option('--to-locator-testid <id>', 'Target locator test id')\n .option('--to-locator-css <selector>', 'Target locator CSS selector')\n .option('--to-locator-text <text>', 'Target locator text')\n .option('--to-locator-role <role>', 'Target locator role name')\n .option('--to-locator-role-value <value>', 'Target locator role value')\n .option('--steps <steps>', 'Number of drag steps')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const from = requireLocator({\n locatorRef: options.fromLocatorRef,\n locatorTestid: options.fromLocatorTestid,\n locatorCss: options.fromLocatorCss,\n locatorText: options.fromLocatorText,\n locatorRole: options.fromLocatorRole,\n locatorRoleValue: options.fromLocatorRoleValue,\n });\n const to = requireLocator({\n locatorRef: options.toLocatorRef,\n locatorTestid: options.toLocatorTestid,\n locatorCss: options.toLocatorCss,\n locatorText: options.toLocatorText,\n locatorRole: options.toLocatorRole,\n locatorRoleValue: options.toLocatorRoleValue,\n });\n const payload = parseInput(DriveDragInputSchema, {\n session_id: options.sessionId,\n from,\n to,\n steps: parseNumber(options.steps),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/drag', payload);\n });\n });\n\n drive\n .command('handle-dialog')\n .description('Handle a JavaScript dialog')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--action <action>', 'Dialog action (accept, dismiss)')\n .option('--prompt-text <text>', 'Prompt text for prompt() dialogs')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveHandleDialogInputSchema, {\n session_id: options.sessionId,\n action: options.action,\n promptText: options.promptText,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/handle_dialog', payload);\n });\n });\n\n drive\n .command('key-press')\n .description('Press a keyboard key')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--key <key>', 'Key to press (e.g. Enter, ArrowDown)')\n .option('--ctrl', 'Hold control modifier')\n .option('--alt', 'Hold alt modifier')\n .option('--shift', 'Hold shift modifier')\n .option('--meta', 'Hold meta modifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveKeyPressInputSchema, {\n session_id: options.sessionId,\n key: options.key,\n modifiers: {\n ctrl: Boolean(options.ctrl),\n alt: Boolean(options.alt),\n shift: Boolean(options.shift),\n meta: Boolean(options.meta),\n },\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/key_press', payload);\n });\n });\n\n drive\n .command('key')\n .description('Press a keyboard key with modifiers')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--key <key>', 'Key to press (e.g. Enter, ArrowDown)')\n .option(\n '--modifier <modifier>',\n 'Modifier key (ctrl, alt, shift, meta)',\n (value: string, previous: string[]) => [...(previous ?? []), value],\n []\n )\n .option('--repeat <count>', 'Number of times to press')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveKeyInputSchema, {\n session_id: options.sessionId,\n key: options.key,\n modifiers: options.modifier,\n repeat: parseNumber(options.repeat),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/key', payload);\n });\n });\n\n drive\n .command('scroll')\n .description('Scroll the page')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--delta-x <px>', 'Scroll delta X')\n .option('--delta-y <px>', 'Scroll delta Y')\n .option('--top <px>', 'Scroll top position')\n .option('--left <px>', 'Scroll left position')\n .option('--behavior <mode>', 'Scroll behavior (auto, smooth)')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveScrollInputSchema, {\n session_id: options.sessionId,\n delta_x: parseNumber(options.deltaX),\n delta_y: parseNumber(options.deltaY),\n top: parseNumber(options.top),\n left: parseNumber(options.left),\n behavior: options.behavior,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/scroll', payload);\n });\n });\n\n drive\n .command('wait-for')\n .description('Wait for a condition')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .requiredOption(\n '--kind <kind>',\n 'Condition kind (locator_visible, text_present, url_matches)'\n )\n .requiredOption('--value <value>', 'Condition value')\n .option('--timeout-ms <ms>', 'Timeout in milliseconds')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveWaitForInputSchema, {\n session_id: options.sessionId,\n condition: {\n kind: options.kind,\n value: options.value,\n },\n timeout_ms: parseNumber(options.timeoutMs),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/wait_for', payload);\n });\n });\n\n drive\n .command('tab-list')\n .description('List browser tabs')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveTabListInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/drive/tab_list', payload);\n });\n });\n\n drive\n .command('tab-activate')\n .description('Activate a tab')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--tab-id <id>', 'Tab identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveTabActivateInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/tab_activate', payload);\n });\n });\n\n drive\n .command('tab-close')\n .description('Close a tab')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--tab-id <id>', 'Tab identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveTabCloseInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/tab_close', payload);\n });\n });\n};\n", "import { Command } from 'commander';\nimport {\n InspectConsoleListInputSchema,\n InspectDomDiffInputSchema,\n InspectDomSnapshotInputSchema,\n InspectExtractContentInputSchema,\n InspectEvaluateInputSchema,\n InspectFindInputSchema,\n InspectNetworkHarInputSchema,\n InspectPageStateInputSchema,\n InspectPerformanceMetricsInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { CliError, parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nexport const registerInspectCommands = (program: Command): void => {\n const inspect = program.command('inspect').description('Inspect commands');\n\n inspect\n .command('dom-snapshot')\n .description('Fetch a DOM snapshot')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--format <format>', 'Snapshot format (ax, html)')\n .option('--consistency <mode>', 'Consistency mode (best_effort, quiesce)')\n .option('-i, --interactive', 'Only include interactive elements')\n .option('-c, --compact', 'Remove empty/decorative nodes')\n .option('--max-nodes <n>', 'Limit AX snapshot to at most n nodes')\n .option('-s, --selector <selector>', 'Limit snapshot to selector')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectDomSnapshotInputSchema, {\n session_id: options.sessionId,\n format: options.format,\n consistency: options.consistency,\n interactive: options.interactive,\n compact: options.compact,\n max_nodes: options.maxNodes,\n selector: options.selector,\n });\n return client.post('/inspect/dom_snapshot', payload);\n });\n });\n\n inspect\n .command('dom-diff')\n .description('Compare recent DOM snapshots')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectDomDiffInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/dom_diff', payload);\n });\n });\n\n inspect\n .command('find')\n .description('Find elements and return refs')\n .requiredOption('--session-id <id>', 'Session identifier')\n .argument('<kind>', 'Find kind (role, text, label)')\n .argument('<value>', 'Role name or text to match')\n .option('--name <name>', 'Accessible name to match (role only)')\n .action(async (kind, value, options, command) => {\n await runCommand(command, (client) => {\n const normalizedKind = String(kind ?? '').toLowerCase();\n let payload: unknown;\n if (normalizedKind === 'role') {\n payload = {\n session_id: options.sessionId,\n kind: 'role',\n role: value,\n name: options.name,\n };\n } else if (normalizedKind === 'text') {\n payload = {\n session_id: options.sessionId,\n kind: 'text',\n text: value,\n };\n } else if (normalizedKind === 'label') {\n payload = {\n session_id: options.sessionId,\n kind: 'label',\n label: value,\n };\n } else {\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message: 'kind must be role, text, or label.',\n retryable: false,\n details: { field: 'kind' },\n });\n }\n const parsed = parseInput(InspectFindInputSchema, payload);\n return client.post('/inspect/find', parsed);\n });\n });\n\n inspect\n .command('extract-content')\n .description('Extract main content from the page')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--format <format>', 'Output format (markdown, text, article_json)')\n .option('--include-metadata', 'Include article metadata')\n .option('--no-include-metadata', 'Exclude article metadata')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectExtractContentInputSchema, {\n session_id: options.sessionId,\n format: options.format,\n include_metadata: options.includeMetadata,\n });\n return client.post('/inspect/extract_content', payload);\n });\n });\n\n inspect\n .command('page-state')\n .description('Capture form, storage, and cookie state')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectPageStateInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/page_state', payload);\n });\n });\n\n inspect\n .command('console-list')\n .description('Fetch console entries')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectConsoleListInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/console_list', payload);\n });\n });\n\n inspect\n .command('network-har')\n .description('Fetch network HAR')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectNetworkHarInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/network_har', payload);\n });\n });\n\n inspect\n .command('evaluate')\n .description('Evaluate a JavaScript expression')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--expression <expr>', 'Expression to evaluate')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectEvaluateInputSchema, {\n session_id: options.sessionId,\n expression: options.expression,\n });\n return client.post('/inspect/evaluate', payload);\n });\n });\n\n inspect\n .command('performance-metrics')\n .description('Fetch performance metrics')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectPerformanceMetricsInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/performance_metrics', payload);\n });\n });\n};\n", "import { ApiEnvelope } from '@btraut/browser-bridge-shared';\n\ntype FetchLike = typeof fetch;\n\nexport type CoreClientOptions = {\n host?: string;\n port?: number | string;\n timeoutMs?: number;\n fetchImpl?: FetchLike;\n};\n\nexport type CoreClient = {\n baseUrl: string;\n post: <T>(path: string, body?: unknown) => Promise<ApiEnvelope<T>>;\n};\n\nconst DEFAULT_HOST = '127.0.0.1';\nconst DEFAULT_PORT = 3210;\n// Must be long enough to accommodate user-approval prompts in the extension.\nconst DEFAULT_TIMEOUT_MS = 30000;\n\nconst resolveHost = (host?: string): string => {\n const candidate =\n host?.trim() ||\n process.env.BROWSER_BRIDGE_CORE_HOST ||\n process.env.BROWSER_VISION_CORE_HOST;\n if (candidate && candidate.length > 0) {\n return candidate;\n }\n return DEFAULT_HOST;\n};\n\nconst resolvePort = (port?: number | string): number => {\n const candidate =\n port ??\n (process.env.BROWSER_BRIDGE_CORE_PORT\n ? Number.parseInt(process.env.BROWSER_BRIDGE_CORE_PORT, 10)\n : process.env.BROWSER_VISION_CORE_PORT\n ? Number.parseInt(process.env.BROWSER_VISION_CORE_PORT, 10)\n : undefined);\n\n if (candidate === undefined || candidate === null) {\n return DEFAULT_PORT;\n }\n\n const parsed =\n typeof candidate === 'number' ? candidate : Number.parseInt(candidate, 10);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`Invalid port: ${String(candidate)}`);\n }\n\n return parsed;\n};\n\nconst normalizePath = (path: string): string =>\n path.startsWith('/') ? path : `/${path}`;\n\nexport const createCoreClient = (\n options: CoreClientOptions = {}\n): CoreClient => {\n const host = resolveHost(options.host);\n const port = resolvePort(options.port);\n const baseUrl = `http://${host}:${port}`;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const fetchImpl = options.fetchImpl ?? fetch;\n\n const requestJson = async <T>(path: string, body?: unknown): Promise<T> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetchImpl(`${baseUrl}${normalizePath(path)}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller.signal,\n });\n\n const raw = await response.text();\n if (!raw) {\n throw new Error(`Empty response from Core (${response.status}).`);\n }\n\n try {\n return JSON.parse(raw) as T;\n } catch (error) {\n const message =\n error instanceof Error ? error.message : 'Unknown JSON parse error';\n throw new Error(`Failed to parse Core response: ${message}`);\n }\n } finally {\n clearTimeout(timeout);\n }\n };\n\n const post = async <T>(\n path: string,\n body?: unknown\n ): Promise<ApiEnvelope<T>> => {\n return requestJson<ApiEnvelope<T>>(path, body);\n };\n\n return { baseUrl, post };\n};\n", "import {\n successEnvelopeSchema,\n ArtifactsScreenshotInputSchema,\n ArtifactsScreenshotOutputSchema,\n DiagnosticsDoctorInputSchema,\n DiagnosticsDoctorOutputSchema,\n DialogAcceptInputSchema,\n DialogAcceptOutputSchema,\n DialogDismissInputSchema,\n DialogDismissOutputSchema,\n HealthCheckInputSchema,\n HealthCheckOutputSchema,\n ErrorEnvelopeSchema,\n DriveClickInputSchema,\n DriveClickOutputSchema,\n DriveDragInputSchema,\n DriveDragOutputSchema,\n DriveFillFormInputSchema,\n DriveFillFormOutputSchema,\n DriveBackInputSchema,\n DriveBackOutputSchema,\n DriveForwardInputSchema,\n DriveForwardOutputSchema,\n DriveGoBackInputSchema,\n DriveGoBackOutputSchema,\n DriveGoForwardInputSchema,\n DriveGoForwardOutputSchema,\n DriveHandleDialogInputSchema,\n DriveHandleDialogOutputSchema,\n DriveHoverInputSchema,\n DriveHoverOutputSchema,\n DriveSelectInputSchema,\n DriveSelectOutputSchema,\n DriveKeyInputSchema,\n DriveKeyOutputSchema,\n DriveKeyPressInputSchema,\n DriveKeyPressOutputSchema,\n DriveNavigateInputSchema,\n DriveNavigateOutputSchema,\n DriveScrollInputSchema,\n DriveScrollOutputSchema,\n DriveTabActivateInputSchema,\n DriveTabActivateOutputSchema,\n DriveTabCloseInputSchema,\n DriveTabCloseOutputSchema,\n DriveTabListInputSchema,\n DriveTabListOutputSchema,\n DriveTypeInputSchema,\n DriveTypeOutputSchema,\n DriveWaitForInputSchema,\n DriveWaitForOutputSchema,\n InspectConsoleListInputSchema,\n InspectConsoleListOutputSchema,\n InspectDomDiffInputSchema,\n InspectDomDiffOutputSchema,\n InspectExtractContentInputSchema,\n InspectExtractContentOutputSchema,\n InspectDomSnapshotInputSchema,\n InspectDomSnapshotOutputSchema,\n InspectEvaluateInputSchema,\n InspectEvaluateOutputSchema,\n InspectFindInputSchema,\n InspectFindOutputSchema,\n InspectPageStateInputSchema,\n InspectPageStateOutputSchema,\n InspectNetworkHarInputSchema,\n InspectNetworkHarOutputSchema,\n InspectPerformanceMetricsInputSchema,\n InspectPerformanceMetricsOutputSchema,\n SessionCloseInputSchema,\n SessionCloseOutputSchema,\n SessionCreateInputSchema,\n SessionCreateOutputSchema,\n SessionRecoverInputSchema,\n SessionRecoverOutputSchema,\n SessionStatusInputSchema,\n SessionStatusOutputSchema,\n} from '@btraut/browser-bridge-shared';\nimport type {\n AnySchema,\n ZodRawShapeCompat,\n} from '@modelcontextprotocol/sdk/server/zod-compat';\nimport type {\n McpServer,\n ToolCallback,\n} from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport { CoreClient } from './core-client';\n\ntype ToolResult = CallToolResult;\n\ntype ToolConfig = {\n title: string;\n description: string;\n inputSchema: AnySchema | ZodRawShapeCompat;\n outputSchema: AnySchema | ZodRawShapeCompat;\n corePath: string;\n};\n\ntype ToolRegistrar = Pick<McpServer, 'registerTool'>;\n\ntype EnvelopeInput = Parameters<typeof successEnvelopeSchema>[0];\n\nconst toToolResult = (payload: unknown): ToolResult => {\n const content = [{ type: 'text' as const, text: JSON.stringify(payload) }];\n if (payload && typeof payload === 'object') {\n const isErrorEnvelope = ErrorEnvelopeSchema.safeParse(payload).success;\n return {\n content,\n structuredContent: payload as Record<string, unknown>,\n isError: isErrorEnvelope,\n };\n }\n return { content };\n};\n\nconst toInternalErrorEnvelope = (error: unknown) => ({\n ok: false as const,\n error: {\n code: 'INTERNAL' as const,\n message: error instanceof Error ? error.message : 'Unknown error.',\n retryable: false,\n },\n});\n\nconst envelope = (schema: EnvelopeInput) => successEnvelopeSchema(schema);\n\nexport const TOOL_DEFINITIONS: Array<{ name: string; config: ToolConfig }> = [\n {\n name: 'session.create',\n config: {\n title: 'Session Create',\n description: 'Create a new browser session.',\n inputSchema: SessionCreateInputSchema,\n outputSchema: envelope(SessionCreateOutputSchema),\n corePath: '/session/create',\n },\n },\n {\n name: 'session.status',\n config: {\n title: 'Session Status',\n description: 'Fetch session status.',\n inputSchema: SessionStatusInputSchema,\n outputSchema: envelope(SessionStatusOutputSchema),\n corePath: '/session/status',\n },\n },\n {\n name: 'session.recover',\n config: {\n title: 'Session Recover',\n description: 'Recover a session after errors.',\n inputSchema: SessionRecoverInputSchema,\n outputSchema: envelope(SessionRecoverOutputSchema),\n corePath: '/session/recover',\n },\n },\n {\n name: 'session.close',\n config: {\n title: 'Session Close',\n description: 'Close a session.',\n inputSchema: SessionCloseInputSchema,\n outputSchema: envelope(SessionCloseOutputSchema),\n corePath: '/session/close',\n },\n },\n {\n name: 'drive.navigate',\n config: {\n title: 'Drive Navigate',\n description: 'Navigate to a URL.',\n inputSchema: DriveNavigateInputSchema,\n outputSchema: envelope(DriveNavigateOutputSchema),\n corePath: '/drive/navigate',\n },\n },\n {\n name: 'drive.go_back',\n config: {\n title: 'Drive Go Back',\n description: 'Go back in browser history.',\n inputSchema: DriveGoBackInputSchema,\n outputSchema: envelope(DriveGoBackOutputSchema),\n corePath: '/drive/go_back',\n },\n },\n {\n name: 'drive.go_forward',\n config: {\n title: 'Drive Go Forward',\n description: 'Go forward in browser history.',\n inputSchema: DriveGoForwardInputSchema,\n outputSchema: envelope(DriveGoForwardOutputSchema),\n corePath: '/drive/go_forward',\n },\n },\n {\n name: 'drive.back',\n config: {\n title: 'Drive Back',\n description: 'Go back in browser history.',\n inputSchema: DriveBackInputSchema,\n outputSchema: envelope(DriveBackOutputSchema),\n corePath: '/drive/back',\n },\n },\n {\n name: 'drive.forward',\n config: {\n title: 'Drive Forward',\n description: 'Go forward in browser history.',\n inputSchema: DriveForwardInputSchema,\n outputSchema: envelope(DriveForwardOutputSchema),\n corePath: '/drive/forward',\n },\n },\n {\n name: 'drive.click',\n config: {\n title: 'Drive Click',\n description: 'Click an element.',\n inputSchema: DriveClickInputSchema,\n outputSchema: envelope(DriveClickOutputSchema),\n corePath: '/drive/click',\n },\n },\n {\n name: 'drive.hover',\n config: {\n title: 'Drive Hover',\n description: 'Hover over an element.',\n inputSchema: DriveHoverInputSchema,\n outputSchema: envelope(DriveHoverOutputSchema),\n corePath: '/drive/hover',\n },\n },\n {\n name: 'drive.select',\n config: {\n title: 'Drive Select',\n description: 'Select an option in a dropdown.',\n inputSchema: DriveSelectInputSchema,\n outputSchema: envelope(DriveSelectOutputSchema),\n corePath: '/drive/select',\n },\n },\n {\n name: 'drive.type',\n config: {\n title: 'Drive Type',\n description: 'Type into an element.',\n inputSchema: DriveTypeInputSchema,\n outputSchema: envelope(DriveTypeOutputSchema),\n corePath: '/drive/type',\n },\n },\n {\n name: 'drive.fill_form',\n config: {\n title: 'Drive Fill Form',\n description: 'Fill multiple form fields.',\n inputSchema: DriveFillFormInputSchema,\n outputSchema: envelope(DriveFillFormOutputSchema),\n corePath: '/drive/fill_form',\n },\n },\n {\n name: 'drive.drag',\n config: {\n title: 'Drive Drag',\n description: 'Drag an element to a target.',\n inputSchema: DriveDragInputSchema,\n outputSchema: envelope(DriveDragOutputSchema),\n corePath: '/drive/drag',\n },\n },\n {\n name: 'drive.handle_dialog',\n config: {\n title: 'Drive Handle Dialog',\n description: 'Handle a JavaScript dialog.',\n inputSchema: DriveHandleDialogInputSchema,\n outputSchema: envelope(DriveHandleDialogOutputSchema),\n corePath: '/drive/handle_dialog',\n },\n },\n {\n name: 'dialog.accept',\n config: {\n title: 'Dialog Accept',\n description: 'Accept a JavaScript dialog.',\n inputSchema: DialogAcceptInputSchema,\n outputSchema: envelope(DialogAcceptOutputSchema),\n corePath: '/dialog/accept',\n },\n },\n {\n name: 'dialog.dismiss',\n config: {\n title: 'Dialog Dismiss',\n description: 'Dismiss a JavaScript dialog.',\n inputSchema: DialogDismissInputSchema,\n outputSchema: envelope(DialogDismissOutputSchema),\n corePath: '/dialog/dismiss',\n },\n },\n {\n name: 'drive.key',\n config: {\n title: 'Drive Key',\n description: 'Press a keyboard key.',\n inputSchema: DriveKeyInputSchema,\n outputSchema: envelope(DriveKeyOutputSchema),\n corePath: '/drive/key',\n },\n },\n {\n name: 'drive.key_press',\n config: {\n title: 'Drive Key Press',\n description: 'Press a key on the active element.',\n inputSchema: DriveKeyPressInputSchema,\n outputSchema: envelope(DriveKeyPressOutputSchema),\n corePath: '/drive/key_press',\n },\n },\n {\n name: 'drive.scroll',\n config: {\n title: 'Drive Scroll',\n description:\n 'Scroll the default tab (agent window/tab unless tab_id is provided).',\n inputSchema: DriveScrollInputSchema,\n outputSchema: envelope(DriveScrollOutputSchema),\n corePath: '/drive/scroll',\n },\n },\n {\n name: 'drive.wait_for',\n config: {\n title: 'Drive Wait For',\n description: 'Wait for a drive condition.',\n inputSchema: DriveWaitForInputSchema,\n outputSchema: envelope(DriveWaitForOutputSchema),\n corePath: '/drive/wait_for',\n },\n },\n {\n name: 'drive.tab_list',\n config: {\n title: 'Drive Tab List',\n description: 'List browser tabs.',\n inputSchema: DriveTabListInputSchema,\n outputSchema: envelope(DriveTabListOutputSchema),\n corePath: '/drive/tab_list',\n },\n },\n {\n name: 'drive.tab_activate',\n config: {\n title: 'Drive Tab Activate',\n description: 'Activate a browser tab.',\n inputSchema: DriveTabActivateInputSchema,\n outputSchema: envelope(DriveTabActivateOutputSchema),\n corePath: '/drive/tab_activate',\n },\n },\n {\n name: 'drive.tab_close',\n config: {\n title: 'Drive Tab Close',\n description: 'Close a browser tab.',\n inputSchema: DriveTabCloseInputSchema,\n outputSchema: envelope(DriveTabCloseOutputSchema),\n corePath: '/drive/tab_close',\n },\n },\n {\n name: 'inspect.dom_snapshot',\n config: {\n title: 'Inspect DOM Snapshot',\n description: 'Capture a DOM snapshot.',\n inputSchema: InspectDomSnapshotInputSchema,\n outputSchema: envelope(InspectDomSnapshotOutputSchema),\n corePath: '/inspect/dom_snapshot',\n },\n },\n {\n name: 'inspect.dom_diff',\n config: {\n title: 'Inspect DOM Diff',\n description: 'Compare recent DOM snapshots.',\n inputSchema: InspectDomDiffInputSchema,\n outputSchema: envelope(InspectDomDiffOutputSchema),\n corePath: '/inspect/dom_diff',\n },\n },\n {\n name: 'inspect.find',\n config: {\n title: 'Inspect Find',\n description: 'Find elements in the accessibility tree and return refs.',\n inputSchema: InspectFindInputSchema,\n outputSchema: envelope(InspectFindOutputSchema),\n corePath: '/inspect/find',\n },\n },\n {\n name: 'inspect.extract_content',\n config: {\n title: 'Inspect Extract Content',\n description: 'Extract main content as markdown or text.',\n inputSchema: InspectExtractContentInputSchema,\n outputSchema: envelope(InspectExtractContentOutputSchema),\n corePath: '/inspect/extract_content',\n },\n },\n {\n name: 'inspect.page_state',\n config: {\n title: 'Inspect Page State',\n description: 'Capture form, storage, and cookie state.',\n inputSchema: InspectPageStateInputSchema,\n outputSchema: envelope(InspectPageStateOutputSchema),\n corePath: '/inspect/page_state',\n },\n },\n {\n name: 'inspect.console_list',\n config: {\n title: 'Inspect Console List',\n description: 'List console entries.',\n inputSchema: InspectConsoleListInputSchema,\n outputSchema: envelope(InspectConsoleListOutputSchema),\n corePath: '/inspect/console_list',\n },\n },\n {\n name: 'inspect.network_har',\n config: {\n title: 'Inspect Network HAR',\n description: 'Capture network HAR data.',\n inputSchema: InspectNetworkHarInputSchema,\n outputSchema: envelope(InspectNetworkHarOutputSchema),\n corePath: '/inspect/network_har',\n },\n },\n {\n name: 'inspect.evaluate',\n config: {\n title: 'Inspect Evaluate',\n description: 'Evaluate an expression in the target.',\n inputSchema: InspectEvaluateInputSchema,\n outputSchema: envelope(InspectEvaluateOutputSchema),\n corePath: '/inspect/evaluate',\n },\n },\n {\n name: 'inspect.performance_metrics',\n config: {\n title: 'Inspect Performance Metrics',\n description: 'Collect performance metrics.',\n inputSchema: InspectPerformanceMetricsInputSchema,\n outputSchema: envelope(InspectPerformanceMetricsOutputSchema),\n corePath: '/inspect/performance_metrics',\n },\n },\n {\n name: 'artifacts.screenshot',\n config: {\n title: 'Artifacts Screenshot',\n description: 'Capture a screenshot artifact.',\n inputSchema: ArtifactsScreenshotInputSchema,\n outputSchema: envelope(ArtifactsScreenshotOutputSchema),\n corePath: '/artifacts/screenshot',\n },\n },\n {\n name: 'health_check',\n config: {\n title: 'Health Check',\n description:\n 'Check server health including uptime, memory usage, active session count, and extension connection status.',\n inputSchema: HealthCheckInputSchema,\n outputSchema: envelope(HealthCheckOutputSchema),\n corePath: '/health_check',\n },\n },\n {\n name: 'diagnostics.doctor',\n config: {\n title: 'Diagnostics Doctor',\n description: 'Run diagnostics checks.',\n inputSchema: DiagnosticsDoctorInputSchema,\n outputSchema: envelope(DiagnosticsDoctorOutputSchema),\n corePath: '/diagnostics/doctor',\n },\n },\n];\n\nexport const createToolHandler = (\n client: CoreClient,\n corePath: string\n): ToolCallback<AnySchema> => {\n return (async (args: unknown, _extra: unknown): Promise<ToolResult> => {\n void _extra;\n try {\n const envelopeResult = await client.post(corePath, args);\n return toToolResult(envelopeResult);\n } catch (error) {\n const parsed = ErrorEnvelopeSchema.safeParse(error);\n if (parsed.success) {\n return toToolResult(parsed.data);\n }\n return toToolResult(toInternalErrorEnvelope(error));\n }\n }) as ToolCallback<AnySchema>;\n};\n\nexport const registerBrowserBridgeTools = (\n server: ToolRegistrar,\n client: CoreClient\n): void => {\n for (const tool of TOOL_DEFINITIONS) {\n server.registerTool(\n tool.name,\n {\n title: tool.config.title,\n description: tool.config.description,\n inputSchema: tool.config.inputSchema,\n outputSchema: tool.config.outputSchema,\n },\n createToolHandler(client, tool.config.corePath)\n );\n }\n};\n", "import { createServer } from 'node:http';\nimport type { IncomingMessage } from 'node:http';\nimport { randomUUID } from 'node:crypto';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';\nimport { CoreClient, CoreClientOptions, createCoreClient } from './core-client';\nimport { registerBrowserBridgeTools } from './tools';\n\nexport type McpAdapterOptions = CoreClientOptions & {\n name?: string;\n version?: string;\n coreClient?: CoreClient;\n};\n\nexport type McpAdapterHandle = {\n server: McpServer;\n client: CoreClient;\n};\n\nexport type McpAdapterStartHandle = McpAdapterHandle & {\n transport: StdioServerTransport;\n};\n\nexport type McpAdapterHttpOptions = {\n host?: string;\n port?: number;\n path?: string;\n};\n\nexport type McpAdapterHttpStartHandle = {\n client: CoreClient;\n host: string;\n port: number;\n path: string;\n close: () => Promise<void>;\n};\n\nconst DEFAULT_SERVER_NAME = 'browser-bridge';\nconst DEFAULT_SERVER_VERSION = '0.0.0';\nconst DEFAULT_HTTP_HOST = '127.0.0.1';\nconst DEFAULT_HTTP_PATH = '/mcp';\n\nexport const createMcpServer = (\n options: McpAdapterOptions = {}\n): McpAdapterHandle => {\n const server = new McpServer({\n name: options.name ?? DEFAULT_SERVER_NAME,\n version: options.version ?? DEFAULT_SERVER_VERSION,\n });\n const client = options.coreClient ?? createCoreClient(options);\n\n registerBrowserBridgeTools(server, client);\n\n return { server, client };\n};\n\nexport const startMcpServer = async (\n options: McpAdapterOptions = {}\n): Promise<McpAdapterStartHandle> => {\n const handle = createMcpServer(options);\n const transport = new StdioServerTransport();\n await handle.server.connect(transport);\n return { ...handle, transport };\n};\n\nconst readJsonBody = async (\n req: IncomingMessage,\n maxBytes = 5 * 1024 * 1024\n): Promise<unknown> => {\n const chunks: Buffer[] = [];\n let total = 0;\n await new Promise<void>((resolve, reject) => {\n req.on('data', (chunk: Buffer) => {\n total += chunk.length;\n if (total > maxBytes) {\n reject(new Error('Request body too large.'));\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => resolve());\n req.on('error', (err: unknown) => reject(err));\n });\n const raw = Buffer.concat(chunks).toString('utf8');\n if (!raw) {\n return undefined;\n }\n return JSON.parse(raw) as unknown;\n};\n\nconst getHeaderValue = (\n value: string | string[] | undefined\n): string | undefined => {\n if (typeof value === 'string') {\n return value;\n }\n if (Array.isArray(value)) {\n return value[0];\n }\n return undefined;\n};\n\nexport const startMcpHttpServer = async (\n options: McpAdapterOptions & McpAdapterHttpOptions = {}\n): Promise<McpAdapterHttpStartHandle> => {\n const host = options.host ?? DEFAULT_HTTP_HOST;\n const port = typeof options.port === 'number' ? options.port : 0;\n const path = options.path ?? DEFAULT_HTTP_PATH;\n\n const client = options.coreClient ?? createCoreClient(options);\n\n const sessions = new Map<\n string,\n {\n transport: StreamableHTTPServerTransport;\n server: McpServer;\n }\n >();\n\n const closeAllSessions = async (): Promise<void> => {\n const entries = Array.from(sessions.values());\n sessions.clear();\n await Promise.all(\n entries.map(async (entry) => {\n try {\n await entry.transport.close();\n } catch {\n // Ignore.\n }\n try {\n await entry.server.close();\n } catch {\n // Ignore.\n }\n })\n );\n };\n\n const httpServer = createServer(async (req, res) => {\n try {\n const url = new URL(req.url ?? '', `http://${host}`);\n if (url.pathname !== path) {\n res.writeHead(404, { 'content-type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not Found' }));\n return;\n }\n\n const sessionId = getHeaderValue(req.headers['mcp-session-id']);\n\n const parsedBody =\n req.method === 'POST' ? await readJsonBody(req) : undefined;\n\n if (sessionId) {\n const entry = sessions.get(sessionId);\n if (!entry) {\n res.writeHead(404, { 'content-type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unknown session.' }));\n return;\n }\n await entry.transport.handleRequest(req, res, parsedBody);\n return;\n }\n\n if (req.method !== 'POST' || !isInitializeRequest(parsedBody)) {\n res.writeHead(400, { 'content-type': 'application/json' });\n res.end(\n JSON.stringify({\n error:\n 'Missing mcp-session-id header. First request must be initialize.',\n })\n );\n return;\n }\n\n let sessionEntry:\n | {\n transport: StreamableHTTPServerTransport;\n server: McpServer;\n }\n | undefined;\n\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (sid) => {\n if (sessionEntry) {\n sessions.set(sid, sessionEntry);\n }\n },\n onsessionclosed: async (sid) => {\n const entry = sessions.get(sid);\n sessions.delete(sid);\n if (!entry) {\n return;\n }\n await Promise.allSettled([\n entry.transport.close(),\n entry.server.close(),\n ]);\n },\n });\n\n const sessionServer = new McpServer({\n name: options.name ?? DEFAULT_SERVER_NAME,\n version: options.version ?? DEFAULT_SERVER_VERSION,\n });\n registerBrowserBridgeTools(sessionServer, client);\n await sessionServer.connect(transport);\n sessionEntry = { transport, server: sessionServer };\n\n await transport.handleRequest(req, res, parsedBody);\n } catch (error) {\n res.writeHead(500, { 'content-type': 'application/json' });\n res.end(\n JSON.stringify({\n error: error instanceof Error ? error.message : 'Internal error.',\n })\n );\n }\n });\n\n const resolvedPort = await new Promise<number>((resolve, reject) => {\n httpServer.listen(port, host, () => {\n const address = httpServer.address();\n resolve(typeof address === 'object' && address ? address.port : port);\n });\n httpServer.on('error', reject);\n });\n\n return {\n client,\n host,\n port: resolvedPort,\n path,\n close: async () => {\n await new Promise<void>((resolve, reject) => {\n httpServer.close((err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n await closeAllSessions();\n },\n };\n};\n", "type CheckboxChoice<T> = {\n value: T;\n label: string;\n checked?: boolean;\n disabled?: boolean | string;\n};\n\nexport const requireTty = (): void => {\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n throw new Error('Interactive install requires a TTY.');\n }\n};\n\nexport const checkboxPrompt = async <T>(options: {\n message: string;\n choices: CheckboxChoice<T>[];\n}): Promise<T[]> => {\n // @inquirer/prompts is ESM; load lazily from our CommonJS bundle.\n const mod = (await import('@inquirer/prompts')) as unknown as {\n checkbox: (args: {\n message: string;\n loop?: boolean;\n choices: Array<{\n value: unknown;\n name: string;\n checked?: boolean;\n disabled?: boolean | string;\n }>;\n }) => Promise<unknown[]>;\n };\n\n const { checkbox } = mod;\n const values = await checkbox({\n message: options.message,\n // Avoid wrapping from bottom -> top (and top -> bottom) when navigating long lists.\n loop: false,\n choices: options.choices.map((c) => ({\n value: c.value as unknown,\n name: c.label,\n checked: c.checked,\n disabled: c.disabled,\n })),\n });\n return values as T[];\n};\n", "import { spawn } from 'node:child_process';\nimport { installCursorMcp } from './cursor-mcp';\n\nexport type McpHarnessId = 'codex' | 'claude' | 'cursor';\n\nexport type McpInstallResult =\n | { ok: true; details?: { cursorSettingsPath?: string } }\n | { ok: false; error: { code: string; message: string } };\n\nconst runQuiet = async (cmd: string, args: string[]): Promise<void> => {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(cmd, args, { stdio: ['ignore', 'pipe', 'pipe'] });\n let stderr = '';\n child.stderr?.on('data', (chunk) => {\n stderr += String(chunk);\n });\n child.on('error', reject);\n child.on('exit', (code) => {\n if (code === 0) resolve();\n else {\n const suffix = stderr.trim() ? `: ${stderr.trim()}` : '';\n reject(new Error(`${cmd} exited with ${code ?? 'unknown'}${suffix}`));\n }\n });\n });\n};\n\nconst tryRun = async (cmd: string, args: string[]): Promise<void> => {\n try {\n await runQuiet(cmd, args);\n } catch {\n // best-effort (used for remove)\n }\n};\n\nexport const installMcp = async (\n harness: McpHarnessId\n): Promise<McpInstallResult> => {\n try {\n if (harness === 'codex') {\n await tryRun('codex', ['mcp', 'remove', 'browser-bridge']);\n await runQuiet('codex', [\n 'mcp',\n 'add',\n 'browser-bridge',\n '--',\n 'browser-bridge',\n 'mcp',\n ]);\n return { ok: true };\n }\n\n if (harness === 'claude') {\n // Remove any existing config, then install user-scoped so it \"just works\" across projects.\n await tryRun('claude', [\n 'mcp',\n 'remove',\n '--scope',\n 'local',\n 'browser-bridge',\n ]);\n await tryRun('claude', [\n 'mcp',\n 'remove',\n '--scope',\n 'project',\n 'browser-bridge',\n ]);\n await tryRun('claude', [\n 'mcp',\n 'remove',\n '--scope',\n 'user',\n 'browser-bridge',\n ]);\n\n await runQuiet('claude', [\n 'mcp',\n 'add',\n '--scope',\n 'user',\n '--transport',\n 'stdio',\n 'browser-bridge',\n '--',\n 'browser-bridge',\n 'mcp',\n ]);\n return { ok: true };\n }\n\n // Cursor supports `--add-mcp`, but in practice its argv parsing breaks when\n // passing JSON that includes commas (it gets split and stops being valid\n // JSON). Install by directly updating Cursor's user settings instead.\n const cursor = await installCursorMcp();\n return { ok: true, details: { cursorSettingsPath: cursor.settingsPath } };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error.';\n return {\n ok: false,\n error: { code: 'MCP_INSTALL_FAILED', message },\n };\n }\n};\n", "import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\ntype JsonObject = Record<string, unknown>;\n\nconst isObject = (value: unknown): value is JsonObject =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\ntype Platform = string;\n\nexport const resolveCursorUserSettingsPath = (options?: {\n platform?: Platform;\n homeDir?: string;\n env?: Record<string, string | undefined>;\n}): string => {\n const platform = options?.platform ?? process.platform;\n const homeDir = options?.homeDir ?? os.homedir();\n const env = options?.env ?? process.env;\n\n if (platform === 'darwin') {\n return path.join(\n homeDir,\n 'Library',\n 'Application Support',\n 'Cursor',\n 'User',\n 'settings.json'\n );\n }\n\n if (platform === 'win32') {\n const appData = env.APPDATA;\n if (!appData) {\n throw new Error(\n 'APPDATA is not set; cannot resolve Cursor settings path.'\n );\n }\n return path.join(appData, 'Cursor', 'User', 'settings.json');\n }\n\n // Linux and other unix-like platforms: follow VS Code convention.\n return path.join(homeDir, '.config', 'Cursor', 'User', 'settings.json');\n};\n\nexport const installCursorMcp = async (\n settingsPath?: string\n): Promise<{ settingsPath: string }> => {\n const filePath = settingsPath ?? resolveCursorUserSettingsPath();\n const dir = path.dirname(filePath);\n await fs.mkdir(dir, { recursive: true });\n\n let settings: JsonObject = {};\n try {\n const raw = await fs.readFile(filePath, 'utf8');\n const parsed = JSON.parse(raw) as unknown;\n if (isObject(parsed)) {\n settings = parsed;\n } else {\n throw new Error('Cursor settings.json is not a JSON object.');\n }\n } catch (error) {\n // If it doesn't exist, initialize a new settings object.\n if (\n error &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as { code?: unknown }).code === 'ENOENT'\n ) {\n settings = {};\n } else {\n throw error;\n }\n }\n\n const mcp = isObject(settings.mcp) ? settings.mcp : {};\n const servers = isObject(mcp.servers) ? mcp.servers : {};\n servers['browser-bridge'] = {\n command: 'browser-bridge',\n args: ['mcp'],\n };\n mcp.servers = servers;\n settings.mcp = mcp;\n\n await fs.writeFile(\n filePath,\n JSON.stringify(settings, null, 2) + '\\n',\n 'utf8'\n );\n\n return { settingsPath: filePath };\n};\n", "import { Command } from 'commander';\nimport {\n startMcpHttpServer,\n startMcpServer,\n} from '@btraut/browser-bridge-mcp-adapter';\nimport { createCoreClient } from '../core-client';\nimport { getGlobalOptions, runLocal } from '../cli-runtime';\nimport { checkboxPrompt, requireTty } from '../tui';\nimport { installMcp } from '../installer/mcp-install';\n\ntype McpCommandOptions = {\n name?: string;\n version?: string;\n};\n\nexport const registerMcpCommand = (program: Command): void => {\n const startServer = async (\n options: McpCommandOptions,\n command: Command\n ): Promise<void> => {\n const globals = getGlobalOptions(command);\n const coreClient = createCoreClient({\n host: globals.host,\n port: globals.port,\n ensureDaemon: globals.daemon !== false,\n });\n\n try {\n await startMcpServer({\n name: options.name,\n version: options.version,\n coreClient,\n });\n } catch (error) {\n console.error(error);\n process.exitCode = 1;\n }\n };\n\n const mcp = program.command('mcp').description('MCP server and helpers');\n\n mcp\n .command('install')\n .description('Install Browser Bridge as an MCP server in supported clients')\n .action(async (_options, command: Command) => {\n await runLocal(command, async ({ json }) => {\n if (json) {\n throw new Error('mcp install is interactive; omit --json.');\n }\n\n requireTty();\n\n const selected = await checkboxPrompt<'codex' | 'claude' | 'cursor'>({\n message: 'Install MCP into clients:',\n choices: [\n { value: 'codex', label: 'Codex', checked: true },\n { value: 'claude', label: 'Claude', checked: true },\n { value: 'cursor', label: 'Cursor', checked: true },\n ],\n });\n\n const results: Record<string, unknown> = {};\n let hadError = false;\n for (const harness of selected) {\n const result = await installMcp(harness);\n results[harness] = result;\n if (result.ok === false) {\n hadError = true;\n }\n }\n\n if (hadError) {\n process.exitCode = 1;\n }\n\n return { ok: true, result: { installed: results } };\n });\n });\n\n // Keep `browser-bridge mcp` working (backwards compatible), but also expose\n // `browser-bridge mcp serve` for clarity.\n mcp\n .option('--name <name>', 'MCP server name')\n .option('--version <version>', 'MCP server version')\n .action(startServer);\n\n mcp\n .command('serve')\n .description('Run the MCP server over stdio')\n .option('--name <name>', 'MCP server name')\n .option('--version <version>', 'MCP server version')\n .action(startServer);\n\n mcp\n .command('serve-http')\n .description('Run the MCP server over Streamable HTTP')\n .option('--name <name>', 'MCP server name')\n .option('--version <version>', 'MCP server version')\n .option('--host <host>', 'HTTP host (default 127.0.0.1)')\n .option('--port <port>', 'HTTP port (default random available port)')\n .option('--path <path>', 'HTTP path (default /mcp)')\n .action(async (options, command: Command) => {\n const globals = getGlobalOptions(command);\n const coreClient = createCoreClient({\n host: globals.host,\n port: globals.port,\n ensureDaemon: globals.daemon !== false,\n });\n\n const parsedPort =\n typeof options.port === 'string' && options.port.length > 0\n ? Number(options.port)\n : undefined;\n\n try {\n const handle = await startMcpHttpServer({\n name: options.name,\n version: options.version,\n host: options.host,\n port:\n typeof parsedPort === 'number' && Number.isFinite(parsedPort)\n ? parsedPort\n : undefined,\n path: options.path,\n coreClient,\n });\n\n console.error(\n `MCP HTTP server listening on http://${handle.host}:${handle.port}${handle.path}`\n );\n } catch (error) {\n console.error(error);\n process.exitCode = 1;\n }\n });\n};\n", "import { createServer } from 'http';\nimport express, { Express } from 'express';\nimport { createSessionRouter } from './routes/session';\nimport { registerArtifactsRoutes } from './routes/artifacts';\nimport { registerDiagnosticsRoutes } from './routes/diagnostics';\nimport { registerDriveRoutes, registerInspectRoutes } from './routes';\nimport { SessionRegistry } from './session';\nimport { ExtensionBridge } from './extension-bridge';\nimport { DriveController } from './drive';\nimport { InspectService, createInspectService } from './inspect';\nimport { RecoveryTracker } from './recovery';\nimport { DebuggerBridge } from './debugger-bridge';\n\nexport type CoreServer = {\n app: Express;\n registry: SessionRegistry;\n extensionBridge: ExtensionBridge;\n debuggerBridge: DebuggerBridge;\n drive: DriveController;\n inspect: InspectService;\n recoveryTracker: RecoveryTracker;\n};\n\nexport type CoreServerOptions = {\n registry?: SessionRegistry;\n};\n\nexport const createCoreServer = (\n options: CoreServerOptions = {}\n): CoreServer => {\n const app = express();\n const registry = options.registry ?? new SessionRegistry();\n const extensionBridge = new ExtensionBridge({ registry });\n const debuggerBridge = new DebuggerBridge({ extensionBridge });\n const drive = new DriveController(extensionBridge, registry);\n const inspect = createInspectService({\n registry,\n debuggerBridge,\n extensionBridge,\n });\n const recoveryTracker = new RecoveryTracker();\n\n app.use(express.json({ limit: '1mb' }));\n\n app.get('/health', (_req, res) => {\n res.status(200).json({ ok: true });\n });\n\n app.use(\n '/session',\n createSessionRouter(registry, {\n driveConnected: () => extensionBridge.isConnected(),\n inspectRecover: (sessionId) => inspect.reconnect(sessionId),\n recordRecovery: (attempt) => recoveryTracker.record(attempt),\n })\n );\n\n registerDriveRoutes(app, { drive });\n registerInspectRoutes(app, {\n registry,\n extensionBridge,\n inspectService: inspect,\n });\n registerArtifactsRoutes(app, {\n registry,\n extensionBridge,\n inspectService: inspect,\n });\n registerDiagnosticsRoutes(app, {\n registry,\n extensionBridge,\n debuggerBridge,\n drive,\n inspectService: inspect,\n recoveryTracker,\n });\n\n return {\n app,\n registry,\n extensionBridge,\n debuggerBridge,\n drive,\n inspect,\n recoveryTracker,\n };\n};\n\nexport type CoreServerStartOptions = {\n host?: string;\n port?: number;\n registry?: SessionRegistry;\n};\n\nexport type CoreServerHandle = {\n app: Express;\n registry: SessionRegistry;\n server: ReturnType<typeof createServer>;\n host: string;\n port: number;\n};\n\nconst resolveCorePort = (portOverride?: number): number => {\n if (portOverride !== undefined) {\n return portOverride;\n }\n const env =\n process.env.BROWSER_BRIDGE_CORE_PORT ||\n process.env.BROWSER_VISION_CORE_PORT;\n if (env) {\n const parsed = Number(env);\n if (Number.isFinite(parsed) && parsed > 0) {\n return parsed;\n }\n }\n return 3210;\n};\n\nconst resolveSessionTtlMs = (): number => {\n const env =\n process.env.BROWSER_BRIDGE_SESSION_TTL_MS ||\n process.env.BROWSER_VISION_SESSION_TTL_MS;\n if (env) {\n const parsed = Number(env);\n if (Number.isFinite(parsed) && parsed >= 0) {\n return parsed;\n }\n }\n return 60 * 60 * 1000;\n};\n\nconst resolveSessionCleanupIntervalMs = (ttlMs: number): number => {\n const env =\n process.env.BROWSER_BRIDGE_SESSION_CLEANUP_INTERVAL_MS ||\n process.env.BROWSER_VISION_SESSION_CLEANUP_INTERVAL_MS;\n if (env) {\n const parsed = Number(env);\n if (Number.isFinite(parsed) && parsed > 0) {\n return parsed;\n }\n }\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n return 60 * 1000;\n }\n return Math.min(60 * 1000, Math.max(1000, Math.floor(ttlMs / 2)));\n};\n\nexport const startCoreServer = (\n options: CoreServerStartOptions = {}\n): Promise<CoreServerHandle> => {\n const host = options.host ?? '127.0.0.1';\n const port = resolveCorePort(options.port);\n const { app, registry, extensionBridge } = createCoreServer({\n registry: options.registry,\n });\n\n return new Promise((resolve, reject) => {\n const server = createServer(app);\n extensionBridge.attach(server);\n server.listen(port, host, () => {\n const address = server.address();\n const resolvedPort =\n typeof address === 'object' && address !== null ? address.port : port;\n\n const ttlMs = resolveSessionTtlMs();\n if (ttlMs > 0) {\n const intervalMs = resolveSessionCleanupIntervalMs(ttlMs);\n const timer = setInterval(() => {\n try {\n registry.cleanupIdleSessions(ttlMs);\n } catch (error) {\n console.warn('Session cleanup failed:', error);\n }\n }, intervalMs);\n timer.unref();\n server.on('close', () => clearInterval(timer));\n }\n\n resolve({ app, registry, server, host, port: resolvedPort });\n });\n\n server.on('error', (error) => {\n reject(error);\n });\n });\n};\n", "import { Router } from 'express';\nimport { InvalidSessionTransition, SessionState } from '../state';\nimport { SessionError, SessionRegistry } from '../session';\nimport { isRecord, sendError, sendResult } from './shared';\n\nconst readSessionId = (body: unknown): string | undefined => {\n if (!isRecord(body)) {\n return undefined;\n }\n\n const sessionId = body.session_id;\n if (typeof sessionId !== 'string' || sessionId.length === 0) {\n return undefined;\n }\n\n return sessionId;\n};\n\ntype SessionRouterOptions = {\n driveConnected?: () => boolean;\n inspectRecover?: (sessionId: string) => Promise<boolean>;\n recordRecovery?: (attempt: {\n sessionId: string;\n recovered: boolean;\n state: SessionState;\n message?: string;\n at: string;\n }) => void;\n};\n\nexport const createSessionRouter = (\n registry: SessionRegistry,\n options: SessionRouterOptions = {}\n): Router => {\n const router = Router();\n\n router.post('/create', (req, res) => {\n const body = req.body;\n if (body !== undefined) {\n if (!isRecord(body)) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'Request body must be an object.',\n retryable: false,\n });\n }\n if (Object.keys(body).length > 0) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session.create does not accept any input fields.',\n retryable: false,\n });\n }\n }\n\n const session = registry.create();\n if (options.driveConnected?.()) {\n try {\n registry.apply(session.id, 'DRIVE_CONNECTED');\n } catch {\n // Ignore invalid transitions.\n }\n }\n return sendResult(res, {\n session_id: session.id,\n state: session.state,\n created_at: session.createdAt.toISOString(),\n });\n });\n\n router.post('/status', (req, res) => {\n const sessionId = readSessionId(req.body);\n if (!sessionId) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session_id is required',\n retryable: false,\n });\n }\n\n try {\n const session = registry.require(sessionId);\n return sendResult(res, {\n session_id: session.id,\n state: session.state,\n updated_at: session.updatedAt.toISOString(),\n });\n } catch (error) {\n if (error instanceof SessionError) {\n return sendError(res, 404, {\n code: error.code,\n message: error.message,\n retryable: false,\n });\n }\n\n return sendError(res, 500, {\n code: 'INTERNAL',\n message: 'Unexpected error while fetching status.',\n retryable: false,\n });\n }\n });\n\n router.post('/recover', async (req, res) => {\n const sessionId = readSessionId(req.body);\n if (!sessionId) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session_id is required',\n retryable: false,\n });\n }\n\n try {\n const session = registry.require(sessionId);\n let outcome:\n | {\n recovered: boolean;\n message?: string;\n }\n | undefined;\n\n if (session.state === SessionState.DEGRADED_DRIVE) {\n const connected = options.driveConnected?.() ?? false;\n outcome = {\n recovered: connected,\n message: connected\n ? 'Drive recovery succeeded.'\n : 'Drive recovery failed.',\n };\n } else if (session.state === SessionState.DEGRADED_INSPECT) {\n const recovered = options.inspectRecover\n ? await options.inspectRecover(sessionId)\n : false;\n outcome = {\n recovered,\n message: recovered\n ? 'Inspect recovery succeeded.'\n : 'Inspect recovery failed.',\n };\n }\n\n const result = registry.recover(sessionId, outcome);\n if (outcome) {\n const attempt = {\n sessionId,\n recovered: result.recovered,\n state: result.state,\n message: result.message,\n at: new Date().toISOString(),\n };\n options.recordRecovery?.(attempt);\n const status = result.recovered ? 'succeeded' : 'failed';\n console.info(\n `[recovery] session ${sessionId} ${status}: ${result.message ?? ''}`\n );\n }\n return sendResult(res, {\n session_id: result.sessionId,\n recovered: result.recovered,\n state: result.state,\n message: result.message,\n });\n } catch (error) {\n if (error instanceof SessionError) {\n const status = error.code === 'SESSION_CLOSED' ? 409 : 404;\n return sendError(res, status, {\n code: error.code,\n message: error.message,\n retryable: false,\n });\n }\n\n if (error instanceof InvalidSessionTransition) {\n return sendError(res, 409, {\n code: 'FAILED_PRECONDITION',\n message: error.message,\n retryable: false,\n });\n }\n\n return sendError(res, 500, {\n code: 'INTERNAL',\n message: 'Unexpected error while recovering session.',\n retryable: false,\n });\n }\n });\n\n router.post('/close', (req, res) => {\n const sessionId = readSessionId(req.body);\n if (!sessionId) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session_id is required',\n retryable: false,\n });\n }\n\n try {\n registry.close(sessionId);\n return sendResult(res, { ok: true });\n } catch (error) {\n if (error instanceof SessionError) {\n return sendError(res, 404, {\n code: error.code,\n message: error.message,\n retryable: false,\n });\n }\n\n if (error instanceof InvalidSessionTransition) {\n return sendError(res, 409, {\n code: 'FAILED_PRECONDITION',\n message: error.message,\n retryable: false,\n });\n }\n\n return sendError(res, 500, {\n code: 'INTERNAL',\n message: 'Unexpected error while closing session.',\n retryable: false,\n });\n }\n });\n\n return router;\n};\n", "import { randomUUID } from 'crypto';\nimport { writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { Readability } from '@mozilla/readability';\nimport { JSDOM } from 'jsdom';\nimport TurndownService from 'turndown';\nimport { ensureArtifactRootDir } from '../artifacts';\nimport { driveMutex } from '../drive';\nimport type { DebuggerBridge } from '../debugger-bridge';\nimport type {\n DriveAction,\n DriveErrorInfo,\n DriveResponse,\n DriveScreenshotResult,\n DriveTabInfo,\n} from '../drive-protocol';\nimport {\n applyAxSnapshotFilters,\n getAxName,\n getAxNodes,\n getAxRole,\n LABEL_AX_ROLES,\n matchesAxText,\n matchesTextValue,\n normalizeQuery,\n truncateAxSnapshot,\n} from './ax-snapshot';\nimport { toConsoleEntry } from './console';\nimport { buildHar } from './har';\nimport { captureHtml } from './html-snapshot';\nimport { SnapshotHistory } from './snapshot-history';\nimport {\n applySnapshotRefs,\n assignRefsToAxSnapshot,\n resolveNodeIdForSelector,\n} from './snapshot-refs';\nimport { InspectError } from './errors';\nimport type {\n ArtifactInfo,\n ConsoleEntry,\n ConsoleListResult,\n DomSnapshotResult,\n EvaluateResult,\n ExtractContentResult,\n FormInfo,\n InspectErrorCode,\n InspectServiceOptions,\n PageStateResult,\n PerformanceMetricsResult,\n StorageEntry,\n} from './types';\nimport { PAGE_STATE_SCRIPT } from '../page-state-script';\nimport { SessionError, SessionRegistry, SessionRecord } from '../session';\nimport { SessionState } from '../state';\nimport { pickBestTarget } from '../target-matching';\nimport type { TargetHint } from '../target-matching';\n\nconst DEFAULT_MAX_SNAPSHOTS_PER_SESSION = 20;\nconst DEFAULT_MAX_SNAPSHOT_HISTORY = 100;\n\nexport class InspectService {\n private readonly registry: SessionRegistry;\n private readonly debugger?: DebuggerBridge;\n private readonly extensionBridge?: {\n isConnected: () => boolean;\n getStatus: () => { tabs: DriveTabInfo[] };\n request?: <T = unknown>(\n action: DriveAction,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ) => Promise<DriveResponse<T>>;\n };\n private lastError?: InspectError;\n private lastErrorAt?: string;\n private readonly snapshots: SnapshotHistory;\n\n constructor(options: InspectServiceOptions) {\n this.registry = options.registry;\n this.debugger = options.debuggerBridge;\n this.extensionBridge = options.extensionBridge;\n const maxSnapshotsPerSession =\n options.maxSnapshotsPerSession ?? DEFAULT_MAX_SNAPSHOTS_PER_SESSION;\n const maxSnapshotHistory =\n options.maxSnapshotHistory ?? DEFAULT_MAX_SNAPSHOT_HISTORY;\n this.snapshots = new SnapshotHistory({\n maxSnapshotsPerSession,\n maxSnapshotHistory,\n });\n }\n\n isConnected(): boolean {\n return this.debugger?.hasAttachments() ?? false;\n }\n\n getLastError(): { error: InspectError; at: string } | undefined {\n if (!this.lastError || !this.lastErrorAt) {\n const debuggerError = this.debugger?.getLastError();\n if (!debuggerError) {\n return undefined;\n }\n return {\n error: new InspectError(\n 'INSPECT_UNAVAILABLE',\n debuggerError.error.message,\n {\n retryable: debuggerError.error.retryable,\n details: {\n code: debuggerError.error.code,\n ...(debuggerError.error.details\n ? debuggerError.error.details\n : {}),\n },\n }\n ),\n at: debuggerError.at,\n };\n }\n return { error: this.lastError, at: this.lastErrorAt };\n }\n\n async reconnect(sessionId: string): Promise<boolean> {\n try {\n this.requireSession(sessionId);\n const selection = await this.resolveTab();\n const debuggerBridge = this.ensureDebugger();\n const result = await debuggerBridge.attach(selection.tabId);\n if (result.ok) {\n this.markInspectConnected(sessionId);\n return true;\n }\n const error = this.mapDebuggerError(result.error);\n this.recordError(error);\n return false;\n } catch (error) {\n if (error instanceof InspectError) {\n this.recordError(error);\n }\n return false;\n }\n }\n\n async domSnapshot(input: {\n sessionId: string;\n format: 'ax' | 'html';\n consistency: 'best_effort' | 'quiesce';\n interactive?: boolean;\n compact?: boolean;\n maxNodes?: number;\n selector?: string;\n targetHint?: TargetHint;\n }): Promise<DomSnapshotResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n const debuggerCommand = this.debuggerCommand.bind(this);\n\n const work = async (): Promise<DomSnapshotResult> => {\n if (input.format === 'html') {\n const html = await captureHtml(selection.tabId, {\n selector: input.selector,\n debuggerCommand,\n onEvaluationFailed: () => {\n const error = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to evaluate HTML snapshot.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n },\n });\n const warnings = [...(selection.warnings ?? [])];\n if (input.interactive) {\n warnings.push(\n 'Interactive filter is only supported for AX snapshots.'\n );\n }\n if (input.compact) {\n warnings.push('Compact filter is only supported for AX snapshots.');\n }\n if (input.maxNodes !== undefined) {\n warnings.push('max_nodes is only supported for AX snapshots.');\n }\n if (input.selector && html === '') {\n warnings.push(`Selector not found: ${input.selector}`);\n }\n return {\n format: 'html',\n snapshot: html,\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n\n try {\n await this.enableAccessibility(selection.tabId);\n const selectorWarnings: string[] = [];\n let result: unknown;\n if (input.selector) {\n const resolved = await resolveNodeIdForSelector(\n selection.tabId,\n input.selector,\n debuggerCommand\n );\n selectorWarnings.push(...(resolved.warnings ?? []));\n if (!resolved.nodeId) {\n let refWarnings: string[] = [];\n try {\n refWarnings = await applySnapshotRefs(\n selection.tabId,\n new Map(),\n debuggerCommand\n );\n } catch {\n refWarnings = ['Failed to clear prior snapshot refs.'];\n }\n const warnings = [\n ...(selection.warnings ?? []),\n ...selectorWarnings,\n ...refWarnings,\n ];\n return {\n format: 'ax',\n snapshot: { nodes: [] },\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n result = await this.debuggerCommand(\n selection.tabId,\n 'Accessibility.getPartialAXTree',\n { nodeId: resolved.nodeId }\n );\n } else {\n result = await this.debuggerCommand(\n selection.tabId,\n 'Accessibility.getFullAXTree',\n {}\n );\n }\n let snapshot =\n input.interactive || input.compact\n ? applyAxSnapshotFilters(result, {\n interactiveOnly: input.interactive,\n compact: input.compact,\n })\n : result;\n let truncated = false;\n const truncationWarnings: string[] = [];\n if (input.maxNodes !== undefined) {\n const truncatedResult = truncateAxSnapshot(snapshot, input.maxNodes);\n snapshot = truncatedResult.snapshot;\n truncated = truncatedResult.truncated;\n if (truncated) {\n truncationWarnings.push(\n `AX snapshot truncated to ${input.maxNodes} nodes.`\n );\n }\n }\n const refMap = assignRefsToAxSnapshot(snapshot);\n const refWarnings = await applySnapshotRefs(\n selection.tabId,\n refMap,\n debuggerCommand\n );\n const warnings = [\n ...(selection.warnings ?? []),\n ...selectorWarnings,\n ...truncationWarnings,\n ...(refWarnings ?? []),\n ];\n return {\n format: 'ax',\n snapshot,\n ...(truncated ? { truncated: true } : {}),\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n } catch (error) {\n if (error instanceof InspectError) {\n const fallbackCodes: InspectErrorCode[] = [\n 'NOT_SUPPORTED',\n 'INSPECT_UNAVAILABLE',\n 'EVALUATION_FAILED',\n ];\n if (!fallbackCodes.includes(error.code)) {\n throw error;\n }\n const html = await captureHtml(selection.tabId, {\n selector: input.selector,\n debuggerCommand,\n onEvaluationFailed: () => {\n const error = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to evaluate HTML snapshot.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n },\n });\n const warnings = [\n ...(selection.warnings ?? []),\n 'AX snapshot failed; returned HTML instead.',\n ...(input.maxNodes !== undefined\n ? ['max_nodes is only supported for AX snapshots.']\n : []),\n ...(input.interactive\n ? ['Interactive filter is only supported for AX snapshots.']\n : []),\n ...(input.compact\n ? ['Compact filter is only supported for AX snapshots.']\n : []),\n ...(input.selector && html === ''\n ? [`Selector not found: ${input.selector}`]\n : []),\n ];\n return {\n format: 'html',\n snapshot: html,\n warnings,\n };\n }\n throw error;\n }\n };\n\n if (input.consistency === 'quiesce') {\n const result = await driveMutex.runExclusive(work);\n this.snapshots.record(input.sessionId, result);\n this.markInspectConnected(input.sessionId);\n return result;\n }\n const result = await work();\n this.snapshots.record(input.sessionId, result);\n this.markInspectConnected(input.sessionId);\n return result;\n }\n\n domDiff(input: { sessionId: string }): {\n added: string[];\n removed: string[];\n changed: string[];\n summary: string;\n } {\n this.requireSession(input.sessionId);\n this.markInspectConnected(input.sessionId);\n return this.snapshots.diff(input.sessionId);\n }\n\n async find(input: {\n sessionId: string;\n kind: 'role' | 'text' | 'label';\n role?: string;\n name?: string;\n text?: string;\n label?: string;\n targetHint?: TargetHint;\n }): Promise<{\n matches: Array<{ ref: string; role?: string; name?: string }>;\n warnings?: string[];\n }> {\n const snapshot = await this.domSnapshot({\n sessionId: input.sessionId,\n format: 'ax',\n consistency: 'best_effort',\n targetHint: input.targetHint,\n });\n const warnings = [...(snapshot.warnings ?? [])];\n if (snapshot.format !== 'ax') {\n warnings.push('AX snapshot unavailable; cannot resolve refs.');\n return {\n matches: [],\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n\n const nodes = getAxNodes(snapshot.snapshot);\n const matches: Array<{ ref: string; role?: string; name?: string }> = [];\n\n const nameQuery =\n typeof input.name === 'string' ? normalizeQuery(input.name) : '';\n const textQuery =\n typeof input.text === 'string' ? normalizeQuery(input.text) : '';\n const labelQuery =\n typeof input.label === 'string' ? normalizeQuery(input.label) : '';\n const roleQuery =\n typeof input.role === 'string' ? normalizeQuery(input.role) : '';\n\n for (const node of nodes) {\n if (!node || typeof node !== 'object') {\n continue;\n }\n if (typeof node.ref !== 'string' || node.ref.length === 0) {\n continue;\n }\n const role = getAxRole(node);\n const name = getAxName(node);\n\n if (input.kind === 'role') {\n if (!role || role !== roleQuery) {\n continue;\n }\n if (nameQuery && !matchesTextValue(name, nameQuery)) {\n continue;\n }\n } else if (input.kind === 'text') {\n if (!textQuery || !matchesAxText(node, textQuery)) {\n continue;\n }\n } else if (input.kind === 'label') {\n if (!labelQuery || !LABEL_AX_ROLES.has(role)) {\n continue;\n }\n if (!matchesTextValue(name, labelQuery)) {\n continue;\n }\n }\n\n matches.push({\n ref: node.ref,\n ...(role ? { role } : {}),\n ...(name ? { name } : {}),\n });\n }\n\n return {\n matches,\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n\n async consoleList(input: {\n sessionId: string;\n targetHint?: TargetHint;\n }): Promise<ConsoleListResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n await this.enableConsole(selection.tabId);\n\n const events = this.ensureDebugger().getConsoleEvents(selection.tabId);\n const entries = events\n .map((event) => toConsoleEntry(event))\n .filter((entry): entry is ConsoleEntry => entry !== null);\n\n const result = {\n entries,\n warnings: selection.warnings,\n };\n this.markInspectConnected(input.sessionId);\n return result;\n }\n\n async networkHar(input: {\n sessionId: string;\n targetHint?: TargetHint;\n }): Promise<ArtifactInfo> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n await this.enableNetwork(selection.tabId);\n\n const events = this.ensureDebugger().getNetworkEvents(selection.tabId);\n const har = buildHar(events, selection.tab.title);\n\n try {\n const rootDir = await ensureArtifactRootDir(input.sessionId);\n const artifactId = randomUUID();\n const filePath = path.join(rootDir, `har-${artifactId}.json`);\n await writeFile(filePath, JSON.stringify(har, null, 2), 'utf-8');\n const result = {\n artifact_id: artifactId,\n path: filePath,\n mime: 'application/json',\n };\n this.markInspectConnected(input.sessionId);\n return result;\n } catch {\n const error = new InspectError(\n 'ARTIFACT_IO_ERROR',\n 'Failed to write HAR file.'\n );\n this.recordError(error);\n throw error;\n }\n }\n\n async evaluate(input: {\n sessionId: string;\n expression?: string;\n targetHint?: TargetHint;\n }): Promise<EvaluateResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n const expression = input.expression ?? 'undefined';\n\n await this.debuggerCommand(selection.tabId, 'Runtime.enable', {});\n const result = await this.debuggerCommand(\n selection.tabId,\n 'Runtime.evaluate',\n {\n expression,\n returnByValue: true,\n awaitPromise: true,\n }\n );\n\n if (result && typeof result === 'object' && 'exceptionDetails' in result) {\n const output = {\n exception: (result as { exceptionDetails?: unknown }).exceptionDetails,\n warnings: selection.warnings,\n };\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n const output = {\n value: (result as { result?: { value?: unknown } })?.result?.value,\n warnings: selection.warnings,\n };\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n async extractContent(input: {\n sessionId: string;\n format: 'markdown' | 'text' | 'article_json';\n includeMetadata?: boolean;\n targetHint?: TargetHint;\n }): Promise<ExtractContentResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n\n const debuggerCommand = this.debuggerCommand.bind(this);\n const html = await captureHtml(selection.tabId, {\n debuggerCommand,\n onEvaluationFailed: () => {\n const error = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to evaluate HTML snapshot.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n },\n });\n const url = selection.tab.url ?? 'about:blank';\n let article: ReturnType<Readability['parse']> | null = null;\n try {\n const dom = new JSDOM(html, { url });\n const reader = new Readability(dom.window.document);\n article = reader.parse();\n } catch {\n const err = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to parse page content.',\n { retryable: false }\n );\n this.recordError(err);\n throw err;\n }\n\n if (!article) {\n const err = new InspectError(\n 'NOT_SUPPORTED',\n 'Readability could not extract content.',\n { retryable: false }\n );\n this.recordError(err);\n throw err;\n }\n\n let content = '';\n if (input.format === 'article_json') {\n content = JSON.stringify(article, null, 2);\n } else if (input.format === 'text') {\n content = article.textContent ?? '';\n } else {\n const turndown = new TurndownService();\n content = turndown.turndown(article.content ?? '');\n }\n\n const warnings = selection.warnings ?? [];\n const includeMetadata = input.includeMetadata ?? true;\n const output: ExtractContentResult = {\n content,\n ...(includeMetadata\n ? {\n title: article.title ?? undefined,\n byline: article.byline ?? undefined,\n excerpt: article.excerpt ?? undefined,\n siteName: (article as { siteName?: string }).siteName ?? undefined,\n }\n : {}),\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n async pageState(input: {\n sessionId: string;\n targetHint?: TargetHint;\n }): Promise<PageStateResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n\n await this.debuggerCommand(selection.tabId, 'Runtime.enable', {});\n const expression = PAGE_STATE_SCRIPT;\n\n const result = await this.debuggerCommand(\n selection.tabId,\n 'Runtime.evaluate',\n {\n expression,\n returnByValue: true,\n awaitPromise: true,\n }\n );\n\n if (result && typeof result === 'object' && 'exceptionDetails' in result) {\n const error = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to capture page state.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n }\n\n const value = (result as { result?: { value?: unknown } })?.result?.value;\n const raw =\n value && typeof value === 'object'\n ? (value as Partial<PageStateResult>)\n : {};\n const warnings = [\n ...(Array.isArray(raw.warnings) ? raw.warnings : []),\n ...(selection.warnings ?? []),\n ];\n const output: PageStateResult = {\n forms: Array.isArray(raw.forms) ? (raw.forms as FormInfo[]) : [],\n localStorage: Array.isArray(raw.localStorage)\n ? (raw.localStorage as StorageEntry[])\n : [],\n sessionStorage: Array.isArray(raw.sessionStorage)\n ? (raw.sessionStorage as StorageEntry[])\n : [],\n cookies: Array.isArray(raw.cookies)\n ? (raw.cookies as StorageEntry[])\n : [],\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n async performanceMetrics(input: {\n sessionId: string;\n targetHint?: TargetHint;\n }): Promise<PerformanceMetricsResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n\n await this.debuggerCommand(selection.tabId, 'Performance.enable', {});\n const result = await this.debuggerCommand(\n selection.tabId,\n 'Performance.getMetrics',\n {}\n );\n const metrics = Array.isArray((result as { metrics?: unknown[] })?.metrics)\n ? (\n result as { metrics: Array<{ name: string; value: number }> }\n ).metrics.map((metric) => ({\n name: metric.name,\n value: metric.value,\n }))\n : [];\n\n const output = { metrics, warnings: selection.warnings };\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n async screenshot(input: {\n sessionId: string;\n target: 'viewport' | 'full';\n selector?: string;\n format?: 'png' | 'jpeg' | 'webp';\n quality?: number;\n targetHint?: TargetHint;\n }): Promise<ArtifactInfo> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n\n const format = input.format ?? 'png';\n const writeArtifact = async (data: string): Promise<ArtifactInfo> => {\n try {\n const rootDir = await ensureArtifactRootDir(input.sessionId);\n const artifactId = randomUUID();\n const extension = format === 'jpeg' ? 'jpg' : format;\n const filePath = path.join(\n rootDir,\n `screenshot-${artifactId}.${extension}`\n );\n await writeFile(filePath, Buffer.from(data, 'base64'));\n const mime = format === 'jpeg' ? 'image/jpeg' : `image/${format}`;\n const output = {\n artifact_id: artifactId,\n path: filePath,\n mime,\n };\n this.markInspectConnected(input.sessionId);\n return output;\n } catch {\n const error = new InspectError(\n 'ARTIFACT_IO_ERROR',\n 'Failed to write screenshot file.'\n );\n this.recordError(error);\n throw error;\n }\n };\n\n if (input.selector) {\n if (!this.extensionBridge?.request) {\n const error = new InspectError(\n 'NOT_SUPPORTED',\n 'Element screenshots require an extension that supports drive.screenshot.'\n );\n this.recordError(error);\n throw error;\n }\n\n const response =\n await this.extensionBridge.request<DriveScreenshotResult>(\n 'drive.screenshot',\n {\n tab_id: selection.tabId,\n mode: 'element',\n selector: input.selector,\n format,\n ...(typeof input.quality === 'number'\n ? { quality: input.quality }\n : {}),\n },\n 120000\n );\n\n if (response.status === 'error') {\n const error = new InspectError(\n (response.error?.code as InspectErrorCode) ?? 'INSPECT_UNAVAILABLE',\n response.error?.message ?? 'Failed to capture element screenshot.',\n {\n retryable: response.error?.retryable ?? false,\n ...(response.error?.details\n ? { details: response.error.details }\n : {}),\n }\n );\n this.recordError(error);\n throw error;\n }\n\n const result = response.result;\n if (!result?.data_base64 || typeof result.data_base64 !== 'string') {\n const error = new InspectError(\n 'INSPECT_UNAVAILABLE',\n 'Failed to capture element screenshot.'\n );\n this.recordError(error);\n throw error;\n }\n\n return await writeArtifact(result.data_base64);\n }\n\n if (input.target === 'full' && this.extensionBridge?.request) {\n try {\n const response =\n await this.extensionBridge.request<DriveScreenshotResult>(\n 'drive.screenshot',\n {\n tab_id: selection.tabId,\n mode: 'full_page',\n format,\n ...(typeof input.quality === 'number'\n ? { quality: input.quality }\n : {}),\n },\n 120000\n );\n\n if (response.status === 'error') {\n const error = new InspectError(\n (response.error?.code as InspectErrorCode) ?? 'INSPECT_UNAVAILABLE',\n response.error?.message ??\n 'Failed to capture full page screenshot.',\n {\n retryable: response.error?.retryable ?? false,\n ...(response.error?.details\n ? { details: response.error.details }\n : {}),\n }\n );\n this.recordError(error);\n throw error;\n }\n\n const result = response.result;\n if (!result?.data_base64 || typeof result.data_base64 !== 'string') {\n const error = new InspectError(\n 'INSPECT_UNAVAILABLE',\n 'Failed to capture full page screenshot.'\n );\n this.recordError(error);\n throw error;\n }\n\n return await writeArtifact(result.data_base64);\n } catch (error) {\n // Fall back to CDP screenshots for environments that don't yet support\n // extension-driven full page capture.\n if (error instanceof InspectError) {\n const code = String(error.code);\n if (\n ![\n 'NOT_SUPPORTED',\n 'NOT_IMPLEMENTED',\n 'INSPECT_UNAVAILABLE',\n ].includes(code)\n ) {\n throw error;\n }\n }\n }\n }\n\n await this.debuggerCommand(selection.tabId, 'Page.enable', {});\n\n let captureParams: Record<string, unknown> = {\n format,\n fromSurface: true,\n };\n if (format !== 'png' && typeof input.quality === 'number') {\n captureParams = { ...captureParams, quality: input.quality };\n }\n\n if (input.target === 'full') {\n const layout = await this.debuggerCommand(\n selection.tabId,\n 'Page.getLayoutMetrics',\n {}\n );\n const contentSize = (\n layout as { contentSize?: { width: number; height: number } }\n )?.contentSize;\n if (contentSize) {\n captureParams = {\n ...captureParams,\n clip: {\n x: 0,\n y: 0,\n width: contentSize.width,\n height: contentSize.height,\n scale: 1,\n },\n };\n } else {\n captureParams = { ...captureParams, captureBeyondViewport: true };\n }\n }\n\n const result = await this.debuggerCommand(\n selection.tabId,\n 'Page.captureScreenshot',\n captureParams\n );\n const data = (result as { data?: string }).data;\n if (!data) {\n const error = new InspectError(\n 'INSPECT_UNAVAILABLE',\n 'Failed to capture screenshot.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n }\n\n return await writeArtifact(data);\n }\n\n private ensureDebugger(): DebuggerBridge {\n if (!this.debugger) {\n const error = this.buildUnavailableError();\n this.recordError(error);\n throw error;\n }\n return this.debugger;\n }\n\n private async resolveTab(\n hint?: TargetHint\n ): Promise<{ tabId: number; tab: DriveTabInfo; warnings?: string[] }> {\n if (!this.extensionBridge || !this.extensionBridge.isConnected()) {\n const error = new InspectError(\n 'EXTENSION_DISCONNECTED',\n 'Extension is not connected.',\n { retryable: true }\n );\n this.recordError(error);\n throw error;\n }\n\n const tabs = this.extensionBridge.getStatus().tabs ?? [];\n if (!Array.isArray(tabs) || tabs.length === 0) {\n const error = new InspectError(\n 'TAB_NOT_FOUND',\n 'No tabs available to inspect.'\n );\n this.recordError(error);\n throw error;\n }\n\n const candidates = tabs.map((tab) => ({\n id: String(tab.tab_id),\n url: tab.url ?? '',\n title: tab.title,\n lastSeenAt: tab.last_active_at\n ? Date.parse(tab.last_active_at)\n : undefined,\n }));\n\n const ranked = pickBestTarget(candidates, hint);\n if (!ranked) {\n const error = new InspectError('TAB_NOT_FOUND', 'No matching tab found.');\n this.recordError(error);\n throw error;\n }\n\n const tabId = Number(ranked.candidate.id);\n if (!Number.isFinite(tabId)) {\n const error = new InspectError(\n 'TAB_NOT_FOUND',\n 'Resolved tab id is invalid.'\n );\n this.recordError(error);\n throw error;\n }\n\n const tab = tabs.find((entry) => entry.tab_id === tabId) ?? tabs[0];\n const warnings: string[] = [];\n if (!hint) {\n warnings.push('No target hint provided; using the most recent tab.');\n } else if (ranked.score < 20) {\n warnings.push('Weak target match; using best available tab.');\n }\n\n return {\n tabId,\n tab,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n\n private async enableConsole(tabId: number): Promise<void> {\n await this.debuggerCommand(tabId, 'Runtime.enable', {});\n await this.debuggerCommand(tabId, 'Log.enable', {});\n }\n\n private async enableNetwork(tabId: number): Promise<void> {\n await this.debuggerCommand(tabId, 'Network.enable', {});\n }\n\n private async enableAccessibility(tabId: number): Promise<void> {\n await this.debuggerCommand(tabId, 'Accessibility.enable', {});\n }\n\n private async debuggerCommand(\n tabId: number,\n method: string,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ): Promise<unknown> {\n const debuggerBridge = this.ensureDebugger();\n const result = await debuggerBridge.command(\n tabId,\n method,\n params,\n timeoutMs\n );\n if (!result.ok) {\n const error = this.mapDebuggerError(result.error);\n this.recordError(error);\n throw error;\n }\n return result.result;\n }\n\n private mapDebuggerError(error: DriveErrorInfo): InspectError {\n const allowed: InspectErrorCode[] = [\n 'INSPECT_UNAVAILABLE',\n 'EXTENSION_DISCONNECTED',\n 'DEBUGGER_IN_USE',\n 'ATTACH_DENIED',\n 'TAB_NOT_FOUND',\n 'NOT_SUPPORTED',\n 'TIMEOUT',\n 'EVALUATION_FAILED',\n 'ARTIFACT_IO_ERROR',\n 'INVALID_ARGUMENT',\n 'INTERNAL',\n ];\n\n const code = allowed.includes(error.code as InspectErrorCode)\n ? (error.code as InspectErrorCode)\n : 'INSPECT_UNAVAILABLE';\n return new InspectError(code, error.message, {\n retryable: error.retryable,\n details: error.details,\n });\n }\n\n private markInspectConnected(sessionId: string): void {\n this.clearLastError();\n try {\n const session = this.registry.require(sessionId);\n if (\n session.state === SessionState.INIT ||\n session.state === SessionState.DRIVE_READY\n ) {\n this.registry.apply(sessionId, 'INSPECT_CONNECTED');\n } else if (session.state === SessionState.DEGRADED_INSPECT) {\n this.registry.apply(sessionId, 'RECOVER_SUCCEEDED');\n }\n } catch {\n // Ignore invalid transitions.\n }\n }\n\n private recordError(error: InspectError): void {\n this.lastError = error;\n this.lastErrorAt = new Date().toISOString();\n }\n\n private clearLastError(): void {\n this.lastError = undefined;\n this.lastErrorAt = undefined;\n }\n\n private buildUnavailableError(): InspectError {\n return new InspectError(\n 'INSPECT_UNAVAILABLE',\n 'Inspect is not available until the debugger bridge is configured.',\n { retryable: false }\n );\n }\n\n private requireSession(sessionId: string): SessionRecord {\n try {\n return this.registry.require(sessionId);\n } catch (error) {\n if (error instanceof SessionError) {\n const code =\n error.code === 'SESSION_CLOSED'\n ? 'SESSION_CLOSED'\n : 'SESSION_NOT_FOUND';\n const wrapped = new InspectError(code, error.message);\n this.recordError(wrapped);\n throw wrapped;\n }\n const wrapped = new InspectError('INTERNAL', 'Failed to load session.');\n this.recordError(wrapped);\n throw wrapped;\n }\n }\n}\n\nexport const createInspectService = (\n options: InspectServiceOptions\n): InspectService => new InspectService(options);\n", "import { mkdir } from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\nconst ARTIFACTS_DIR_NAME = 'browser-agent';\n\nconst resolveTempRoot = (): string =>\n process.env.TMPDIR || process.env.TEMP || process.env.TMP || os.tmpdir();\n\nexport const getArtifactRootDir = (sessionId: string): string =>\n path.join(resolveTempRoot(), ARTIFACTS_DIR_NAME, sessionId);\n\nexport const ensureArtifactRootDir = async (\n sessionId: string\n): Promise<string> => {\n const rootDir = getArtifactRootDir(sessionId);\n await mkdir(rootDir, { recursive: true });\n return rootDir;\n};\n", "import { randomUUID } from 'crypto';\nimport type { Server } from 'http';\nimport type { RawData } from 'ws';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport type {\n DebuggerEvent,\n DebuggerRequestAction,\n DebuggerResponse,\n DriveAction,\n DriveErrorInfo,\n DriveResponse,\n DriveTabInfo,\n ExtensionEvent,\n ExtensionMessage,\n ExtensionRequest,\n ExtensionRequestAction,\n ExtensionResponse,\n} from './drive-protocol';\nimport { SessionRegistry } from './session';\nimport { SessionState } from './state';\n\nexport type ExtensionBridgeStatus = {\n connected: boolean;\n lastSeenAt?: string;\n tabs: DriveTabInfo[];\n};\n\ntype PendingRequest = {\n resolve: (response: ExtensionResponse) => void;\n reject: (error: ExtensionBridgeError) => void;\n timeout: ReturnType<typeof setTimeout>;\n};\n\ntype DebuggerEventListener = (event: DebuggerEvent) => void;\n\nexport class ExtensionBridgeError extends Error {\n public readonly code: string;\n public readonly retryable: boolean;\n public readonly details?: Record<string, unknown>;\n\n constructor(\n code: string,\n message: string,\n retryable = false,\n details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'ExtensionBridgeError';\n this.code = code;\n this.retryable = retryable;\n this.details = details;\n }\n}\n\nexport type ExtensionBridgeOptions = {\n path?: string;\n registry?: SessionRegistry;\n heartbeatIntervalMs?: number;\n heartbeatTimeoutMs?: number;\n};\n\nexport class ExtensionBridge {\n private readonly wss: WebSocketServer;\n private socket: WebSocket | null = null;\n private pending = new Map<string, PendingRequest>();\n private connected = false;\n private lastSeenAt?: string;\n private tabs: DriveTabInfo[] = [];\n private badMessageLogsRemaining = 3;\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n private awaitingHeartbeat = false;\n private readonly heartbeatIntervalMs: number;\n private readonly heartbeatTimeoutMs: number;\n private readonly path: string;\n private readonly registry?: SessionRegistry;\n private readonly debuggerListeners = new Set<DebuggerEventListener>();\n\n constructor(options: ExtensionBridgeOptions = {}) {\n this.wss = new WebSocketServer({ noServer: true });\n this.path = options.path ?? '/drive';\n this.registry = options.registry;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? 15000;\n this.heartbeatTimeoutMs = options.heartbeatTimeoutMs ?? 5000;\n\n this.wss.on('connection', (socket) => {\n this.handleConnection(socket);\n });\n }\n\n attach(server: Server): void {\n server.on('upgrade', (request, socket, head) => {\n const url = new URL(request.url ?? '', 'ws://127.0.0.1');\n if (url.pathname !== this.path) {\n socket.destroy();\n return;\n }\n\n this.wss.handleUpgrade(request, socket, head, (ws) => {\n this.wss.emit('connection', ws, request);\n });\n });\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n getStatus(): ExtensionBridgeStatus {\n return {\n connected: this.connected,\n lastSeenAt: this.lastSeenAt,\n tabs: this.tabs,\n };\n }\n\n async request<T = unknown>(\n action: DriveAction,\n params?: Record<string, unknown>,\n timeoutMs = 30000\n ): Promise<DriveResponse<T>> {\n const response = await this.requestInternal(action, params, timeoutMs);\n return response as DriveResponse<T>;\n }\n\n async requestDebugger<T = unknown>(\n action: DebuggerRequestAction,\n params?: Record<string, unknown>,\n timeoutMs = 30000\n ): Promise<DebuggerResponse<T>> {\n const response = await this.requestInternal(action, params, timeoutMs);\n return response as DebuggerResponse<T>;\n }\n\n onDebuggerEvent(listener: DebuggerEventListener): () => void {\n this.debuggerListeners.add(listener);\n return () => {\n this.debuggerListeners.delete(listener);\n };\n }\n\n private async requestInternal(\n action: ExtensionRequestAction,\n params?: Record<string, unknown>,\n timeoutMs = 30000\n ): Promise<ExtensionResponse> {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n throw new ExtensionBridgeError(\n 'EXTENSION_DISCONNECTED',\n 'Extension is not connected.',\n true\n );\n }\n\n const id = randomUUID();\n const request: ExtensionRequest =\n typeof action === 'string' && action.startsWith('debugger.')\n ? {\n id,\n action: action as DebuggerRequestAction,\n status: 'request',\n params,\n }\n : {\n id,\n action: action as DriveAction,\n status: 'request',\n params,\n };\n\n const response = await new Promise<ExtensionResponse>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(id);\n reject(\n new ExtensionBridgeError(\n 'TIMEOUT',\n `Extension request timed out after ${timeoutMs}ms.`,\n true,\n { action }\n )\n );\n }, timeoutMs);\n\n this.pending.set(id, {\n resolve,\n reject,\n timeout,\n });\n\n this.socket?.send(JSON.stringify(request));\n });\n\n return response;\n }\n\n private startHeartbeat(): void {\n if (this.heartbeatInterval) {\n return;\n }\n this.heartbeatInterval = setInterval(() => {\n void this.sendHeartbeat();\n }, this.heartbeatIntervalMs);\n void this.sendHeartbeat();\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n this.awaitingHeartbeat = false;\n }\n\n private async sendHeartbeat(): Promise<void> {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n return;\n }\n if (this.awaitingHeartbeat) {\n return;\n }\n this.awaitingHeartbeat = true;\n try {\n await this.requestInternal(\n 'drive.ping',\n undefined,\n this.heartbeatTimeoutMs\n );\n } catch (error) {\n console.warn('Extension heartbeat failed:', error);\n this.forceDisconnect();\n } finally {\n this.awaitingHeartbeat = false;\n }\n }\n\n private forceDisconnect(): void {\n if (this.socket && this.socket.readyState === WebSocket.OPEN) {\n try {\n this.socket.terminate();\n } catch (error) {\n console.debug(\n 'Extension socket terminate failed; falling back to close().',\n error\n );\n this.socket.close();\n }\n }\n this.handleDisconnect();\n }\n\n private handleConnection(socket: WebSocket): void {\n if (this.socket && this.socket.readyState === WebSocket.OPEN) {\n this.socket.close();\n }\n\n this.socket = socket;\n this.connected = true;\n this.lastSeenAt = new Date().toISOString();\n\n this.applyDriveConnected();\n this.startHeartbeat();\n\n socket.on('message', (data) => {\n this.handleMessage(data);\n });\n\n socket.on('close', () => {\n this.handleDisconnect();\n });\n\n socket.on('error', () => {\n this.handleDisconnect();\n });\n }\n\n private handleDisconnect(): void {\n if (!this.connected) {\n return;\n }\n\n this.stopHeartbeat();\n this.connected = false;\n this.socket = null;\n this.lastSeenAt = new Date().toISOString();\n this.applyDriveDisconnected();\n\n for (const [id, pending] of this.pending.entries()) {\n clearTimeout(pending.timeout);\n pending.reject(\n new ExtensionBridgeError(\n 'EXTENSION_DISCONNECTED',\n 'Extension disconnected before responding.',\n true,\n { request_id: id }\n )\n );\n this.pending.delete(id);\n }\n }\n\n private handleMessage(data: RawData): void {\n const text = typeof data === 'string' ? data : data.toString();\n\n let message: ExtensionMessage | null = null;\n try {\n message = JSON.parse(text) as ExtensionMessage;\n } catch (error) {\n if (this.badMessageLogsRemaining > 0) {\n this.badMessageLogsRemaining -= 1;\n console.debug('Failed to parse extension message.', error);\n }\n return;\n }\n\n if (!message || typeof message !== 'object') {\n return;\n }\n\n this.lastSeenAt = new Date().toISOString();\n\n if (message.status === 'event') {\n this.handleEvent(message as ExtensionEvent);\n return;\n }\n\n if (\n message.status === 'ok' ||\n message.status === 'error' ||\n message.status === 'ack'\n ) {\n const pending = this.pending.get(message.id);\n if (!pending) {\n return;\n }\n clearTimeout(pending.timeout);\n this.pending.delete(message.id);\n pending.resolve(message as ExtensionResponse);\n }\n }\n\n private handleEvent(message: ExtensionEvent): void {\n if (\n message.action === 'drive.hello' ||\n message.action === 'drive.tab_report'\n ) {\n const tabs = (message.params as { tabs?: DriveTabInfo[] } | undefined)\n ?.tabs;\n if (Array.isArray(tabs)) {\n this.tabs = tabs;\n }\n }\n\n if (\n typeof message.action === 'string' &&\n message.action.startsWith('debugger.')\n ) {\n this.emitDebuggerEvent(message as DebuggerEvent);\n }\n }\n\n private emitDebuggerEvent(event: DebuggerEvent): void {\n for (const listener of this.debuggerListeners) {\n try {\n listener(event);\n } catch (error) {\n console.debug('Debugger event listener failed.', error);\n }\n }\n }\n\n private applyDriveConnected(): void {\n if (!this.registry) {\n return;\n }\n\n for (const session of this.registry.list()) {\n try {\n if (session.state === SessionState.INIT) {\n this.registry.apply(session.id, 'DRIVE_CONNECTED');\n } else if (session.state === SessionState.INSPECT_READY) {\n this.registry.apply(session.id, 'DRIVE_CONNECTED');\n } else if (session.state === SessionState.DEGRADED_DRIVE) {\n this.registry.apply(session.id, 'RECOVER_SUCCEEDED');\n }\n } catch (error) {\n console.debug(\n `Drive connect transition ignored for session ${session.id} (${session.state}).`,\n error\n );\n }\n }\n }\n\n private applyDriveDisconnected(): void {\n if (!this.registry) {\n return;\n }\n\n for (const session of this.registry.list()) {\n try {\n if (session.state === SessionState.READY) {\n this.registry.apply(session.id, 'DRIVE_DISCONNECTED');\n }\n } catch (error) {\n console.debug(\n `Drive disconnect transition ignored for session ${session.id} (${session.state}).`,\n error\n );\n }\n }\n }\n}\n\nexport const toDriveError = (error: ExtensionBridgeError): DriveErrorInfo => ({\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n ...(error.details ? { details: error.details } : {}),\n});\n", "import type { DriveAction, DriveErrorInfo } from './drive-protocol';\nimport {\n ExtensionBridge,\n ExtensionBridgeError,\n toDriveError,\n} from './extension-bridge';\nimport { SessionError, SessionRegistry } from './session';\nimport { SessionState, shouldRetryDriveOp } from './state';\n\nexport type DriveResult<T> =\n | { ok: true; result: T }\n | { ok: false; error: DriveErrorInfo };\n\nclass DriveMutex {\n private tail = Promise.resolve();\n\n async runExclusive<T>(work: () => T | Promise<T>): Promise<T> {\n const result = this.tail.then(work, work);\n this.tail = result.then(\n () => undefined,\n () => undefined\n );\n return await result;\n }\n}\n\nexport const driveMutex = new DriveMutex();\n\nexport class DriveController {\n private readonly bridge: ExtensionBridge;\n private readonly registry: SessionRegistry;\n private lastError?: DriveErrorInfo;\n private lastErrorAt?: string;\n\n constructor(bridge: ExtensionBridge, registry: SessionRegistry) {\n this.bridge = bridge;\n this.registry = registry;\n }\n\n getLastError(): { error: DriveErrorInfo; at: string } | undefined {\n if (!this.lastError || !this.lastErrorAt) {\n return undefined;\n }\n return { error: this.lastError, at: this.lastErrorAt };\n }\n\n private recordError(error: DriveErrorInfo): void {\n this.lastError = error;\n this.lastErrorAt = new Date().toISOString();\n }\n\n private clearLastError(): void {\n this.lastError = undefined;\n this.lastErrorAt = undefined;\n }\n\n async execute<T>(\n sessionId: string,\n action: DriveAction,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ): Promise<DriveResult<T>> {\n return await driveMutex.runExclusive(async () => {\n try {\n this.registry.require(sessionId);\n } catch (error) {\n if (error instanceof SessionError) {\n const errorInfo: DriveErrorInfo = {\n code: error.code,\n message: error.message,\n retryable: false,\n };\n this.recordError(errorInfo);\n return {\n ok: false,\n error: errorInfo,\n };\n }\n const errorInfo: DriveErrorInfo = {\n code: 'INTERNAL',\n message: 'Unexpected error while validating session.',\n retryable: false,\n };\n this.recordError(errorInfo);\n return {\n ok: false,\n error: errorInfo,\n };\n }\n\n if (this.bridge.isConnected()) {\n this.ensureDriveReady(sessionId);\n }\n\n let attempt = 0;\n while (true) {\n try {\n const response = await this.bridge.request<T>(\n action,\n params,\n timeoutMs\n );\n if (response.status === 'ok') {\n this.clearLastError();\n return {\n ok: true,\n result: response.result as T,\n };\n }\n\n const errorInfo: DriveErrorInfo = response.error ?? {\n code: 'UNKNOWN',\n message: 'Drive operation failed.',\n retryable: false,\n };\n\n if (shouldRetryDriveOp({ attempt, retryable: errorInfo.retryable })) {\n attempt += 1;\n continue;\n }\n\n this.recordError(errorInfo);\n return { ok: false, error: errorInfo };\n } catch (error) {\n if (error instanceof ExtensionBridgeError) {\n if (error.code === 'EXTENSION_DISCONNECTED') {\n this.applyDriveDisconnected(sessionId);\n }\n const errorInfo = toDriveError(error);\n if (\n shouldRetryDriveOp({ attempt, retryable: errorInfo.retryable })\n ) {\n attempt += 1;\n continue;\n }\n this.recordError(errorInfo);\n return { ok: false, error: errorInfo };\n }\n\n const errorInfo: DriveErrorInfo = {\n code: 'INTERNAL',\n message: 'Unexpected error while executing drive action.',\n retryable: false,\n };\n this.recordError(errorInfo);\n return {\n ok: false,\n error: errorInfo,\n };\n }\n }\n });\n }\n\n private ensureDriveReady(sessionId: string): void {\n try {\n const session = this.registry.require(sessionId);\n if (session.state === SessionState.INIT) {\n this.registry.apply(sessionId, 'DRIVE_CONNECTED');\n } else if (session.state === SessionState.INSPECT_READY) {\n this.registry.apply(sessionId, 'DRIVE_CONNECTED');\n } else if (session.state === SessionState.DEGRADED_DRIVE) {\n this.registry.apply(sessionId, 'RECOVER_SUCCEEDED');\n }\n } catch (error) {\n console.debug(\n `Drive ready transition ignored for session ${sessionId}.`,\n error\n );\n }\n }\n\n private applyDriveDisconnected(sessionId: string): void {\n try {\n const session = this.registry.require(sessionId);\n if (session.state === SessionState.READY) {\n this.registry.apply(sessionId, 'DRIVE_DISCONNECTED');\n }\n } catch (error) {\n console.debug(\n `Drive disconnect transition ignored for session ${sessionId}.`,\n error\n );\n }\n }\n}\n", "export const PAGE_STATE_SCRIPT = [\n '(() => {',\n ' const escape = (value) => {',\n \" if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\",\n ' return CSS.escape(value);',\n ' }',\n \" return String(value).replace(/[\\\"'\\\\\\\\]/g, '\\\\\\\\$&');\",\n ' };',\n ' const truncate = (value, max) => {',\n \" const text = String(value ?? '');\",\n ' return text.length > max ? text.slice(0, max) : text;',\n ' };',\n ' const selectorFor = (element) => {',\n ' if (element.id) {',\n ' return `#${escape(element.id)}`;',\n ' }',\n \" const name = element.getAttribute('name');\",\n ' if (name) {',\n ' return `${element.tagName.toLowerCase()}[name=\"${escape(name)}\"]`;',\n ' }',\n ' const parts = [];',\n ' let node = element;',\n ' while (node && node.nodeType === 1 && parts.length < 4) {',\n ' let part = node.tagName.toLowerCase();',\n ' const parent = node.parentElement;',\n ' if (parent) {',\n ' const siblings = Array.from(parent.children).filter(',\n ' (child) => child.tagName === node.tagName',\n ' );',\n ' if (siblings.length > 1) {',\n ' part += `:nth-of-type(${siblings.indexOf(node) + 1})`;',\n ' }',\n ' }',\n ' parts.unshift(part);',\n ' node = parent;',\n ' }',\n \" return parts.join('>');\",\n ' };',\n ' const readStorage = (storage, limit) => {',\n ' try {',\n ' return Object.keys(storage)',\n ' .slice(0, limit)',\n ' .map((key) => ({',\n ' key,',\n ' value: truncate(storage.getItem(key), 500),',\n ' }));',\n ' } catch {',\n ' return [];',\n ' }',\n ' };',\n \" const forms = Array.from(document.querySelectorAll('form')).map((form) => {\",\n ' const fields = Array.from(form.elements)',\n ' .filter((element) => element && element.tagName)',\n ' .map((element) => {',\n ' const tag = element.tagName.toLowerCase();',\n \" const type = 'type' in element && element.type ? element.type : tag;\",\n \" const name = element.name || element.getAttribute('name') || element.id || '';\",\n \" let value = '';\",\n ' let options;',\n \" if (tag === 'select') {\",\n ' const select = element;',\n \" value = select.value ?? '';\",\n ' options = Array.from(select.options).map((option) => option.text);',\n \" } else if (tag === 'input' && element.type === 'password') {\",\n \" value = '[redacted]';\",\n \" } else if (tag === 'input' || tag === 'textarea') {\",\n \" value = element.value ?? '';\",\n ' } else if (element.isContentEditable) {',\n \" value = element.textContent ?? '';\",\n \" } else if ('value' in element) {\",\n \" value = element.value ?? '';\",\n ' }',\n ' return {',\n ' name,',\n ' type,',\n ' value: truncate(value, 500),',\n ' ...(options ? { options } : {}),',\n ' };',\n ' });',\n ' return {',\n ' selector: selectorFor(form),',\n \" action: form.getAttribute('action') || undefined,\",\n \" method: form.getAttribute('method') || undefined,\",\n ' fields,',\n ' };',\n ' });',\n ' const localStorage = readStorage(window.localStorage, 100);',\n ' const sessionStorage = readStorage(window.sessionStorage, 100);',\n \" const cookies = (document.cookie ? document.cookie.split(';') : [])\",\n ' .map((entry) => entry.trim())',\n ' .filter((entry) => entry.length > 0)',\n ' .slice(0, 50)',\n ' .map((entry) => {',\n \" const [key, ...rest] = entry.split('=');\",\n \" return { key, value: truncate(rest.join('='), 500) };\",\n ' });',\n ' return { forms, localStorage, sessionStorage, cookies };',\n '})()',\n].join('\\n');\n", "import { getArtifactRootDir } from './artifacts';\nimport type { RecoveryAttempt, RecoveryMetrics } from './recovery';\n\nexport type DiagnosticCheck = {\n name: string;\n ok: boolean;\n message?: string;\n details?: Record<string, unknown>;\n};\n\nexport type DiagnosticReport = {\n ok: boolean;\n session_id?: string;\n checks?: DiagnosticCheck[];\n sessions?: {\n count?: number;\n max_age_ms?: number;\n max_idle_ms?: number;\n };\n extension?: {\n connected?: boolean;\n version?: string;\n last_seen_at?: string;\n };\n debugger?: {\n attached?: boolean;\n idle_timeout_ms?: number;\n console_buffer_size?: number;\n network_buffer_size?: number;\n last_error?: {\n code: string;\n message: string;\n retryable: boolean;\n details?: Record<string, unknown>;\n };\n };\n artifacts?: {\n root_dir?: string;\n };\n recovery?: {\n last_attempt?: {\n session_id: string;\n recovered: boolean;\n state: string;\n message?: string;\n at: string;\n };\n attempts?: {\n session_id: string;\n recovered: boolean;\n state: string;\n message?: string;\n at: string;\n }[];\n success_count?: number;\n failure_count?: number;\n success_rate?: number;\n recent_failure_count?: number;\n loop_detected?: boolean;\n };\n warnings?: string[];\n notes?: string[];\n};\n\nexport type DiagnosticsContext = {\n sessionState?: string;\n sessions?: {\n count: number;\n maxAgeMs?: number;\n maxIdleMs?: number;\n };\n extension?: {\n connected: boolean;\n lastSeenAt?: string;\n };\n debugger?: {\n attached: boolean;\n idle_timeout_ms: number;\n console_buffer_size: number;\n network_buffer_size: number;\n last_error?: {\n code: string;\n message: string;\n retryable: boolean;\n details?: Record<string, unknown>;\n };\n };\n driveLastError?: {\n code: string;\n message: string;\n retryable: boolean;\n at: string;\n };\n inspectLastError?: {\n code: string;\n message: string;\n retryable: boolean;\n at: string;\n };\n recoveryAttempt?: RecoveryAttempt;\n recoveryMetrics?: RecoveryMetrics;\n};\n\nconst STALE_ERROR_THRESHOLD_MS = 2 * 60 * 1000;\n\nconst getErrorAgeMs = (timestamp: string): number | undefined => {\n const parsed = Date.parse(timestamp);\n if (!Number.isFinite(parsed)) {\n return undefined;\n }\n return Math.max(0, Date.now() - parsed);\n};\n\nexport const buildDiagnosticReport = (\n sessionId?: string,\n context: DiagnosticsContext = {}\n): DiagnosticReport => {\n const extensionConnected = context.extension?.connected ?? false;\n const debuggerAttached = context.debugger?.attached ?? false;\n const sessionState = context.sessionState;\n const hasSessionId = Boolean(sessionId);\n const warnings: string[] = [];\n\n const checks: DiagnosticCheck[] = [\n {\n name: 'extension.connected',\n ok: extensionConnected,\n message: extensionConnected\n ? 'Extension is connected.'\n : 'Extension is not connected.',\n },\n {\n name: 'debugger.attached',\n ok: true,\n message: debuggerAttached\n ? 'Debugger is attached.'\n : 'Debugger is not attached (inspect is idle).',\n },\n {\n name: 'session.state',\n ok: hasSessionId ? Boolean(sessionState) : true,\n message: sessionState\n ? `Session state is ${sessionState}.`\n : hasSessionId\n ? 'Session state unavailable.'\n : 'Session id not provided.',\n details: {\n session_id: sessionId || null,\n state: sessionState ?? 'UNKNOWN',\n },\n },\n ];\n\n if (context.driveLastError) {\n const ageMs = getErrorAgeMs(context.driveLastError.at);\n const isStale = ageMs !== undefined && ageMs > STALE_ERROR_THRESHOLD_MS;\n if (isStale) {\n warnings.push(\n `Ignoring stale drive error (${Math.round(ageMs / 1000)}s old): ${context.driveLastError.message}`\n );\n }\n checks.push({\n name: 'drive.last_error',\n ok: isStale,\n message: context.driveLastError.message,\n details: {\n code: context.driveLastError.code,\n retryable: context.driveLastError.retryable,\n at: context.driveLastError.at,\n ...(ageMs !== undefined ? { age_ms: ageMs } : {}),\n },\n });\n }\n\n if (context.inspectLastError) {\n const ageMs = getErrorAgeMs(context.inspectLastError.at);\n const isStale = ageMs !== undefined && ageMs > STALE_ERROR_THRESHOLD_MS;\n if (isStale) {\n warnings.push(\n `Ignoring stale inspect error (${Math.round(ageMs / 1000)}s old): ${context.inspectLastError.message}`\n );\n }\n checks.push({\n name: 'inspect.last_error',\n ok: isStale,\n message: context.inspectLastError.message,\n details: {\n code: context.inspectLastError.code,\n retryable: context.inspectLastError.retryable,\n at: context.inspectLastError.at,\n ...(ageMs !== undefined ? { age_ms: ageMs } : {}),\n },\n });\n }\n\n if (context.recoveryAttempt) {\n checks.push({\n name: 'recovery.last_attempt',\n ok: context.recoveryAttempt.recovered,\n message: context.recoveryAttempt.message ?? 'Recovery attempt recorded.',\n details: {\n session_id: context.recoveryAttempt.sessionId,\n state: context.recoveryAttempt.state,\n at: context.recoveryAttempt.at,\n },\n });\n }\n\n const formatRecoveryAttempt = (attempt: RecoveryAttempt) => ({\n session_id: attempt.sessionId,\n recovered: attempt.recovered,\n state: attempt.state,\n message: attempt.message,\n at: attempt.at,\n });\n const recoveryAttempts = context.recoveryMetrics?.attempts;\n const lastRecoveryAttempt =\n context.recoveryAttempt ??\n (recoveryAttempts && recoveryAttempts[recoveryAttempts.length - 1]);\n\n const report: DiagnosticReport = {\n ok: checks.every((check) => check.ok),\n session_id: sessionId,\n checks,\n sessions: context.sessions\n ? {\n count: context.sessions.count,\n max_age_ms: context.sessions.maxAgeMs,\n max_idle_ms: context.sessions.maxIdleMs,\n }\n : undefined,\n extension: {\n connected: extensionConnected,\n last_seen_at: context.extension?.lastSeenAt,\n },\n debugger: context.debugger\n ? {\n attached: debuggerAttached,\n idle_timeout_ms: context.debugger.idle_timeout_ms,\n console_buffer_size: context.debugger.console_buffer_size,\n network_buffer_size: context.debugger.network_buffer_size,\n last_error: context.debugger.last_error,\n }\n : undefined,\n artifacts: sessionId\n ? {\n root_dir: getArtifactRootDir(sessionId),\n }\n : undefined,\n recovery:\n context.recoveryMetrics || lastRecoveryAttempt\n ? {\n ...(lastRecoveryAttempt\n ? { last_attempt: formatRecoveryAttempt(lastRecoveryAttempt) }\n : {}),\n ...(recoveryAttempts\n ? { attempts: recoveryAttempts.map(formatRecoveryAttempt) }\n : {}),\n ...(context.recoveryMetrics\n ? {\n success_count: context.recoveryMetrics.successCount,\n failure_count: context.recoveryMetrics.failureCount,\n success_rate: context.recoveryMetrics.successRate,\n recent_failure_count:\n context.recoveryMetrics.recentFailureCount,\n loop_detected: context.recoveryMetrics.loopDetected,\n }\n : {}),\n }\n : undefined,\n ...(warnings.length > 0 ? { warnings } : {}),\n notes: ['Diagnostics include runtime status; some checks may be stubbed.'],\n };\n\n return report;\n};\n", "import { DiagnosticsContext, buildDiagnosticReport } from '../diagnostics';\nimport type { SessionRegistry } from '../session';\nimport type { ExtensionBridge } from '../extension-bridge';\nimport type { DriveController } from '../drive';\nimport type { InspectService } from '../inspect';\nimport type { DebuggerBridge } from '../debugger-bridge';\nimport type { RecoveryTracker } from '../recovery';\nimport { HealthCheckInputSchema } from '@btraut/browser-bridge-shared';\nimport { ResponseLike, isRecord, sendError, sendResult } from './shared';\n\ntype RequestLike = {\n body?: unknown;\n};\n\ntype RouteRegistry = {\n post: (\n path: string,\n handler: (req: RequestLike, res: ResponseLike) => void\n ) => void;\n};\n\ntype DiagnosticsRoutesOptions = {\n registry?: SessionRegistry;\n extensionBridge?: ExtensionBridge;\n debuggerBridge?: DebuggerBridge;\n drive?: DriveController;\n inspectService?: InspectService;\n recoveryTracker?: RecoveryTracker;\n};\n\nconst PROCESS_STARTED_AT = new Date(\n Date.now() - Math.floor(process.uptime() * 1000)\n).toISOString();\n\nexport const registerDiagnosticsRoutes = (\n router: RouteRegistry,\n options: DiagnosticsRoutesOptions = {}\n): void => {\n router.post('/health_check', (req, res) => {\n const body = req.body ?? {};\n if (!isRecord(body)) {\n sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'Request body must be an object.',\n retryable: false,\n });\n return;\n }\n\n const parsed = HealthCheckInputSchema.safeParse(body);\n if (!parsed.success) {\n const issue = parsed.error.issues[0];\n sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: issue?.message ?? 'Invalid health check request.',\n retryable: false,\n details: issue?.path.length\n ? { field: issue.path.map((part) => String(part)).join('.') }\n : undefined,\n });\n return;\n }\n\n const sessionsActive = options.registry\n ? options.registry.list().length\n : 0;\n const extensionStatus = options.extensionBridge?.getStatus();\n\n sendResult(res, {\n started_at: PROCESS_STARTED_AT,\n uptime_ms: Math.floor(process.uptime() * 1000),\n memory: process.memoryUsage(),\n sessions: { active: sessionsActive },\n extension: {\n connected: extensionStatus?.connected ?? false,\n ...(extensionStatus?.lastSeenAt\n ? { last_seen_at: extensionStatus.lastSeenAt }\n : {}),\n },\n });\n });\n\n router.post('/diagnostics/doctor', (req, res) => {\n let sessionId: string | undefined;\n if (req.body !== undefined) {\n if (!isRecord(req.body)) {\n sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'Request body must be an object.',\n retryable: false,\n });\n return;\n }\n const raw = req.body.session_id;\n if (raw !== undefined && (typeof raw !== 'string' || raw.length === 0)) {\n sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session_id must be a non-empty string.',\n retryable: false,\n details: { field: 'session_id' },\n });\n return;\n }\n sessionId = raw as string | undefined;\n }\n\n try {\n const context: DiagnosticsContext = {};\n if (options.registry && sessionId) {\n try {\n const session = options.registry.require(sessionId);\n context.sessionState = session.state;\n } catch {\n // Ignore missing session for diagnostics.\n }\n }\n\n if (options.registry) {\n const now = Date.now();\n const sessions = options.registry.list();\n let maxAgeMs = 0;\n let maxIdleMs = 0;\n for (const session of sessions) {\n const ageMs = now - session.createdAt.getTime();\n const idleMs = now - session.lastAccessedAt.getTime();\n if (ageMs > maxAgeMs) {\n maxAgeMs = ageMs;\n }\n if (idleMs > maxIdleMs) {\n maxIdleMs = idleMs;\n }\n }\n context.sessions = {\n count: sessions.length,\n ...(sessions.length > 0 ? { maxAgeMs, maxIdleMs } : {}),\n };\n }\n\n if (options.extensionBridge) {\n const status = options.extensionBridge.getStatus();\n context.extension = {\n connected: status.connected,\n lastSeenAt: status.lastSeenAt,\n };\n }\n\n if (options.debuggerBridge) {\n const settings = options.debuggerBridge.getSettings();\n const lastError = options.debuggerBridge.getLastError();\n context.debugger = {\n attached: options.debuggerBridge.hasAttachments(),\n idle_timeout_ms: settings.idleTimeoutMs,\n console_buffer_size: settings.consoleBufferSize,\n network_buffer_size: settings.networkBufferSize,\n last_error: lastError\n ? {\n code: lastError.error.code,\n message: lastError.error.message,\n retryable: lastError.error.retryable,\n details: lastError.error.details,\n }\n : undefined,\n };\n }\n\n if (options.drive) {\n const lastError = options.drive.getLastError();\n if (lastError) {\n context.driveLastError = {\n code: lastError.error.code,\n message: lastError.error.message,\n retryable: lastError.error.retryable,\n at: lastError.at,\n };\n }\n }\n\n if (options.inspectService) {\n const lastError = options.inspectService.getLastError();\n if (lastError) {\n context.inspectLastError = {\n code: lastError.error.code,\n message: lastError.error.message,\n retryable: lastError.error.retryable,\n at: lastError.at,\n };\n }\n }\n\n if (options.recoveryTracker) {\n const attempt = options.recoveryTracker.getLastAttempt();\n if (attempt) {\n context.recoveryAttempt = {\n sessionId: attempt.sessionId,\n recovered: attempt.recovered,\n state: attempt.state,\n message: attempt.message,\n at: attempt.at,\n };\n }\n context.recoveryMetrics = options.recoveryTracker.getMetrics();\n }\n\n const report = buildDiagnosticReport(sessionId, context);\n sendResult(res, report);\n } catch {\n sendError(res, 500, {\n code: 'INTERNAL',\n message: 'Failed to build diagnostics report.',\n retryable: false,\n });\n }\n });\n};\n", "import { spawn } from 'node:child_process';\n\nexport const openPath = async (target: string): Promise<void> => {\n const platform = process.platform;\n\n if (platform === 'darwin') {\n const child = spawn('open', [target], { detached: true, stdio: 'ignore' });\n child.unref();\n return;\n }\n\n if (platform === 'win32') {\n const child = spawn('cmd', ['/c', 'start', '', target], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n return;\n }\n\n const child = spawn('xdg-open', [target], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n};\n", "import { Command } from 'commander';\nimport { ensureArtifactRootDir } from '@btraut/browser-bridge-core';\nimport { SessionIdSchema } from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runLocal } from '../cli-runtime';\nimport { openPath } from '../open-path';\n\nexport const registerOpenArtifactsCommand = (program: Command): void => {\n program\n .command('open-artifacts')\n .description('Open the artifact folder for a session')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runLocal(command, async () => {\n const payload = parseInput(SessionIdSchema, {\n session_id: options.sessionId,\n });\n const rootDir = await ensureArtifactRootDir(payload.session_id);\n await openPath(rootDir);\n return { ok: true, result: { path: rootDir, opened: true } };\n });\n });\n};\n", "import { Command } from 'commander';\nimport {\n SessionCloseInputSchema,\n SessionCreateInputSchema,\n SessionRecoverInputSchema,\n SessionStatusInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nexport const registerSessionCommands = (program: Command): void => {\n const session = program\n .command('session')\n .description('Manage Core sessions');\n\n session\n .command('create')\n .description('Create a new session')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(SessionCreateInputSchema, {});\n return client.post('/session/create', payload);\n });\n });\n\n session\n .command('status')\n .description('Get session status')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(SessionStatusInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/session/status', payload);\n });\n });\n\n session\n .command('recover')\n .description('Attempt to recover a session')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(SessionRecoverInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/session/recover', payload);\n });\n });\n\n session\n .command('close')\n .description('Close a session')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(SessionCloseInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/session/close', payload);\n });\n });\n};\n", "import { Command } from 'commander';\nimport fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { runLocal } from '../cli-runtime';\nimport { checkboxPrompt, requireTty } from '../tui';\nimport {\n getDefaultHarnessTargets,\n HarnessId,\n} from '../installer/harness-targets';\nimport {\n resolveSkillSourceDir,\n readCliPackageVersion,\n} from '../installer/package-info';\nimport { installBrowserBridgeSkill } from '../installer/skill-install';\nimport { readSkillManifest } from '../installer/skill-manifest';\n\nconst getHarnessMarkerDir = (homeDir: string, harness: HarnessId): string => {\n switch (harness) {\n case 'codex':\n return path.join(homeDir, '.agents');\n default:\n return path.join(homeDir, `.${harness}`);\n }\n};\n\ntype SkillStatusRow = {\n harness: HarnessId;\n skillsDir: string;\n installed: boolean;\n installedVersion: string | null;\n expectedVersion: string;\n upToDate: boolean;\n};\n\nexport const registerSkillCommands = (program: Command): void => {\n const skill = program.command('skill').description('Skill commands');\n\n skill\n .command('install')\n .description('Install the Browser Bridge skill into one or more clients')\n .option(\n '--client <id...>',\n 'Client ids to install into (codex, claude, cursor, factory, opencode, gemini, github, ampcode)'\n )\n .option('--harness <id...>', 'Alias for --client')\n .action(\n async (\n options: { client?: string[]; harness?: string[] },\n command: Command\n ) => {\n await runLocal(command, async ({ json }) => {\n if (json) {\n throw new Error('skill install is interactive; omit --json.');\n }\n\n const version = await readCliPackageVersion();\n const srcSkillDir = await resolveSkillSourceDir();\n\n const targets = getDefaultHarnessTargets();\n const byId = new Map(targets.map((t) => [t.id, t]));\n\n let selected: HarnessId[];\n const requested = options.client?.length\n ? options.client\n : options.harness;\n\n if (requested && requested.length > 0) {\n selected = requested.map((id) => {\n if (!byId.has(id as HarnessId)) {\n throw new Error(`Unknown client: ${id}`);\n }\n return id as HarnessId;\n });\n } else {\n requireTty();\n\n // Default to clients whose home dirs exist, otherwise select Codex.\n const homeDir = os.homedir();\n\n const checked = new Set<HarnessId>();\n for (const t of targets) {\n try {\n const marker = getHarnessMarkerDir(homeDir, t.id);\n await fs.stat(marker);\n checked.add(t.id);\n } catch {\n // ignore\n }\n }\n if (checked.size === 0) {\n checked.add('codex');\n }\n\n selected = await checkboxPrompt<HarnessId>({\n message: 'Install Browser Bridge skill into clients:',\n choices: targets.map((t) => ({\n value: t.id,\n label: `${t.label} (${t.skillsDir})`,\n checked: checked.has(t.id),\n })),\n });\n }\n\n const results: Record<string, { destDir: string }> = {};\n for (const client of selected) {\n const target = byId.get(client);\n if (!target) continue;\n const installed = await installBrowserBridgeSkill({\n srcSkillDir,\n destSkillsDir: target.skillsDir,\n version,\n });\n results[client] = { destDir: installed.destDir };\n }\n\n return {\n ok: true,\n result: {\n version,\n installed: results,\n },\n };\n });\n }\n );\n\n skill\n .command('status')\n .description('Show Browser Bridge skill install status across clients')\n .action(async (_options, command: Command) => {\n await runLocal(command, async () => {\n const version = await readCliPackageVersion();\n const targets = getDefaultHarnessTargets();\n\n const rows: SkillStatusRow[] = [];\n for (const t of targets) {\n const skillDir = path.join(t.skillsDir, 'browser-bridge');\n let installed = false;\n try {\n await fs.stat(skillDir);\n installed = true;\n } catch {\n installed = false;\n }\n\n const manifest = installed ? await readSkillManifest(skillDir) : null;\n const installedVersion = manifest?.version ?? null;\n const upToDate = installedVersion === version;\n\n rows.push({\n harness: t.id,\n skillsDir: t.skillsDir,\n installed,\n installedVersion,\n expectedVersion: version,\n upToDate,\n });\n }\n\n return { ok: true, result: { rows } };\n });\n });\n};\n", "import os from 'node:os';\nimport path from 'node:path';\n\nexport type HarnessId =\n | 'codex'\n | 'claude'\n | 'cursor'\n | 'factory'\n | 'opencode'\n | 'gemini'\n | 'github'\n | 'ampcode';\n\nexport type HarnessTarget = {\n id: HarnessId;\n label: string;\n skillsDir: string;\n // Whether we can install MCP config automatically.\n supportsMcpInstall: boolean;\n};\n\nexport const getDefaultHarnessTargets = (homeDir?: string): HarnessTarget[] => {\n const home = homeDir ?? os.homedir();\n\n // Note: Codex now reads skills from ~/.agents/skills (and may symlink from ~/.codex/skills).\n return [\n {\n id: 'codex',\n label: 'Codex',\n skillsDir: path.join(home, '.agents', 'skills'),\n supportsMcpInstall: true,\n },\n {\n id: 'claude',\n label: 'Claude',\n skillsDir: path.join(home, '.claude', 'skills'),\n supportsMcpInstall: true,\n },\n {\n id: 'cursor',\n label: 'Cursor',\n skillsDir: path.join(home, '.cursor', 'skills'),\n supportsMcpInstall: true,\n },\n {\n id: 'factory',\n label: 'Factory',\n skillsDir: path.join(home, '.factory', 'skills'),\n supportsMcpInstall: false,\n },\n {\n id: 'opencode',\n label: 'OpenCode',\n skillsDir: path.join(home, '.opencode', 'skills'),\n supportsMcpInstall: false,\n },\n {\n id: 'gemini',\n label: 'Gemini',\n skillsDir: path.join(home, '.gemini', 'skills'),\n supportsMcpInstall: false,\n },\n {\n id: 'github',\n label: 'GitHub',\n skillsDir: path.join(home, '.github', 'skills'),\n supportsMcpInstall: false,\n },\n {\n id: 'ampcode',\n label: 'Ampcode',\n skillsDir: path.join(home, '.ampcode', 'skills'),\n supportsMcpInstall: false,\n },\n ];\n};\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nconst PACKAGE_NAME = '@btraut/browser-bridge';\n\nconst tryReadJson = async (filePath: string): Promise<unknown | null> => {\n try {\n const raw = await fs.readFile(filePath, 'utf8');\n return JSON.parse(raw) as unknown;\n } catch {\n return null;\n }\n};\n\nexport const resolveCliPackageRootDir = async (): Promise<string> => {\n // When bundled, `__dirname` may be something like dist/ or dist/installer/\n // (depending on how the bundler preserves module paths). Find the nearest\n // parent directory that contains this package's package.json.\n let dir = __dirname;\n for (let i = 0; i < 12; i++) {\n const candidate = path.join(dir, 'package.json');\n const parsed = (await tryReadJson(candidate)) as { name?: unknown } | null;\n if (parsed && parsed.name === PACKAGE_NAME) {\n return dir;\n }\n\n const parent = path.dirname(dir);\n if (parent === dir) {\n break;\n }\n dir = parent;\n }\n\n throw new Error(\n 'Unable to locate Browser Bridge package root (package.json).'\n );\n};\n\nexport const readCliPackageVersion = async (): Promise<string> => {\n const rootDir = await resolveCliPackageRootDir();\n const pkgPath = path.join(rootDir, 'package.json');\n const parsed = (await tryReadJson(pkgPath)) as { version?: unknown } | null;\n if (!parsed || typeof parsed.version !== 'string' || !parsed.version) {\n throw new Error(`Unable to read version from ${pkgPath}`);\n }\n return parsed.version;\n};\n\nexport const resolveSkillSourceDir = async (): Promise<string> => {\n const rootDir = await resolveCliPackageRootDir();\n\n const packaged = path.join(rootDir, 'skills', 'browser-bridge');\n try {\n await fs.stat(packaged);\n return packaged;\n } catch {\n // In-repo dev usage: `npm run build` does not stage `packages/cli/skills/*`\n // (that happens at npm pack time). Fall back to docs/skills.\n }\n\n const repoRoot = path.resolve(rootDir, '..', '..');\n const docsSkill = path.join(repoRoot, 'docs', 'skills', 'browser-bridge');\n try {\n await fs.stat(docsSkill);\n return docsSkill;\n } catch {\n // ignore\n }\n\n throw new Error(\n `Unable to locate packaged skill. Expected ${packaged} (npm install) or ${docsSkill} (repo dev).`\n );\n};\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { writeSkillManifest } from './skill-manifest';\n\nexport type SkillInstallResult = {\n ok: true;\n destDir: string;\n};\n\nexport const installBrowserBridgeSkill = async (options: {\n srcSkillDir: string;\n destSkillsDir: string;\n version: string;\n}): Promise<SkillInstallResult> => {\n const destDir = path.join(options.destSkillsDir, 'browser-bridge');\n\n await fs.mkdir(options.destSkillsDir, { recursive: true });\n await fs.rm(destDir, { recursive: true, force: true });\n await fs.cp(options.srcSkillDir, destDir, { recursive: true });\n\n // Ensure the installed copy has a version marker that matches the app.\n await writeSkillManifest(destDir, options.version);\n\n return { ok: true, destDir };\n};\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport type SkillManifest = {\n name: 'browser-bridge';\n version: string;\n};\n\nexport const SKILL_MANIFEST_FILENAME = 'skill.json';\n\nexport const readSkillManifest = async (\n skillDir: string\n): Promise<SkillManifest | null> => {\n try {\n const raw = await fs.readFile(\n path.join(skillDir, SKILL_MANIFEST_FILENAME),\n 'utf8'\n );\n const parsed = JSON.parse(raw) as unknown;\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n (parsed as { name?: unknown }).name === 'browser-bridge' &&\n typeof (parsed as { version?: unknown }).version === 'string'\n ) {\n return parsed as SkillManifest;\n }\n return null;\n } catch {\n return null;\n }\n};\n\nexport const writeSkillManifest = async (\n skillDir: string,\n version: string\n): Promise<void> => {\n const payload: SkillManifest = { name: 'browser-bridge', version };\n await fs.writeFile(\n path.join(skillDir, SKILL_MANIFEST_FILENAME),\n JSON.stringify(payload, null, 2) + '\\n',\n 'utf8'\n );\n};\n", "import { Command } from 'commander';\nimport fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { runLocal } from '../cli-runtime';\nimport { checkboxPrompt, requireTty } from '../tui';\nimport {\n getDefaultHarnessTargets,\n HarnessId,\n} from '../installer/harness-targets';\nimport {\n resolveSkillSourceDir,\n readCliPackageVersion,\n} from '../installer/package-info';\nimport { installBrowserBridgeSkill } from '../installer/skill-install';\nimport { installMcp } from '../installer/mcp-install';\n\ntype SetupItem = 'skill' | 'mcp';\n\ntype HarnessInstallResult = {\n harness: HarnessId;\n skill?: { ok: true; destDir: string };\n mcp?:\n | { ok: true; details?: { cursorSettingsPath?: string } }\n | { ok: false; error: { code: string; message: string } };\n};\n\nconst formatInstallSummary = (options: {\n setup: SetupItem[];\n results: HarnessInstallResult[];\n}): string => {\n const wantsSkill = options.setup.includes('skill');\n const wantsMcp = options.setup.includes('mcp');\n\n const lines: string[] = [];\n\n if (wantsSkill) {\n const skillInstalled = options.results\n .filter((r) => r.skill?.ok)\n .map((r) => `- ${r.harness}: ${r.skill?.destDir ?? ''}`);\n if (skillInstalled.length > 0) {\n lines.push('Skill installed:');\n lines.push(...skillInstalled);\n lines.push('');\n }\n }\n\n if (wantsMcp) {\n const mcpOk = options.results\n .filter((r) => r.mcp?.ok)\n .map((r) => `- ${r.harness}`);\n\n const mcpFailed = options.results\n .filter((r) => r.mcp && r.mcp.ok === false)\n .map((r) =>\n r.mcp && r.mcp.ok === false\n ? `- ${r.harness}: ${r.mcp.error.message}`\n : `- ${r.harness}: unknown error`\n );\n\n if (mcpOk.length > 0) {\n lines.push('MCP installed:');\n lines.push(...mcpOk);\n lines.push('');\n }\n\n if (mcpFailed.length > 0) {\n lines.push('MCP failed:');\n lines.push(...mcpFailed);\n lines.push('');\n }\n }\n\n return lines.join('\\n').trimEnd();\n};\n\nconst getHarnessMarkerDir = (harness: HarnessId): string => {\n const homeDir = os.homedir();\n switch (harness) {\n case 'codex':\n return path.join(homeDir, '.agents');\n default:\n return path.join(homeDir, `.${harness}`);\n }\n};\n\nexport const registerInstallCommand = (program: Command): void => {\n program\n .command('install')\n .description('Install Browser Bridge integrations (Skill and/or MCP)')\n .action(async (_options, command: Command) => {\n await runLocal(command, async ({ json }) => {\n if (json) {\n throw new Error('install is interactive; omit --json.');\n }\n\n requireTty();\n\n console.log('Browser Bridge Installer');\n\n const setup = await checkboxPrompt<SetupItem>({\n message: \"Choose what you'd like to install:\",\n choices: [\n { value: 'skill', label: 'Skill (Recommended)', checked: true },\n { value: 'mcp', label: 'MCP (Optional)', checked: true },\n ],\n });\n\n if (setup.length === 0) {\n return { ok: true, result: 'No changes (nothing selected).' };\n }\n\n const wantsSkill = setup.includes('skill');\n const wantsMcp = setup.includes('mcp');\n\n const targets = getDefaultHarnessTargets();\n\n // Default to harnesses whose home dirs exist, otherwise select Codex.\n const checked = new Set<HarnessId>();\n for (const t of targets) {\n try {\n await fs.stat(getHarnessMarkerDir(t.id));\n checked.add(t.id);\n } catch {\n // ignore\n }\n }\n if (checked.size === 0) {\n checked.add('codex');\n }\n\n const selected = await checkboxPrompt<HarnessId>({\n message: 'Install into clients:',\n choices: targets.map((t) => {\n const mcpCapable = t.supportsMcpInstall;\n const enabled = wantsSkill || mcpCapable;\n const disabled = enabled\n ? false\n : wantsMcp\n ? 'MCP install not supported yet'\n : false;\n\n // Keep labels minimal: only annotate when the row is \"skill only\"\n // while the user selected Skill+MCP.\n const suffix =\n wantsMcp && wantsSkill && !mcpCapable ? ' (skill only)' : '';\n\n return {\n value: t.id,\n label: `${t.label}${suffix}`,\n checked: checked.has(t.id),\n disabled,\n };\n }),\n });\n\n const version = await readCliPackageVersion();\n const srcSkillDir = await resolveSkillSourceDir();\n const byId = new Map(targets.map((t) => [t.id, t]));\n\n const results: HarnessInstallResult[] = [];\n let hadError = false;\n for (const harness of selected) {\n const t = byId.get(harness);\n if (!t) continue;\n\n const row: HarnessInstallResult = { harness };\n\n if (wantsSkill) {\n const installed = await installBrowserBridgeSkill({\n srcSkillDir,\n destSkillsDir: t.skillsDir,\n version,\n });\n row.skill = { ok: true, destDir: installed.destDir };\n }\n\n if (wantsMcp && t.supportsMcpInstall) {\n // Only Codex/Claude/Cursor supported in v1.\n if (\n harness === 'codex' ||\n harness === 'claude' ||\n harness === 'cursor'\n ) {\n row.mcp = await installMcp(harness);\n if (row.mcp.ok === false) {\n hadError = true;\n }\n }\n }\n\n results.push(row);\n }\n\n if (hadError) {\n process.exitCode = 1;\n }\n\n const summary = formatInstallSummary({ setup, results });\n return { ok: true, result: summary || 'Done.' };\n });\n });\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["import_zod", "import_zod", "path", "delay", "envelope", "envelope", "program", "parseNumber", "program", "program", "
|
|
3
|
+
"sources": ["../src/index.ts", "../../shared/src/errors.ts", "../../shared/src/logging.ts", "../../shared/src/runtime-config.ts", "../../shared/src/schemas.ts", "../src/cli-output.ts", "../src/core-client.ts", "../src/cli-runtime.ts", "../src/commands/artifacts.ts", "../src/commands/dialog.ts", "../src/commands/diagnostics.ts", "../src/open-path.ts", "../src/commands/dev.ts", "../src/locator.ts", "../src/commands/drive.ts", "../src/commands/inspect.ts", "../../mcp-adapter/src/core-client.ts", "../../mcp-adapter/src/tools.ts", "../../mcp-adapter/src/server.ts", "../src/tui.ts", "../src/installer/mcp-install.ts", "../src/installer/cursor-mcp.ts", "../src/commands/mcp.ts", "../../core/src/server.ts", "../../core/src/routes/session.ts", "../../core/src/inspect/service.ts", "../../core/src/artifacts.ts", "../../core/src/extension-bridge.ts", "../../core/src/drive.ts", "../../core/src/page-state-script.ts", "../../core/src/diagnostics.ts", "../../core/src/routes/diagnostics.ts", "../src/commands/open-artifacts.ts", "../src/commands/session.ts", "../src/commands/skill.ts", "../src/installer/harness-targets.ts", "../src/installer/package-info.ts", "../src/installer/skill-install.ts", "../src/installer/skill-manifest.ts", "../src/commands/install.ts"],
|
|
4
|
+
"sourcesContent": ["import { Command } from 'commander';\nimport { registerArtifactsCommands } from './commands/artifacts';\nimport { registerDialogCommands } from './commands/dialog';\nimport { registerDiagnosticsCommands } from './commands/diagnostics';\nimport { registerDevCommands } from './commands/dev';\nimport { registerDriveCommands } from './commands/drive';\nimport { registerInspectCommands } from './commands/inspect';\nimport { registerMcpCommand } from './commands/mcp';\nimport { registerOpenArtifactsCommand } from './commands/open-artifacts';\nimport { registerSessionCommands } from './commands/session';\nimport { registerSkillCommands } from './commands/skill';\nimport { registerInstallCommand } from './commands/install';\n\nconst program = new Command();\n\nprogram\n .name('browser-bridge')\n .description('Browser Bridge CLI')\n .option('--host <host>', 'Core host (default: 127.0.0.1)')\n .option('--port <port>', 'Core port (default: 3210)')\n .option('--json', 'Output JSON')\n .option('--no-daemon', 'Disable auto-starting Core');\n\nregisterSessionCommands(program);\nregisterDriveCommands(program);\nregisterInspectCommands(program);\nregisterArtifactsCommands(program);\nregisterDiagnosticsCommands(program);\nregisterDialogCommands(program);\nregisterDevCommands(program);\nregisterOpenArtifactsCommand(program);\nregisterMcpCommand(program);\nregisterSkillCommands(program);\nregisterInstallCommand(program);\n\nvoid program.parseAsync(process.argv);\n", "import { z } from 'zod';\n\n// Keep error codes stable; add new codes without renaming existing ones.\nexport const ErrorCodeSchema = z.enum([\n 'UNKNOWN',\n 'INVALID_ARGUMENT',\n 'NOT_FOUND',\n 'ALREADY_EXISTS',\n 'FAILED_PRECONDITION',\n 'UNAUTHORIZED',\n 'FORBIDDEN',\n 'PERMISSION_REQUIRED',\n 'PERMISSION_DENIED',\n 'PERMISSION_PROMPT_TIMEOUT',\n 'CONFLICT',\n 'TIMEOUT',\n 'CANCELLED',\n 'UNAVAILABLE',\n 'RATE_LIMITED',\n 'NOT_IMPLEMENTED',\n 'INTERNAL',\n 'SESSION_NOT_FOUND',\n 'SESSION_CLOSED',\n 'SESSION_BROKEN',\n 'DRIVE_UNAVAILABLE',\n 'INSPECT_UNAVAILABLE',\n 'EXTENSION_DISCONNECTED',\n 'DEBUGGER_IN_USE',\n 'ATTACH_DENIED',\n 'TAB_NOT_FOUND',\n 'NOT_SUPPORTED',\n 'LOCATOR_NOT_FOUND',\n 'NAVIGATION_FAILED',\n 'EVALUATION_FAILED',\n 'ARTIFACT_IO_ERROR',\n]);\n\nexport type ErrorCode = z.infer<typeof ErrorCodeSchema>;\n\nexport const ErrorInfoSchema = z.object({\n code: ErrorCodeSchema,\n message: z.string(),\n retryable: z.boolean(),\n details: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type ErrorInfo = z.infer<typeof ErrorInfoSchema>;\n\nexport const ErrorEnvelopeSchema = z.object({\n ok: z.literal(false),\n error: ErrorInfoSchema,\n});\n\nexport type ErrorEnvelope = z.infer<typeof ErrorEnvelopeSchema>;\n\nexport const successEnvelopeSchema = <T extends z.ZodTypeAny>(result: T) =>\n z.object({\n ok: z.literal(true),\n result,\n });\n\nexport const apiEnvelopeSchema = <T extends z.ZodTypeAny>(result: T) =>\n z.union([successEnvelopeSchema(result), ErrorEnvelopeSchema]);\n\nexport type SuccessEnvelope<T> = {\n ok: true;\n result: T;\n};\n\nexport type ApiEnvelope<T> = SuccessEnvelope<T> | ErrorEnvelope;\n", "import {\n appendFileSync,\n existsSync,\n mkdirSync,\n renameSync,\n rmSync,\n statSync,\n} from 'node:fs';\nimport { join } from 'node:path';\nimport { resolveLogDirectory } from './runtime-config';\n\nexport const DEFAULT_LOG_ROTATION_MAX_BYTES = 10 * 1024 * 1024;\nexport const DEFAULT_LOG_RETENTION = 20;\n\nconst DEFAULT_REDACT_KEYS = [\n 'authorization',\n 'cookie',\n 'setcookie',\n 'password',\n 'passwd',\n 'secret',\n 'token',\n 'accesstoken',\n 'refreshtoken',\n 'apikey',\n 'apikeyid',\n 'privatekey',\n 'clientsecret',\n];\n\nconst REDACTED_VALUE = '[REDACTED]';\nconst MAX_NORMALIZE_DEPTH = 8;\n\ntype JsonValue =\n | null\n | string\n | number\n | boolean\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport type LogFields = Record<string, unknown>;\n\nexport type JsonlLoggerOptions = {\n stream: string;\n cwd?: string;\n gitRoot?: string | null;\n logDir?: string;\n level?: LogLevel;\n bindings?: LogFields;\n redactKeys?: string[];\n maxBytes?: number;\n retention?: number;\n now?: () => Date;\n};\n\nexport type JsonlLogger = {\n stream: string;\n level: LogLevel;\n logDir: string;\n filePath: string;\n child: (bindings: LogFields) => JsonlLogger;\n log: (level: LogLevel, event: string, fields?: LogFields) => void;\n debug: (event: string, fields?: LogFields) => void;\n info: (event: string, fields?: LogFields) => void;\n warn: (event: string, fields?: LogFields) => void;\n error: (event: string, fields?: LogFields) => void;\n};\n\ntype LoggerState = {\n stream: string;\n level: LogLevel;\n logDir: string;\n filePath: string;\n maxBytes: number;\n retention: number;\n redactKeys: Set<string>;\n now: () => Date;\n};\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nconst normalizeRedactionKey = (value: string): string =>\n value.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();\n\nconst sanitizeStreamName = (stream: string): string => {\n const sanitized = stream\n .trim()\n .replace(/[^a-zA-Z0-9._-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n if (sanitized.length === 0) {\n throw new Error('Logger stream name must contain visible characters.');\n }\n return sanitized;\n};\n\nconst normalizeForJson = (\n value: unknown,\n seen: WeakSet<object>,\n depth = 0\n): JsonValue => {\n if (value === null) {\n return null;\n }\n\n if (depth >= MAX_NORMALIZE_DEPTH) {\n return '[MaxDepth]';\n }\n\n const valueType = typeof value;\n if (\n valueType === 'string' ||\n valueType === 'number' ||\n valueType === 'boolean'\n ) {\n return value as string | number | boolean;\n }\n\n if (valueType === 'bigint') {\n return String(value);\n }\n\n if (\n valueType === 'undefined' ||\n valueType === 'symbol' ||\n valueType === 'function'\n ) {\n return String(value);\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (value instanceof Error) {\n return {\n name: value.name,\n message: value.message,\n stack: value.stack ?? null,\n };\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => normalizeForJson(item, seen, depth + 1));\n }\n\n if (value instanceof Set) {\n return Array.from(value.values()).map((item) =>\n normalizeForJson(item, seen, depth + 1)\n );\n }\n\n if (value instanceof Map) {\n const mapped: Record<string, JsonValue> = {};\n for (const [entryKey, entryValue] of value.entries()) {\n mapped[String(entryKey)] = normalizeForJson(entryValue, seen, depth + 1);\n }\n return mapped;\n }\n\n if (typeof value === 'object') {\n const objectValue = value as Record<string, unknown>;\n if (seen.has(objectValue)) {\n return '[Circular]';\n }\n seen.add(objectValue);\n\n const normalized: Record<string, JsonValue> = {};\n for (const [key, nestedValue] of Object.entries(objectValue)) {\n normalized[key] = normalizeForJson(nestedValue, seen, depth + 1);\n }\n\n seen.delete(objectValue);\n return normalized;\n }\n\n return String(value);\n};\n\nconst redactJson = (value: JsonValue, redactKeys: Set<string>): JsonValue => {\n if (Array.isArray(value)) {\n return value.map((item) => redactJson(item, redactKeys));\n }\n\n if (!value || typeof value !== 'object') {\n return value;\n }\n\n const record = value as Record<string, JsonValue>;\n const redacted: Record<string, JsonValue> = {};\n\n for (const [key, nestedValue] of Object.entries(record)) {\n if (redactKeys.has(normalizeRedactionKey(key))) {\n redacted[key] = REDACTED_VALUE;\n continue;\n }\n redacted[key] = redactJson(nestedValue, redactKeys);\n }\n\n return redacted;\n};\n\nconst streamFilePath = (logDir: string, stream: string): string =>\n join(logDir, `${stream}.jsonl`);\n\nconst rotationFilePath = (\n logDir: string,\n stream: string,\n index: number\n): string => join(logDir, `${stream}.${index}.jsonl`);\n\nconst rotateStreamFiles = (\n logDir: string,\n stream: string,\n retention: number\n): void => {\n if (retention <= 1) {\n rmSync(streamFilePath(logDir, stream), { force: true });\n return;\n }\n\n const maxArchiveIndex = retention - 1;\n rmSync(rotationFilePath(logDir, stream, maxArchiveIndex), { force: true });\n\n for (let index = maxArchiveIndex - 1; index >= 1; index -= 1) {\n const source = rotationFilePath(logDir, stream, index);\n if (!existsSync(source)) {\n continue;\n }\n const target = rotationFilePath(logDir, stream, index + 1);\n renameSync(source, target);\n }\n\n const current = streamFilePath(logDir, stream);\n if (existsSync(current)) {\n renameSync(current, rotationFilePath(logDir, stream, 1));\n }\n};\n\nconst rotateIfNeeded = (state: LoggerState, pendingLine: string): void => {\n if (!existsSync(state.filePath)) {\n return;\n }\n\n const pendingBytes = Buffer.byteLength(pendingLine, 'utf8');\n const currentSize = statSync(state.filePath).size;\n if (currentSize + pendingBytes <= state.maxBytes) {\n return;\n }\n\n rotateStreamFiles(state.logDir, state.stream, state.retention);\n};\n\nconst buildLogger = (state: LoggerState, bindings: LogFields): JsonlLogger => {\n const log = (\n level: LogLevel,\n event: string,\n fields: LogFields = {}\n ): void => {\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[state.level]) {\n return;\n }\n\n const payload = {\n ts: state.now().toISOString(),\n level,\n stream: state.stream,\n event,\n ...bindings,\n ...fields,\n };\n\n const normalized = normalizeForJson(payload, new WeakSet<object>());\n const redacted = redactJson(normalized, state.redactKeys);\n const line = `${JSON.stringify(redacted)}\\n`;\n\n try {\n rotateIfNeeded(state, line);\n appendFileSync(state.filePath, line, 'utf8');\n } catch {\n // Logging should not break request flows.\n }\n };\n\n return {\n stream: state.stream,\n level: state.level,\n logDir: state.logDir,\n filePath: state.filePath,\n child: (childBindings) =>\n buildLogger(state, {\n ...bindings,\n ...childBindings,\n }),\n log,\n debug: (event, fields) => log('debug', event, fields),\n info: (event, fields) => log('info', event, fields),\n warn: (event, fields) => log('warn', event, fields),\n error: (event, fields) => log('error', event, fields),\n };\n};\n\nexport const createJsonlLogger = (options: JsonlLoggerOptions): JsonlLogger => {\n const stream = sanitizeStreamName(options.stream);\n const logDir = resolveLogDirectory({\n cwd: options.cwd,\n gitRoot: options.gitRoot,\n logDir: options.logDir,\n });\n\n mkdirSync(logDir, { recursive: true });\n\n const maxBytes =\n typeof options.maxBytes === 'number' && options.maxBytes > 0\n ? Math.floor(options.maxBytes)\n : DEFAULT_LOG_ROTATION_MAX_BYTES;\n\n const retention =\n typeof options.retention === 'number' && options.retention > 0\n ? Math.max(1, Math.floor(options.retention))\n : DEFAULT_LOG_RETENTION;\n\n const state: LoggerState = {\n stream,\n level: options.level ?? 'debug',\n logDir,\n filePath: streamFilePath(logDir, stream),\n maxBytes,\n retention,\n redactKeys: new Set(\n (options.redactKeys ?? DEFAULT_REDACT_KEYS).map(normalizeRedactionKey)\n ),\n now: options.now ?? (() => new Date()),\n };\n\n return buildLogger(state, options.bindings ?? {});\n};\n", "import {\n existsSync,\n mkdirSync,\n readFileSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, isAbsolute, join, resolve } from 'node:path';\n\nconst DEFAULT_HOST = '127.0.0.1';\nconst LEGACY_DEFAULT_PORT = 3210;\nconst DETERMINISTIC_PORT_WINDOW = 2000;\nconst ENV_CORE_HOST = 'BROWSER_BRIDGE_CORE_HOST';\nconst ENV_VISION_HOST = 'BROWSER_VISION_CORE_HOST';\nconst ENV_CORE_PORT = 'BROWSER_BRIDGE_CORE_PORT';\nconst ENV_VISION_PORT = 'BROWSER_VISION_CORE_PORT';\n\nexport const RUNTIME_METADATA_RELATIVE_PATH =\n '.context/browser-bridge/dev.json';\nexport const DEFAULT_LOG_DIRECTORY_RELATIVE_PATH =\n '.context/logs/browser-bridge';\n\nexport type RuntimeMetadata = {\n host?: string;\n port?: number;\n git_root?: string;\n worktree_id?: string;\n extension_id?: string;\n updated_at?: string;\n};\n\nexport type ResolveCoreRuntimeOptions = {\n host?: string;\n port?: number | string;\n cwd?: string;\n gitRoot?: string | null;\n metadataPath?: string;\n metadata?: RuntimeMetadata | null;\n env?: Record<string, string | undefined>;\n strictEnvPort?: boolean;\n};\n\nexport type ResolvedCoreRuntime = {\n host: string;\n port: number;\n hostSource: 'option' | 'env' | 'metadata' | 'default';\n portSource: 'option' | 'env' | 'metadata' | 'deterministic';\n metadataPath: string;\n metadata: RuntimeMetadata | null;\n gitRoot: string | null;\n worktreeId: string | null;\n deterministicPort: number;\n};\n\nconst resolveCwd = (cwd?: string): string => resolve(cwd ?? process.cwd());\n\nconst resolveOptionalPath = (\n cwd: string,\n value?: string\n): string | undefined => {\n if (!value) {\n return undefined;\n }\n return isAbsolute(value) ? value : resolve(cwd, value);\n};\n\nconst normalizeHost = (value: unknown): string | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\nconst parsePort = (\n value: unknown,\n label: string,\n invalidPolicy: 'throw' | 'ignore'\n): number | undefined => {\n if (value === undefined || value === null) {\n return undefined;\n }\n\n if (typeof value === 'string' && value.trim().length === 0) {\n return undefined;\n }\n\n const parsed =\n typeof value === 'number' ? value : Number.parseInt(String(value), 10);\n if (Number.isFinite(parsed) && parsed > 0) {\n return Math.floor(parsed);\n }\n\n if (invalidPolicy === 'throw') {\n throw new Error(`Invalid ${label}: ${String(value)}`);\n }\n return undefined;\n};\n\nconst hashString = (value: string): number => {\n let hash = 2166136261;\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n return hash >>> 0;\n};\n\nconst normalizePathForHash = (value: string): string =>\n value.replace(/\\\\/g, '/').toLowerCase();\n\nconst sanitizeToken = (value: string): string =>\n value\n .trim()\n .replace(/[^a-zA-Z0-9._-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\nconst fallbackWorktreeId = (gitRoot: string): string => {\n const hash = hashString(normalizePathForHash(gitRoot))\n .toString(16)\n .padStart(8, '0');\n return `wt-${hash}`;\n};\n\nconst extractWorktreeIdFromGitDir = (gitDir: string): string | null => {\n const normalized = gitDir.replace(/\\\\/g, '/');\n const marker = '/.git/worktrees/';\n const markerIndex = normalized.lastIndexOf(marker);\n if (markerIndex < 0) {\n return null;\n }\n const remainder = normalized.slice(markerIndex + marker.length);\n const rawId = remainder.split('/')[0];\n if (!rawId) {\n return null;\n }\n const sanitized = sanitizeToken(rawId);\n return sanitized.length > 0 ? sanitized : null;\n};\n\nconst readWorktreeGitDir = (gitRoot: string): string | null => {\n const gitPath = join(gitRoot, '.git');\n try {\n const stats = statSync(gitPath);\n if (stats.isDirectory()) {\n return gitPath;\n }\n if (!stats.isFile()) {\n return null;\n }\n } catch {\n return null;\n }\n\n try {\n const raw = readFileSync(gitPath, 'utf8');\n const match = raw.match(/^gitdir:\\s*(.+)$/m);\n if (!match?.[1]) {\n return null;\n }\n const candidate = match[1].trim();\n return isAbsolute(candidate) ? candidate : resolve(gitRoot, candidate);\n } catch {\n return null;\n }\n};\n\nconst resolveEnvHost = (\n env: Record<string, string | undefined>\n): string | undefined => {\n const bridgeHost = normalizeHost(env[ENV_CORE_HOST]);\n if (bridgeHost) {\n return bridgeHost;\n }\n return normalizeHost(env[ENV_VISION_HOST]);\n};\n\nconst resolveEnvPortRaw = (\n env: Record<string, string | undefined>\n): string | undefined => {\n if (env[ENV_CORE_PORT] !== undefined) {\n return env[ENV_CORE_PORT];\n }\n return env[ENV_VISION_PORT];\n};\n\nconst sanitizeMetadata = (raw: unknown): RuntimeMetadata | null => {\n if (!raw || typeof raw !== 'object') {\n return null;\n }\n const candidate = raw as Record<string, unknown>;\n const host = normalizeHost(candidate.host);\n const port = parsePort(candidate.port, 'port', 'ignore');\n const gitRoot = normalizeHost(candidate.git_root);\n const worktreeId = normalizeHost(candidate.worktree_id);\n const extensionId = normalizeHost(candidate.extension_id);\n const updatedAt = normalizeHost(candidate.updated_at);\n\n if (\n !host &&\n port === undefined &&\n !gitRoot &&\n !worktreeId &&\n !extensionId &&\n !updatedAt\n ) {\n return null;\n }\n\n return {\n host,\n port,\n git_root: gitRoot,\n worktree_id: worktreeId,\n extension_id: extensionId,\n updated_at: updatedAt,\n };\n};\n\nexport const findGitRoot = (cwd = process.cwd()): string | null => {\n let current = resolve(cwd);\n while (true) {\n if (existsSync(join(current, '.git'))) {\n return current;\n }\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n};\n\nexport const resolveWorktreeId = ({\n cwd,\n gitRoot,\n}: {\n cwd?: string;\n gitRoot?: string | null;\n} = {}): string | null => {\n const resolvedGitRoot = gitRoot ?? findGitRoot(resolveCwd(cwd));\n if (!resolvedGitRoot) {\n return null;\n }\n const gitDir = readWorktreeGitDir(resolvedGitRoot);\n const parsedId = gitDir ? extractWorktreeIdFromGitDir(gitDir) : null;\n if (parsedId) {\n return parsedId;\n }\n return fallbackWorktreeId(resolvedGitRoot);\n};\n\nexport const resolveDeterministicCorePort = ({\n cwd,\n gitRoot,\n}: {\n cwd?: string;\n gitRoot?: string | null;\n} = {}): number => {\n const resolvedGitRoot = gitRoot ?? findGitRoot(resolveCwd(cwd));\n if (!resolvedGitRoot) {\n return LEGACY_DEFAULT_PORT;\n }\n const seed = normalizePathForHash(resolvedGitRoot);\n return LEGACY_DEFAULT_PORT + (hashString(seed) % DETERMINISTIC_PORT_WINDOW);\n};\n\nexport const resolveRuntimeMetadataPath = ({\n cwd,\n gitRoot,\n metadataPath,\n}: {\n cwd?: string;\n gitRoot?: string | null;\n metadataPath?: string;\n} = {}): string => {\n const resolvedCwd = resolveCwd(cwd);\n const providedPath = resolveOptionalPath(resolvedCwd, metadataPath);\n if (providedPath) {\n return providedPath;\n }\n const root = gitRoot ?? findGitRoot(resolvedCwd) ?? resolvedCwd;\n return join(root, RUNTIME_METADATA_RELATIVE_PATH);\n};\n\nexport const resolveLogDirectory = ({\n cwd,\n gitRoot,\n logDir,\n}: {\n cwd?: string;\n gitRoot?: string | null;\n logDir?: string;\n} = {}): string => {\n const resolvedCwd = resolveCwd(cwd);\n const providedPath = resolveOptionalPath(resolvedCwd, logDir);\n if (providedPath) {\n return providedPath;\n }\n\n const resolvedGitRoot =\n gitRoot === undefined\n ? findGitRoot(resolvedCwd)\n : gitRoot\n ? resolve(gitRoot)\n : null;\n\n return join(\n resolvedGitRoot ?? resolvedCwd,\n DEFAULT_LOG_DIRECTORY_RELATIVE_PATH\n );\n};\n\nexport const readRuntimeMetadata = ({\n cwd,\n gitRoot,\n metadataPath,\n}: {\n cwd?: string;\n gitRoot?: string | null;\n metadataPath?: string;\n} = {}): RuntimeMetadata | null => {\n const path = resolveRuntimeMetadataPath({ cwd, gitRoot, metadataPath });\n if (!existsSync(path)) {\n return null;\n }\n try {\n const raw = readFileSync(path, 'utf8');\n const parsed = JSON.parse(raw) as unknown;\n return sanitizeMetadata(parsed);\n } catch {\n return null;\n }\n};\n\nexport const writeRuntimeMetadata = (\n metadata: RuntimeMetadata,\n {\n cwd,\n gitRoot,\n metadataPath,\n }: {\n cwd?: string;\n gitRoot?: string | null;\n metadataPath?: string;\n } = {}\n): string => {\n const path = resolveRuntimeMetadataPath({ cwd, gitRoot, metadataPath });\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(metadata, null, 2)}\\n`, 'utf8');\n return path;\n};\n\nexport const createBoundedPortProbeSequence = (\n startPort: number,\n maxAttempts = 20,\n maxPort = 65535\n): number[] => {\n const normalizedStart = parsePort(startPort, 'startPort', 'throw');\n if (normalizedStart === undefined) {\n throw new Error(`Invalid startPort: ${String(startPort)}`);\n }\n const attempts = Math.max(1, Math.floor(maxAttempts));\n const ceiling = Math.min(65535, Math.max(1, Math.floor(maxPort)));\n\n if (normalizedStart > ceiling) {\n throw new Error(`startPort ${normalizedStart} exceeds maxPort ${ceiling}.`);\n }\n\n const sequence: number[] = [];\n for (let offset = 0; offset < attempts; offset += 1) {\n const port = normalizedStart + offset;\n if (port > ceiling) {\n break;\n }\n sequence.push(port);\n }\n return sequence;\n};\n\nexport const resolveCoreRuntime = (\n options: ResolveCoreRuntimeOptions = {}\n): ResolvedCoreRuntime => {\n const env = options.env ?? process.env;\n const resolvedCwd = resolveCwd(options.cwd);\n const gitRoot =\n options.gitRoot === undefined\n ? findGitRoot(resolvedCwd)\n : options.gitRoot\n ? resolve(options.gitRoot)\n : null;\n\n const metadataPath = resolveRuntimeMetadataPath({\n cwd: resolvedCwd,\n gitRoot,\n metadataPath: options.metadataPath,\n });\n\n const metadata =\n options.metadata === undefined\n ? readRuntimeMetadata({ metadataPath })\n : sanitizeMetadata(options.metadata);\n\n const deterministicPort = resolveDeterministicCorePort({\n cwd: resolvedCwd,\n gitRoot,\n });\n\n const optionHost = normalizeHost(options.host);\n const envHost = resolveEnvHost(env);\n const metadataHost = normalizeHost(metadata?.host);\n\n const host = optionHost ?? envHost ?? metadataHost ?? DEFAULT_HOST;\n const hostSource: ResolvedCoreRuntime['hostSource'] = optionHost\n ? 'option'\n : envHost\n ? 'env'\n : metadataHost\n ? 'metadata'\n : 'default';\n\n const optionPort = parsePort(options.port, 'port', 'throw');\n const envPort = parsePort(\n resolveEnvPortRaw(env),\n 'port',\n options.strictEnvPort ? 'throw' : 'ignore'\n );\n const metadataPort = parsePort(metadata?.port, 'port', 'ignore');\n\n let port: number;\n let portSource: ResolvedCoreRuntime['portSource'];\n\n if (optionPort !== undefined) {\n port = optionPort;\n portSource = 'option';\n } else if (envPort !== undefined) {\n port = envPort;\n portSource = 'env';\n } else if (metadataPort !== undefined) {\n port = metadataPort;\n portSource = 'metadata';\n } else {\n port = deterministicPort;\n portSource = 'deterministic';\n }\n\n return {\n host,\n port,\n hostSource,\n portSource,\n metadataPath,\n metadata,\n gitRoot,\n worktreeId: resolveWorktreeId({ cwd: resolvedCwd, gitRoot }),\n deterministicPort,\n };\n};\n", "import { z } from 'zod';\nimport { ErrorInfoSchema } from './errors';\n\nexport const LocatorRoleSchema = z.object({\n name: z.string(),\n value: z.string().optional(),\n});\n\nexport const LocatorSchema = z\n .object({\n ref: z.string().min(1).optional(),\n testid: z.string().min(1).optional(),\n css: z.string().min(1).optional(),\n text: z.string().min(1).optional(),\n role: LocatorRoleSchema.optional(),\n })\n .refine(\n (value) =>\n Boolean(\n value.ref || value.testid || value.css || value.text || value.role\n ),\n {\n message: 'Locator must include at least one selector.',\n }\n );\n\nexport const OpResultSchema = z.object({\n ok: z.literal(true),\n message: z.string().optional(),\n warnings: z.array(z.string()).optional(),\n});\n\nexport const SessionStateSchema = z.enum([\n 'INIT',\n 'DRIVE_READY',\n 'INSPECT_READY',\n 'READY',\n 'DEGRADED_DRIVE',\n 'DEGRADED_INSPECT',\n 'BROKEN',\n 'CLOSED',\n]);\n\nexport const SessionInfoSchema = z.object({\n session_id: z.string(),\n state: SessionStateSchema,\n created_at: z.string().datetime().optional(),\n});\n\nexport const SessionPlaneStatusSchema = z.object({\n connected: z.boolean(),\n last_seen_at: z.string().datetime().optional(),\n error: ErrorInfoSchema.optional(),\n});\n\nexport const SessionStatusSchema = z.object({\n session_id: z.string(),\n state: SessionStateSchema,\n drive: SessionPlaneStatusSchema.optional(),\n inspect: SessionPlaneStatusSchema.optional(),\n updated_at: z.string().datetime().optional(),\n});\n\nexport const RecoverResultSchema = z.object({\n session_id: z.string(),\n recovered: z.boolean(),\n state: SessionStateSchema,\n message: z.string().optional(),\n});\n\nexport const DiagnosticCheckSchema = z.object({\n name: z.string(),\n ok: z.boolean(),\n message: z.string().optional(),\n details: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const DiagnosticReportSchema = z.object({\n ok: z.boolean(),\n session_id: z.string().optional(),\n checks: z.array(DiagnosticCheckSchema).optional(),\n sessions: z\n .object({\n count: z.number().finite().optional(),\n max_age_ms: z.number().finite().optional(),\n max_idle_ms: z.number().finite().optional(),\n })\n .optional(),\n extension: z\n .object({\n connected: z.boolean().optional(),\n version: z.string().optional(),\n last_seen_at: z.string().datetime().optional(),\n })\n .optional(),\n debugger: z\n .object({\n attached: z.boolean().optional(),\n idle_timeout_ms: z.number().finite().optional(),\n console_buffer_size: z.number().finite().optional(),\n network_buffer_size: z.number().finite().optional(),\n last_error: ErrorInfoSchema.optional(),\n })\n .optional(),\n artifacts: z\n .object({\n root_dir: z.string().optional(),\n })\n .optional(),\n recovery: z\n .object({\n last_attempt: z\n .object({\n session_id: z.string(),\n recovered: z.boolean(),\n state: SessionStateSchema,\n message: z.string().optional(),\n at: z.string(),\n })\n .optional(),\n attempts: z\n .array(\n z.object({\n session_id: z.string(),\n recovered: z.boolean(),\n state: SessionStateSchema,\n message: z.string().optional(),\n at: z.string(),\n })\n )\n .optional(),\n success_count: z.number().finite().optional(),\n failure_count: z.number().finite().optional(),\n success_rate: z.number().finite().optional(),\n recent_failure_count: z.number().finite().optional(),\n loop_detected: z.boolean().optional(),\n })\n .optional(),\n warnings: z.array(z.string()).optional(),\n notes: z.array(z.string()).optional(),\n});\n\nexport const SessionIdSchema = z.object({\n session_id: z.string().min(1),\n});\n\nexport const SessionCreateInputSchema = z.object({}).strict().default({});\nexport const SessionCreateOutputSchema = SessionInfoSchema;\n\nexport const SessionStatusInputSchema = SessionIdSchema;\nexport const SessionStatusOutputSchema = SessionStatusSchema;\n\nexport const SessionRecoverInputSchema = SessionIdSchema;\nexport const SessionRecoverOutputSchema = RecoverResultSchema;\n\nexport const SessionCloseInputSchema = SessionIdSchema;\nexport const SessionCloseOutputSchema = z.object({\n ok: z.boolean(),\n});\n\nexport const DriveWaitConditionSchema = z.object({\n kind: z.enum(['locator_visible', 'text_present', 'url_matches']),\n value: z.string().min(1),\n});\n\nexport const DriveNavigateInputSchema = z.object({\n session_id: z.string().min(1),\n url: z.string().min(1),\n tab_id: z.number().finite().optional(),\n wait: z.enum(['none', 'domcontentloaded']).default('domcontentloaded'),\n});\nexport const DriveNavigateOutputSchema = OpResultSchema;\n\nexport const DriveGoBackInputSchema = z.object({\n session_id: z.string().min(1),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveGoBackOutputSchema = OpResultSchema;\n\nexport const DriveGoForwardInputSchema = z.object({\n session_id: z.string().min(1),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveGoForwardOutputSchema = OpResultSchema;\n\nexport const DriveBackInputSchema = DriveGoBackInputSchema;\nexport const DriveBackOutputSchema = OpResultSchema;\n\nexport const DriveForwardInputSchema = DriveGoForwardInputSchema;\nexport const DriveForwardOutputSchema = OpResultSchema;\n\nexport const DriveClickInputSchema = z.object({\n session_id: z.string().min(1),\n locator: LocatorSchema,\n tab_id: z.number().finite().optional(),\n click_count: z.number().finite().optional(),\n});\nexport const DriveClickOutputSchema = OpResultSchema;\n\nexport const DriveHoverInputSchema = z.object({\n session_id: z.string().min(1),\n locator: LocatorSchema,\n delay_ms: z.number().min(0).max(10000).optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveHoverOutputSchema = z.object({\n format: z.literal('html'),\n snapshot: z.string(),\n});\n\nexport const DriveSelectInputSchema = z\n .object({\n session_id: z.string().min(1),\n locator: LocatorSchema,\n value: z.string().min(1).optional(),\n text: z.string().min(1).optional(),\n index: z.number().int().min(0).optional(),\n tab_id: z.number().finite().optional(),\n })\n .refine((value) => value.value || value.text || value.index !== undefined, {\n message: 'Either value, text, or index must be provided.',\n path: ['select'],\n });\nexport const DriveSelectOutputSchema = OpResultSchema;\n\nexport const DriveTypeInputSchema = z.object({\n session_id: z.string().min(1),\n locator: LocatorSchema.optional(),\n text: z.string().min(1),\n tab_id: z.number().finite().optional(),\n clear: z.boolean().default(false),\n submit: z.boolean().default(false),\n});\nexport const DriveTypeOutputSchema = OpResultSchema;\n\nexport const DriveFillFormFieldSchema = z\n .object({\n selector: z.string().min(1).optional(),\n locator: LocatorSchema.optional(),\n value: z.union([z.string(), z.boolean()]),\n type: z\n .enum(['auto', 'text', 'select', 'checkbox', 'radio', 'contentEditable'])\n .default('auto'),\n submit: z.boolean().default(false),\n })\n .refine((value) => Boolean(value.selector || value.locator), {\n message: 'fill_form field requires selector or locator.',\n path: ['selector'],\n });\n\nexport const DriveFillFormInputSchema = z.object({\n session_id: z.string().min(1),\n fields: z.array(DriveFillFormFieldSchema).min(1),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveFillFormOutputSchema = z.object({\n filled: z.number().finite(),\n attempted: z.number().finite(),\n errors: z.array(z.string()).optional(),\n});\n\nexport const DriveDragInputSchema = z.object({\n session_id: z.string().min(1),\n from: LocatorSchema,\n to: LocatorSchema,\n steps: z.number().min(1).max(50).default(12),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveDragOutputSchema = OpResultSchema;\n\nexport const DriveHandleDialogInputSchema = z.object({\n session_id: z.string().min(1),\n action: z.enum(['accept', 'dismiss']),\n promptText: z.string().optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveHandleDialogOutputSchema = OpResultSchema;\n\nexport const DialogAcceptInputSchema = SessionIdSchema.extend({\n promptText: z.string().optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DialogAcceptOutputSchema = OpResultSchema;\n\nexport const DialogDismissInputSchema = SessionIdSchema.extend({\n tab_id: z.number().finite().optional(),\n});\nexport const DialogDismissOutputSchema = OpResultSchema;\n\nexport const DriveKeyModifiersSchema = z.object({\n ctrl: z.boolean().optional(),\n alt: z.boolean().optional(),\n shift: z.boolean().optional(),\n meta: z.boolean().optional(),\n});\n\nexport const DriveKeyPressInputSchema = z.object({\n session_id: z.string().min(1),\n key: z.string().min(1),\n modifiers: DriveKeyModifiersSchema.optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveKeyPressOutputSchema = OpResultSchema;\n\nexport const DriveKeyModifierSchema = z.enum(['ctrl', 'alt', 'shift', 'meta']);\n\nexport const DriveKeyInputSchema = z.object({\n session_id: z.string().min(1),\n key: z.string().min(1),\n modifiers: z.array(DriveKeyModifierSchema).optional(),\n repeat: z.number().int().min(1).max(50).optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveKeyOutputSchema = OpResultSchema;\n\nexport const DriveScrollInputSchema = z\n .object({\n session_id: z.string().min(1),\n delta_x: z.number().finite().optional(),\n delta_y: z.number().finite().optional(),\n top: z.number().finite().optional(),\n left: z.number().finite().optional(),\n behavior: z.enum(['auto', 'smooth']).optional(),\n tab_id: z.number().finite().optional(),\n })\n .refine(\n (value) =>\n value.delta_x !== undefined ||\n value.delta_y !== undefined ||\n value.top !== undefined ||\n value.left !== undefined,\n {\n message: 'scroll requires delta_x/delta_y or top/left.',\n path: ['scroll'],\n }\n );\nexport const DriveScrollOutputSchema = OpResultSchema;\n\nexport const DriveWaitForInputSchema = z.object({\n session_id: z.string().min(1),\n condition: DriveWaitConditionSchema,\n timeout_ms: z.number().finite().optional(),\n tab_id: z.number().finite().optional(),\n});\nexport const DriveWaitForOutputSchema = OpResultSchema;\n\nexport const DriveTabInfoSchema = z.object({\n tab_id: z.number().finite(),\n window_id: z.number().finite(),\n url: z.string().min(1),\n title: z.string(),\n active: z.boolean().optional(),\n last_active_at: z.string().datetime().optional(),\n});\n\nexport const DriveTabListInputSchema = SessionIdSchema;\nexport const DriveTabListOutputSchema = z.object({\n tabs: z.array(DriveTabInfoSchema),\n});\n\nexport const DriveTabActivateInputSchema = z.object({\n session_id: z.string().min(1),\n tab_id: z.number().finite(),\n});\nexport const DriveTabActivateOutputSchema = OpResultSchema;\n\nexport const DriveTabCloseInputSchema = z.object({\n session_id: z.string().min(1),\n tab_id: z.number().finite(),\n});\nexport const DriveTabCloseOutputSchema = OpResultSchema;\n\nexport const InspectDomFormatSchema = z.enum(['ax', 'html']);\nexport const InspectConsistencySchema = z.enum(['best_effort', 'quiesce']);\n\nexport const TargetHintSchema = z.object({\n url: z.string().min(1).optional(),\n title: z.string().min(1).optional(),\n last_active_at: z.string().optional(),\n lastActiveAt: z.string().optional(),\n});\n\nexport const FormFieldInfoSchema = z.object({\n name: z.string(),\n type: z.string(),\n value: z.string(),\n options: z.array(z.string()).optional(),\n});\n\nexport const FormInfoSchema = z.object({\n selector: z.string(),\n action: z.string().optional(),\n method: z.string().optional(),\n fields: z.array(FormFieldInfoSchema),\n});\n\nexport const StorageEntrySchema = z.object({\n key: z.string(),\n value: z.string(),\n});\n\nexport const PageStateSchema = z.object({\n forms: z.array(FormInfoSchema),\n localStorage: z.array(StorageEntrySchema),\n sessionStorage: z.array(StorageEntrySchema),\n cookies: z.array(StorageEntrySchema),\n warnings: z.array(z.string()).optional(),\n});\n\nexport const DomSnapshotSchema = z\n .object({\n format: InspectDomFormatSchema,\n snapshot: z.unknown(),\n })\n .passthrough();\n\nexport const InspectDomSnapshotInputSchema = z.object({\n session_id: z.string().min(1),\n format: InspectDomFormatSchema.default('ax'),\n consistency: InspectConsistencySchema.default('best_effort'),\n interactive: z.boolean().default(false),\n compact: z.boolean().default(false),\n // Used primarily to bound large AX trees for LLM/agent consumption.\n // CLI passes this as a string, so coerce for convenience.\n max_nodes: z.coerce.number().int().positive().max(50000).optional(),\n selector: z.string().min(1).optional(),\n target: TargetHintSchema.optional(),\n});\nexport const InspectDomSnapshotOutputSchema = DomSnapshotSchema;\n\nexport const DomDiffResultSchema = z.object({\n added: z.array(z.string()),\n removed: z.array(z.string()),\n changed: z.array(z.string()),\n summary: z.string(),\n});\n\nexport const InspectDomDiffInputSchema = SessionIdSchema;\nexport const InspectDomDiffOutputSchema = DomDiffResultSchema;\n\nexport const InspectFindRoleInputSchema = SessionIdSchema.extend({\n kind: z.literal('role'),\n role: z.string().min(1),\n name: z.string().min(1).optional(),\n target: TargetHintSchema.optional(),\n});\n\nexport const InspectFindTextInputSchema = SessionIdSchema.extend({\n kind: z.literal('text'),\n text: z.string().min(1),\n target: TargetHintSchema.optional(),\n});\n\nexport const InspectFindLabelInputSchema = SessionIdSchema.extend({\n kind: z.literal('label'),\n label: z.string().min(1),\n target: TargetHintSchema.optional(),\n});\n\nexport const InspectFindInputSchema = z.discriminatedUnion('kind', [\n InspectFindRoleInputSchema,\n InspectFindTextInputSchema,\n InspectFindLabelInputSchema,\n]);\n\nexport const InspectFindMatchSchema = z.object({\n ref: z.string(),\n role: z.string().optional(),\n name: z.string().optional(),\n});\n\nexport const InspectFindOutputSchema = z.object({\n matches: z.array(InspectFindMatchSchema),\n warnings: z.array(z.string()).optional(),\n});\n\nexport const InspectPageStateInputSchema = SessionIdSchema.extend({\n target: TargetHintSchema.optional(),\n});\nexport const InspectPageStateOutputSchema = PageStateSchema;\n\nexport const InspectExtractContentFormatSchema = z.enum([\n 'markdown',\n 'text',\n 'article_json',\n]);\n\nexport const InspectExtractContentInputSchema = SessionIdSchema.extend({\n format: InspectExtractContentFormatSchema.default('markdown'),\n include_metadata: z.boolean().default(true),\n target: TargetHintSchema.optional(),\n});\n\nexport const InspectExtractContentOutputSchema = z.object({\n content: z.string(),\n title: z.string().optional(),\n byline: z.string().optional(),\n excerpt: z.string().optional(),\n siteName: z.string().optional(),\n warnings: z.array(z.string()).optional(),\n});\n\nexport const InspectConsoleListInputSchema = SessionIdSchema.extend({\n target: TargetHintSchema.optional(),\n});\n// Console output may expand over time; include a stable core + allow passthrough.\nexport const ConsoleSourceLocationSchema = z\n .object({\n url: z.string().optional(),\n // 1-based line/column for human readability.\n line: z.number().int().positive().optional(),\n column: z.number().int().positive().optional(),\n })\n .passthrough();\n\nexport const ConsoleStackFrameSchema = z\n .object({\n functionName: z.string().optional(),\n url: z.string().optional(),\n // 1-based line/column for human readability.\n line: z.number().int().positive().optional(),\n column: z.number().int().positive().optional(),\n })\n .passthrough();\n\nexport const ConsoleRemoteObjectSchema = z\n .object({\n type: z.string().optional(),\n subtype: z.string().optional(),\n description: z.string().optional(),\n value: z.unknown().optional(),\n unserializableValue: z.string().optional(),\n })\n .passthrough();\n\nexport const ConsoleEntrySchema = z\n .object({\n level: z.string().optional(),\n text: z.string().optional(),\n timestamp: z.string().datetime().optional(),\n source: ConsoleSourceLocationSchema.optional(),\n stack: z.array(ConsoleStackFrameSchema).optional(),\n exception: ConsoleRemoteObjectSchema.optional(),\n args: z.array(ConsoleRemoteObjectSchema).optional(),\n })\n .passthrough();\nexport const ConsoleListSchema = z\n .object({\n entries: z.array(ConsoleEntrySchema),\n })\n .passthrough();\nexport const InspectConsoleListOutputSchema = ConsoleListSchema;\n\nexport const ArtifactInfoSchema = z.object({\n artifact_id: z.string(),\n path: z.string(),\n mime: z.string(),\n});\n\nexport const InspectNetworkHarInputSchema = SessionIdSchema.extend({\n target: TargetHintSchema.optional(),\n});\nexport const InspectNetworkHarOutputSchema = ArtifactInfoSchema;\n\nexport const InspectEvaluateInputSchema = z.object({\n session_id: z.string().min(1),\n expression: z.string().min(1).optional(),\n target: TargetHintSchema.optional(),\n});\n// Evaluate output is implementation-defined; allow passthrough fields.\nexport const EvaluateResultSchema = z\n .object({\n value: z.unknown().optional(),\n exception: z.unknown().optional(),\n })\n .passthrough();\nexport const InspectEvaluateOutputSchema = EvaluateResultSchema;\n\nexport const InspectPerformanceMetricsInputSchema = SessionIdSchema.extend({\n target: TargetHintSchema.optional(),\n});\n// Performance metrics output shape may expand; allow passthrough metadata.\nexport const PerformanceMetricSchema = z\n .object({\n name: z.string(),\n value: z.number().finite(),\n })\n .passthrough();\nexport const PerformanceMetricsSchema = z\n .object({\n metrics: z.array(PerformanceMetricSchema),\n })\n .passthrough();\nexport const InspectPerformanceMetricsOutputSchema = PerformanceMetricsSchema;\n\nexport const ArtifactsScreenshotInputSchema = z.object({\n session_id: z.string().min(1),\n target: z.enum(['viewport', 'full']).default('viewport'),\n fullPage: z.boolean().default(false),\n selector: z.string().min(1).optional(),\n format: z.enum(['png', 'jpeg', 'webp']).default('png'),\n quality: z.number().min(0).max(100).optional(),\n});\nexport const ArtifactsScreenshotOutputSchema = ArtifactInfoSchema;\n\nexport const HealthCheckInputSchema = z.object({});\nexport const HealthCheckOutputSchema = z\n .object({\n started_at: z.string().min(1),\n uptime_ms: z.number().finite().nonnegative(),\n memory: z\n .object({\n rss: z.number().finite().nonnegative(),\n heapTotal: z.number().finite().nonnegative(),\n heapUsed: z.number().finite().nonnegative(),\n external: z.number().finite().nonnegative(),\n arrayBuffers: z.number().finite().nonnegative().optional(),\n })\n .passthrough(),\n sessions: z\n .object({\n active: z.number().finite().nonnegative(),\n })\n .passthrough(),\n extension: z\n .object({\n connected: z.boolean(),\n last_seen_at: z.string().min(1).optional(),\n })\n .passthrough(),\n })\n .passthrough();\n\nexport const DiagnosticsDoctorInputSchema = z.object({\n session_id: z.string().min(1).optional(),\n});\nexport const DiagnosticsDoctorOutputSchema = DiagnosticReportSchema;\n", "import {\n ErrorEnvelope,\n ErrorInfo,\n ApiEnvelope,\n} from '@btraut/browser-bridge-shared';\nimport { ZodError, z } from 'zod';\nimport { CoreClientError } from './core-client';\n\ntype OutputOptions = {\n json: boolean;\n};\n\nexport class CliError extends Error {\n readonly info: ErrorInfo;\n\n constructor(info: ErrorInfo) {\n super(info.message);\n this.info = info;\n }\n}\n\nexport const parseInput = <T>(schema: z.ZodType<T>, payload: unknown): T => {\n const result = schema.safeParse(payload);\n if (result.success) {\n return result.data;\n }\n\n const [issue] = result.error.issues;\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message: issue?.message ?? 'Invalid input.',\n retryable: false,\n details: { issues: result.error.issues },\n });\n};\n\nexport const outputEnvelope = (\n envelope: ApiEnvelope<unknown>,\n options: OutputOptions\n): void => {\n if (options.json) {\n console.log(JSON.stringify(envelope, null, 2));\n return;\n }\n\n if (envelope.ok) {\n if (typeof envelope.result === 'string') {\n console.log(envelope.result);\n return;\n }\n\n console.log(JSON.stringify(envelope.result, null, 2));\n return;\n }\n\n console.error(`${envelope.error.code}: ${envelope.error.message}`);\n if (envelope.error.details) {\n console.error(JSON.stringify(envelope.error.details, null, 2));\n }\n};\n\nconst toErrorInfo = (error: unknown): ErrorInfo => {\n if (error instanceof CliError) {\n return error.info;\n }\n\n if (error instanceof CoreClientError) {\n return error.info;\n }\n\n if (error instanceof ZodError) {\n const [issue] = error.issues;\n return {\n code: 'INVALID_ARGUMENT',\n message: issue?.message ?? 'Invalid input.',\n retryable: false,\n details: { issues: error.issues },\n };\n }\n\n if (error instanceof Error) {\n return {\n code: 'INTERNAL',\n message: error.message,\n retryable: false,\n };\n }\n\n return {\n code: 'INTERNAL',\n message: 'Unknown error.',\n retryable: false,\n };\n};\n\nexport const outputError = (error: unknown, options: OutputOptions): void => {\n const info = toErrorInfo(error);\n const envelope: ErrorEnvelope = { ok: false, error: info };\n\n if (options.json) {\n console.log(JSON.stringify(envelope, null, 2));\n return;\n }\n\n console.error(`${info.code}: ${info.message}`);\n if (info.details) {\n console.error(JSON.stringify(info.details, null, 2));\n }\n};\n", "import {\n ApiEnvelope,\n ErrorInfo,\n JsonlLogger,\n createJsonlLogger,\n resolveCoreRuntime,\n} from '@btraut/browser-bridge-shared';\nimport { spawn } from 'node:child_process';\nimport { resolve } from 'node:path';\nimport { setTimeout as delay } from 'node:timers/promises';\n\ntype FetchLike = typeof fetch;\n\ntype SpawnLike = typeof spawn;\n\nexport class CoreClientError extends Error {\n readonly info: ErrorInfo;\n\n constructor(info: ErrorInfo) {\n super(info.message);\n this.name = 'CoreClientError';\n this.info = info;\n }\n}\n\nexport type CoreClientOptions = {\n host?: string;\n port?: number | string;\n cwd?: string;\n ensureDaemon?: boolean;\n timeoutMs?: number;\n fetchImpl?: FetchLike;\n spawnImpl?: SpawnLike;\n logger?: JsonlLogger;\n};\n\nexport type CoreClient = {\n baseUrl: string;\n ensureReady: () => Promise<void>;\n post: <T>(path: string, body?: unknown) => Promise<ApiEnvelope<T>>;\n};\n\n// Must be long enough to accommodate user-approval prompts in the extension.\nconst DEFAULT_TIMEOUT_MS = 30000;\nconst HEALTH_RETRY_MS = 250;\nconst HEALTH_ATTEMPTS = 20;\n\nconst resolveTimeoutMs = (timeoutMs?: number): number => {\n const candidate =\n timeoutMs ??\n (process.env.BROWSER_BRIDGE_CORE_TIMEOUT_MS\n ? Number.parseInt(process.env.BROWSER_BRIDGE_CORE_TIMEOUT_MS, 10)\n : process.env.BROWSER_VISION_CORE_TIMEOUT_MS\n ? Number.parseInt(process.env.BROWSER_VISION_CORE_TIMEOUT_MS, 10)\n : undefined);\n\n if (candidate === undefined || candidate === null) {\n return DEFAULT_TIMEOUT_MS;\n }\n\n const parsed = typeof candidate === 'number' ? candidate : Number(candidate);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`Invalid timeoutMs: ${String(candidate)}`);\n }\n\n return Math.floor(parsed);\n};\n\nconst normalizePath = (path: string): string =>\n path.startsWith('/') ? path : `/${path}`;\n\nconst durationMs = (startedAt: bigint): number =>\n Number((Number(process.hrtime.bigint() - startedAt) / 1_000_000).toFixed(3));\n\nexport const createCoreClient = (\n options: CoreClientOptions = {}\n): CoreClient => {\n const logger =\n options.logger ??\n createJsonlLogger({\n stream: 'cli',\n cwd: options.cwd,\n }).child({ scope: 'core-client' });\n\n let runtime = resolveCoreRuntime({\n host: options.host,\n port: options.port,\n cwd: options.cwd,\n strictEnvPort: true,\n });\n let baseUrl = `http://${runtime.host}:${runtime.port}`;\n const timeoutMs = resolveTimeoutMs(options.timeoutMs);\n const fetchImpl = options.fetchImpl ?? fetch;\n const spawnImpl = options.spawnImpl ?? spawn;\n const ensureDaemon = options.ensureDaemon ?? true;\n const allowRuntimeRefresh =\n options.host === undefined &&\n options.port === undefined &&\n process.env.BROWSER_BRIDGE_CORE_HOST === undefined &&\n process.env.BROWSER_VISION_CORE_HOST === undefined &&\n process.env.BROWSER_BRIDGE_CORE_PORT === undefined &&\n process.env.BROWSER_VISION_CORE_PORT === undefined;\n\n const refreshRuntime = (): void => {\n if (!allowRuntimeRefresh) {\n return;\n }\n runtime = resolveCoreRuntime({\n cwd: options.cwd,\n strictEnvPort: true,\n });\n baseUrl = `http://${runtime.host}:${runtime.port}`;\n };\n\n const requestJson = async <T>(\n method: 'GET' | 'POST',\n path: string,\n body?: unknown\n ): Promise<T> => {\n const requestPath = normalizePath(path);\n const startedAt = process.hrtime.bigint();\n logger.debug('cli.core.request.start', {\n method,\n path: requestPath,\n base_url: baseUrl,\n });\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n let response: Response;\n try {\n response = await fetchImpl(`${baseUrl}${requestPath}`, {\n method,\n headers: {\n 'content-type': 'application/json',\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (error) {\n if (\n controller.signal.aborted ||\n (error instanceof Error && error.name === 'AbortError')\n ) {\n logger.warn('cli.core.request.timeout', {\n method,\n path: requestPath,\n base_url: baseUrl,\n timeout_ms: timeoutMs,\n duration_ms: durationMs(startedAt),\n });\n throw new CoreClientError({\n code: 'TIMEOUT',\n message: `Core request timed out after ${timeoutMs}ms.`,\n retryable: true,\n details: {\n timeout_ms: timeoutMs,\n base_url: baseUrl,\n path: requestPath,\n },\n });\n }\n logger.error('cli.core.request.failed', {\n method,\n path: requestPath,\n base_url: baseUrl,\n duration_ms: durationMs(startedAt),\n error,\n });\n throw error;\n }\n\n const raw = await response.text();\n if (!raw) {\n logger.warn('cli.core.request.empty_response', {\n method,\n path: requestPath,\n base_url: baseUrl,\n status: response.status,\n duration_ms: durationMs(startedAt),\n });\n throw new Error(`Empty response from Core (${response.status}).`);\n }\n\n try {\n const parsed = JSON.parse(raw) as T;\n logger.debug('cli.core.request.end', {\n method,\n path: requestPath,\n base_url: baseUrl,\n status: response.status,\n duration_ms: durationMs(startedAt),\n });\n return parsed;\n } catch (error) {\n const message =\n error instanceof Error ? error.message : 'Unknown JSON parse error';\n logger.error('cli.core.request.invalid_json', {\n method,\n path: requestPath,\n base_url: baseUrl,\n status: response.status,\n duration_ms: durationMs(startedAt),\n error,\n });\n throw new Error(`Failed to parse Core response: ${message}`);\n }\n } finally {\n clearTimeout(timeout);\n }\n };\n\n const checkHealth = async (): Promise<boolean> => {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n let response: Response;\n try {\n response = await fetchImpl(`${baseUrl}/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n } catch (error) {\n if (\n controller.signal.aborted ||\n (error instanceof Error && error.name === 'AbortError')\n ) {\n logger.warn('cli.core.health.timeout', {\n base_url: baseUrl,\n timeout_ms: timeoutMs,\n });\n return false;\n }\n logger.warn('cli.core.health.fetch_failed', {\n base_url: baseUrl,\n error,\n });\n throw error;\n }\n if (!response.ok) {\n logger.warn('cli.core.health.non_ok', {\n base_url: baseUrl,\n status: response.status,\n });\n return false;\n }\n const data = (await response.json().catch(() => null)) as {\n ok?: boolean;\n } | null;\n const ok = Boolean(data?.ok);\n if (!ok) {\n logger.warn('cli.core.health.not_ready', {\n base_url: baseUrl,\n });\n }\n return ok;\n } finally {\n clearTimeout(timeout);\n }\n } catch (error) {\n logger.warn('cli.core.health.error', {\n base_url: baseUrl,\n error,\n });\n return false;\n }\n };\n\n const spawnDaemon = (): void => {\n const coreEntry = resolve(__dirname, 'api.js');\n const startOptions: string[] = [];\n if (runtime.hostSource === 'option' || runtime.hostSource === 'env') {\n startOptions.push(`host: ${JSON.stringify(runtime.host)}`);\n }\n if (runtime.portSource === 'option' || runtime.portSource === 'env') {\n startOptions.push(`port: ${runtime.port}`);\n }\n const script = `const { startCoreServer } = require(${JSON.stringify(\n coreEntry\n )});\\nstartCoreServer({ ${startOptions.join(\n ', '\n )} })\\n .catch((err) => { console.error(err); process.exit(1); });`;\n\n logger.info('cli.core.spawn.start', {\n host: runtime.host,\n port: runtime.port,\n host_source: runtime.hostSource,\n port_source: runtime.portSource,\n });\n\n const child = spawnImpl(process.execPath, ['-e', script], {\n detached: true,\n stdio: 'ignore',\n env: { ...process.env },\n });\n\n child.on('error', (error) => {\n logger.error('cli.core.spawn.error', {\n host: runtime.host,\n port: runtime.port,\n error,\n });\n });\n\n child.unref();\n };\n\n const ensureCoreRunning = async (): Promise<void> => {\n refreshRuntime();\n if (await checkHealth()) {\n logger.debug('cli.core.ensure_ready.already_running', {\n base_url: baseUrl,\n });\n return;\n }\n\n spawnDaemon();\n\n for (let attempt = 0; attempt < HEALTH_ATTEMPTS; attempt += 1) {\n await delay(HEALTH_RETRY_MS);\n refreshRuntime();\n if (await checkHealth()) {\n logger.info('cli.core.ensure_ready.ready', {\n base_url: baseUrl,\n attempts: attempt + 1,\n });\n return;\n }\n }\n\n logger.error('cli.core.ensure_ready.failed', {\n host: runtime.host,\n port: runtime.port,\n attempts: HEALTH_ATTEMPTS,\n });\n throw new Error(\n `Core daemon failed to start on ${runtime.host}:${runtime.port}.`\n );\n };\n\n let ensurePromise: Promise<void> | null = null;\n const ensureReady = async (): Promise<void> => {\n if (!ensureDaemon) {\n return;\n }\n if (!ensurePromise) {\n ensurePromise = ensureCoreRunning();\n }\n await ensurePromise;\n };\n\n const post = async <T>(\n path: string,\n body?: unknown\n ): Promise<ApiEnvelope<T>> => {\n await ensureReady();\n refreshRuntime();\n return requestJson<ApiEnvelope<T>>('POST', path, body);\n };\n\n return {\n get baseUrl() {\n return baseUrl;\n },\n ensureReady,\n post,\n };\n};\n", "import { Command } from 'commander';\nimport {\n ApiEnvelope,\n JsonlLogger,\n createJsonlLogger,\n} from '@btraut/browser-bridge-shared';\nimport { createCoreClient, CoreClient } from './core-client';\nimport { outputEnvelope, outputError } from './cli-output';\n\ntype GlobalOptions = {\n host?: string;\n port?: number | string;\n json?: boolean;\n daemon?: boolean;\n};\n\nconst getRootCommand = (command: Command): Command => {\n let current: Command = command;\n while (current.parent) {\n current = current.parent;\n }\n return current;\n};\n\nexport const getGlobalOptions = (command: Command): GlobalOptions => {\n const root = getRootCommand(command);\n return root.opts<GlobalOptions>();\n};\n\nconst durationMs = (startedAt: bigint): number =>\n Number((Number(process.hrtime.bigint() - startedAt) / 1_000_000).toFixed(3));\n\nconst commandLabel = (command: Command): string => {\n const pieces = command\n .name()\n .split(' ')\n .filter((piece) => piece.length > 0);\n return pieces.length > 0 ? pieces.join('.') : 'unknown';\n};\n\nconst createCliLogger = (command: Command): JsonlLogger =>\n createJsonlLogger({ stream: 'cli' }).child({\n scope: 'cli-runtime',\n command: commandLabel(command),\n });\n\nexport const createClientFromCommand = (\n command: Command,\n logger?: JsonlLogger\n): CoreClient => {\n const options = getGlobalOptions(command);\n return createCoreClient({\n host: options.host,\n port: options.port,\n ensureDaemon: options.daemon !== false,\n logger: logger?.child({ scope: 'core-client' }),\n });\n};\n\nexport const runCommand = async <T>(\n command: Command,\n work: (client: CoreClient, options: GlobalOptions) => Promise<ApiEnvelope<T>>\n): Promise<void> => {\n const options = getGlobalOptions(command);\n const logger = createCliLogger(command);\n const startedAt = process.hrtime.bigint();\n logger.info('cli.command.start', {\n host: options.host ?? null,\n port: options.port ?? null,\n daemon: options.daemon !== false,\n json: Boolean(options.json),\n });\n const client = createClientFromCommand(command, logger);\n\n try {\n const envelope = await work(client, options);\n outputEnvelope(envelope, { json: Boolean(options.json) });\n logger.info('cli.command.end', {\n ok: envelope.ok,\n duration_ms: durationMs(startedAt),\n });\n if (!envelope.ok) {\n process.exitCode = 1;\n }\n } catch (error) {\n logger.error('cli.command.error', {\n duration_ms: durationMs(startedAt),\n error,\n });\n outputError(error, { json: Boolean(options.json) });\n process.exitCode = 1;\n }\n};\n\nexport const runLocal = async (\n command: Command,\n work: (options: GlobalOptions) => Promise<ApiEnvelope<unknown>>\n): Promise<void> => {\n const options = getGlobalOptions(command);\n const logger = createCliLogger(command).child({ mode: 'local' });\n const startedAt = process.hrtime.bigint();\n logger.info('cli.command.start', {\n json: Boolean(options.json),\n });\n\n try {\n const envelope = await work(options);\n outputEnvelope(envelope, { json: Boolean(options.json) });\n logger.info('cli.command.end', {\n ok: envelope.ok,\n duration_ms: durationMs(startedAt),\n });\n if (!envelope.ok) {\n process.exitCode = 1;\n }\n } catch (error) {\n logger.error('cli.command.error', {\n duration_ms: durationMs(startedAt),\n error,\n });\n outputError(error, { json: Boolean(options.json) });\n process.exitCode = 1;\n }\n};\n", "import { Command } from 'commander';\nimport { ArtifactsScreenshotInputSchema } from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nconst parseNumber = (value: unknown): number | undefined => {\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n};\n\nexport const registerArtifactsCommands = (program: Command): void => {\n const artifacts = program\n .command('artifacts')\n .description('Artifact commands');\n\n artifacts\n .command('screenshot')\n .description('Request a screenshot artifact')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--target <target>', 'Screenshot target (viewport, full)')\n .option('--full-page', 'Capture full page (alias for --target full)')\n .option(\n '--selector <selector>',\n 'Capture a specific element by CSS selector'\n )\n .option('--format <format>', 'Screenshot format (png, jpeg, webp)')\n .option('--quality <quality>', 'Screenshot quality (0-100) for jpeg/webp')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(ArtifactsScreenshotInputSchema, {\n session_id: options.sessionId,\n target: options.target,\n fullPage: Boolean(options.fullPage),\n selector: options.selector,\n format: options.format,\n quality: parseNumber(options.quality),\n });\n return client.post('/artifacts/screenshot', payload);\n });\n });\n};\n", "import { Command } from 'commander';\nimport {\n DialogAcceptInputSchema,\n DialogDismissInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nconst parseNumber = (value: unknown): number | undefined => {\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n};\n\nexport const registerDialogCommands = (program: Command): void => {\n const dialog = program.command('dialog').description('Dialog commands');\n\n dialog\n .command('accept')\n .description('Accept a JavaScript dialog')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--prompt-text <text>', 'Prompt text for prompt() dialogs')\n .option('--tab-id <id>', 'Tab identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DialogAcceptInputSchema, {\n session_id: options.sessionId,\n promptText: options.promptText,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/dialog/accept', payload);\n });\n });\n\n dialog\n .command('dismiss')\n .description('Dismiss a JavaScript dialog')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DialogDismissInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/dialog/dismiss', payload);\n });\n });\n};\n", "import { Command } from 'commander';\nimport {\n DiagnosticsDoctorInputSchema,\n HealthCheckInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nexport const registerDiagnosticsCommands = (program: Command): void => {\n const diagnostics = program\n .command('diagnostics')\n .description('Diagnostics commands');\n\n diagnostics\n .command('doctor')\n .description('Run diagnostics')\n .option('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DiagnosticsDoctorInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/diagnostics/doctor', payload);\n });\n });\n\n diagnostics\n .command('health-check')\n .description('Run a lightweight health check')\n .action(async (_options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(HealthCheckInputSchema, {});\n return client.post('/health_check', payload);\n });\n });\n};\n", "import { spawn } from 'node:child_process';\n\nexport const openPath = async (target: string): Promise<void> => {\n const platform = process.platform;\n\n if (platform === 'darwin') {\n const child = spawn('open', [target], { detached: true, stdio: 'ignore' });\n child.unref();\n return;\n }\n\n if (platform === 'win32') {\n const child = spawn('cmd', ['/c', 'start', '', target], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n return;\n }\n\n const child = spawn('xdg-open', [target], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n};\n", "import { Command } from 'commander';\nimport {\n resolveCoreRuntime,\n resolveLogDirectory,\n writeRuntimeMetadata,\n type ResolvedCoreRuntime,\n type RuntimeMetadata,\n} from '@btraut/browser-bridge-shared';\nimport { CliError } from '../cli-output';\nimport { runLocal } from '../cli-runtime';\nimport { openPath } from '../open-path';\n\nconst ENV_EXTENSION_ID = 'BROWSER_BRIDGE_EXTENSION_ID';\nconst ACTIVATION_FLAG_PARAM = 'bb_activate';\nconst ACTIVATION_PORT_PARAM = 'corePort';\nconst ACTIVATION_WORKTREE_PARAM = 'worktreeId';\n\ntype ExtensionIdSource = 'flag' | 'env' | 'metadata';\n\ntype ResolvedExtensionId = {\n extensionId: string;\n source: ExtensionIdSource;\n};\n\nconst normalizeToken = (value: unknown): string | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\nexport const resolveActivationExtensionId = (options: {\n optionExtensionId?: string;\n envExtensionId?: string;\n metadataExtensionId?: string;\n}): ResolvedExtensionId | null => {\n const optionId = normalizeToken(options.optionExtensionId);\n if (optionId) {\n return { extensionId: optionId, source: 'flag' };\n }\n\n const envId = normalizeToken(options.envExtensionId);\n if (envId) {\n return { extensionId: envId, source: 'env' };\n }\n\n const metadataId = normalizeToken(options.metadataExtensionId);\n if (metadataId) {\n return { extensionId: metadataId, source: 'metadata' };\n }\n\n return null;\n};\n\nexport const buildActivationOptionsUrl = (options: {\n extensionId: string;\n corePort: number;\n worktreeId: string | null;\n}): string => {\n const search = new URLSearchParams();\n search.set(ACTIVATION_FLAG_PARAM, '1');\n search.set(ACTIVATION_PORT_PARAM, String(options.corePort));\n if (options.worktreeId) {\n search.set(ACTIVATION_WORKTREE_PARAM, options.worktreeId);\n }\n return `chrome-extension://${options.extensionId}/options.html?${search.toString()}`;\n};\n\nconst buildPersistedRuntimeMetadata = (\n runtime: ResolvedCoreRuntime,\n extensionId: string\n): RuntimeMetadata => ({\n host: runtime.host,\n port: runtime.port,\n git_root: runtime.gitRoot ?? runtime.metadata?.git_root,\n worktree_id: runtime.worktreeId ?? runtime.metadata?.worktree_id,\n extension_id: extensionId,\n updated_at: new Date().toISOString(),\n});\n\nconst resolveRuntimeForCommand = (options: {\n host?: string;\n port?: number | string;\n}): ResolvedCoreRuntime =>\n resolveCoreRuntime({\n host: options.host,\n port: options.port,\n strictEnvPort: true,\n });\n\nexport const registerDevCommands = (program: Command): void => {\n const dev = program.command('dev').description('Development commands');\n\n dev\n .command('info')\n .description('Print resolved runtime details for the current worktree')\n .action(async (_options, command: Command) => {\n await runLocal(command, async (globalOptions) => {\n const runtime = resolveRuntimeForCommand(globalOptions);\n const logDir = resolveLogDirectory({ gitRoot: runtime.gitRoot });\n return {\n ok: true,\n result: {\n host: runtime.host,\n hostSource: runtime.hostSource,\n port: runtime.port,\n portSource: runtime.portSource,\n deterministicPort: runtime.deterministicPort,\n worktreeId: runtime.worktreeId,\n metadataPath: runtime.metadataPath,\n logDir,\n metadataSnapshot: runtime.metadata,\n },\n };\n });\n });\n\n dev\n .command('activate')\n .description(\n 'Persist worktree runtime metadata and open extension options for activation'\n )\n .option(\n '--extension-id <id>',\n 'Chrome extension id to activate for this worktree'\n )\n .action(async (options: { extensionId?: string }, command: Command) => {\n await runLocal(command, async (globalOptions) => {\n const runtime = resolveRuntimeForCommand(globalOptions);\n const extension = resolveActivationExtensionId({\n optionExtensionId: options.extensionId,\n envExtensionId: process.env[ENV_EXTENSION_ID],\n metadataExtensionId: runtime.metadata?.extension_id,\n });\n\n if (!extension) {\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message:\n 'Missing extension id. Provide --extension-id <id>, set BROWSER_BRIDGE_EXTENSION_ID, or persist extension_id in metadata by running dev activate with --extension-id once.',\n retryable: false,\n details: {\n metadataPath: runtime.metadataPath,\n },\n });\n }\n\n const metadataPath = writeRuntimeMetadata(\n buildPersistedRuntimeMetadata(runtime, extension.extensionId),\n { metadataPath: runtime.metadataPath }\n );\n const activationUrl = buildActivationOptionsUrl({\n extensionId: extension.extensionId,\n corePort: runtime.port,\n worktreeId: runtime.worktreeId,\n });\n\n await openPath(activationUrl);\n\n return {\n ok: true,\n result: {\n extensionId: extension.extensionId,\n extensionIdSource: extension.source,\n host: runtime.host,\n port: runtime.port,\n metadataPath,\n activationUrl,\n },\n };\n });\n });\n};\n", "import { CliError } from './cli-output';\n\ntype LocatorRoleInput = {\n name: string;\n value?: string;\n};\n\nexport type LocatorInput = {\n ref?: string;\n testid?: string;\n css?: string;\n text?: string;\n role?: LocatorRoleInput;\n};\n\ntype LocatorOptions = {\n locatorRef?: string;\n locatorTestid?: string;\n locatorCss?: string;\n locatorText?: string;\n locatorRole?: string;\n locatorRoleValue?: string;\n};\n\nexport const buildLocator = (\n options: LocatorOptions\n): LocatorInput | undefined => {\n const locator: LocatorInput = {};\n\n if (options.locatorRef) {\n locator.ref = options.locatorRef;\n }\n\n if (options.locatorTestid) {\n locator.testid = options.locatorTestid;\n }\n\n if (options.locatorCss) {\n locator.css = options.locatorCss;\n }\n\n if (options.locatorText) {\n locator.text = options.locatorText;\n }\n\n if (options.locatorRoleValue && !options.locatorRole) {\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message: 'locator-role-value requires locator-role to be set.',\n retryable: false,\n details: { field: 'locator.role.value' },\n });\n }\n\n if (options.locatorRole) {\n locator.role = {\n name: options.locatorRole,\n ...(options.locatorRoleValue ? { value: options.locatorRoleValue } : {}),\n };\n }\n\n if (\n !locator.ref &&\n !locator.testid &&\n !locator.css &&\n !locator.text &&\n !locator.role\n ) {\n return undefined;\n }\n\n return locator;\n};\n\nexport const requireLocator = (options: LocatorOptions): LocatorInput => {\n const locator = buildLocator(options);\n if (!locator) {\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message: 'Locator must include at least one selector.',\n retryable: false,\n details: { field: 'locator' },\n });\n }\n return locator;\n};\n", "import { Command } from 'commander';\nimport {\n DriveClickInputSchema,\n DriveDragInputSchema,\n DriveFillFormInputSchema,\n DriveBackInputSchema,\n DriveForwardInputSchema,\n DriveGoBackInputSchema,\n DriveGoForwardInputSchema,\n DriveHandleDialogInputSchema,\n DriveHoverInputSchema,\n DriveSelectInputSchema,\n DriveKeyInputSchema,\n DriveKeyPressInputSchema,\n DriveNavigateInputSchema,\n DriveScrollInputSchema,\n DriveTabActivateInputSchema,\n DriveTabCloseInputSchema,\n DriveTabListInputSchema,\n DriveTypeInputSchema,\n DriveWaitForInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\nimport { buildLocator, requireLocator } from '../locator';\n\nconst parseNumber = (value: unknown): number | undefined => {\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n};\n\nconst parseJson = (value: string, label: string): unknown => {\n try {\n return JSON.parse(value);\n } catch {\n throw new Error(`${label} must be valid JSON.`);\n }\n};\n\nexport const registerDriveCommands = (program: Command): void => {\n const drive = program.command('drive').description('Drive commands');\n\n drive\n .command('navigate')\n .description('Navigate to a URL')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--url <url>', 'URL to navigate to')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--wait <mode>', 'Wait mode (none, domcontentloaded)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveNavigateInputSchema, {\n session_id: options.sessionId,\n url: options.url,\n tab_id: parseNumber(options.tabId),\n wait: options.wait,\n });\n return client.post('/drive/navigate', payload);\n });\n });\n\n drive\n .command('go-back')\n .description('Go back in browser history')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveGoBackInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/go_back', payload);\n });\n });\n\n drive\n .command('back')\n .description('Go back in browser history')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveBackInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/back', payload);\n });\n });\n\n drive\n .command('go-forward')\n .description('Go forward in browser history')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveGoForwardInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/go_forward', payload);\n });\n });\n\n drive\n .command('forward')\n .description('Go forward in browser history')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveForwardInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/forward', payload);\n });\n });\n\n drive\n .command('click')\n .description('Click an element')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--locator-ref <ref>', 'Locator ref (e.g., @e1)')\n .option('--locator-testid <id>', 'Locator test id')\n .option('--locator-css <selector>', 'Locator CSS selector')\n .option('--locator-text <text>', 'Locator text')\n .option('--locator-role <role>', 'Locator role name')\n .option('--locator-role-value <value>', 'Locator role value')\n .option('--click-count <count>', 'Click count')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const locator = requireLocator({\n locatorRef: options.locatorRef,\n locatorTestid: options.locatorTestid,\n locatorCss: options.locatorCss,\n locatorText: options.locatorText,\n locatorRole: options.locatorRole,\n locatorRoleValue: options.locatorRoleValue,\n });\n const payload = parseInput(DriveClickInputSchema, {\n session_id: options.sessionId,\n locator,\n tab_id: parseNumber(options.tabId),\n click_count: parseNumber(options.clickCount),\n });\n return client.post('/drive/click', payload);\n });\n });\n\n drive\n .command('hover')\n .description('Hover over an element')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--locator-ref <ref>', 'Locator ref (e.g., @e1)')\n .option('--locator-testid <id>', 'Locator test id')\n .option('--locator-css <selector>', 'Locator CSS selector')\n .option('--locator-text <text>', 'Locator text')\n .option('--locator-role <role>', 'Locator role name')\n .option('--locator-role-value <value>', 'Locator role value')\n .option('--delay-ms <ms>', 'Delay after hover in milliseconds')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const locator = requireLocator({\n locatorRef: options.locatorRef,\n locatorTestid: options.locatorTestid,\n locatorCss: options.locatorCss,\n locatorText: options.locatorText,\n locatorRole: options.locatorRole,\n locatorRoleValue: options.locatorRoleValue,\n });\n const payload = parseInput(DriveHoverInputSchema, {\n session_id: options.sessionId,\n locator,\n delay_ms: parseNumber(options.delayMs),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/hover', payload);\n });\n });\n\n drive\n .command('select')\n .description('Select an option in a dropdown')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--locator-ref <ref>', 'Locator ref (e.g., @e1)')\n .option('--locator-testid <id>', 'Locator test id')\n .option('--locator-css <selector>', 'Locator CSS selector')\n .option('--locator-text <text>', 'Locator text')\n .option('--locator-role <role>', 'Locator role name')\n .option('--locator-role-value <value>', 'Locator role value')\n .option('--value <value>', 'Option value attribute')\n .option('--text <text>', 'Option visible text')\n .option('--index <index>', 'Option index (0-based)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const locator = requireLocator({\n locatorRef: options.locatorRef,\n locatorTestid: options.locatorTestid,\n locatorCss: options.locatorCss,\n locatorText: options.locatorText,\n locatorRole: options.locatorRole,\n locatorRoleValue: options.locatorRoleValue,\n });\n const payload = parseInput(DriveSelectInputSchema, {\n session_id: options.sessionId,\n locator,\n value: options.value,\n text: options.text,\n index: parseNumber(options.index),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/select', payload);\n });\n });\n\n drive\n .command('type')\n .description('Type into a field')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--text <text>', 'Text to enter')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .option('--locator-ref <ref>', 'Locator ref (e.g., @e1)')\n .option('--locator-testid <id>', 'Locator test id')\n .option('--locator-css <selector>', 'Locator CSS selector')\n .option('--locator-text <text>', 'Locator text')\n .option('--locator-role <role>', 'Locator role name')\n .option('--locator-role-value <value>', 'Locator role value')\n .option('--clear', 'Clear input before typing')\n .option('--submit', 'Submit after typing')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const locator = buildLocator({\n locatorRef: options.locatorRef,\n locatorTestid: options.locatorTestid,\n locatorCss: options.locatorCss,\n locatorText: options.locatorText,\n locatorRole: options.locatorRole,\n locatorRoleValue: options.locatorRoleValue,\n });\n const payload = parseInput(DriveTypeInputSchema, {\n session_id: options.sessionId,\n locator,\n text: options.text,\n tab_id: parseNumber(options.tabId),\n clear: Boolean(options.clear),\n submit: Boolean(options.submit),\n });\n return client.post('/drive/type', payload);\n });\n });\n\n drive\n .command('fill-form')\n .description('Fill multiple form fields')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--fields <json>', 'JSON array of fields to fill')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const fields = parseJson(options.fields, 'fields');\n const payload = parseInput(DriveFillFormInputSchema, {\n session_id: options.sessionId,\n fields,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/fill_form', payload);\n });\n });\n\n drive\n .command('drag')\n .description('Drag an element to a target')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--from-locator-ref <ref>', 'Source locator ref (e.g., @e1)')\n .option('--from-locator-testid <id>', 'Source locator test id')\n .option('--from-locator-css <selector>', 'Source locator CSS selector')\n .option('--from-locator-text <text>', 'Source locator text')\n .option('--from-locator-role <role>', 'Source locator role name')\n .option('--from-locator-role-value <value>', 'Source locator role value')\n .option('--to-locator-ref <ref>', 'Target locator ref (e.g., @e1)')\n .option('--to-locator-testid <id>', 'Target locator test id')\n .option('--to-locator-css <selector>', 'Target locator CSS selector')\n .option('--to-locator-text <text>', 'Target locator text')\n .option('--to-locator-role <role>', 'Target locator role name')\n .option('--to-locator-role-value <value>', 'Target locator role value')\n .option('--steps <steps>', 'Number of drag steps')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const from = requireLocator({\n locatorRef: options.fromLocatorRef,\n locatorTestid: options.fromLocatorTestid,\n locatorCss: options.fromLocatorCss,\n locatorText: options.fromLocatorText,\n locatorRole: options.fromLocatorRole,\n locatorRoleValue: options.fromLocatorRoleValue,\n });\n const to = requireLocator({\n locatorRef: options.toLocatorRef,\n locatorTestid: options.toLocatorTestid,\n locatorCss: options.toLocatorCss,\n locatorText: options.toLocatorText,\n locatorRole: options.toLocatorRole,\n locatorRoleValue: options.toLocatorRoleValue,\n });\n const payload = parseInput(DriveDragInputSchema, {\n session_id: options.sessionId,\n from,\n to,\n steps: parseNumber(options.steps),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/drag', payload);\n });\n });\n\n drive\n .command('handle-dialog')\n .description('Handle a JavaScript dialog')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--action <action>', 'Dialog action (accept, dismiss)')\n .option('--prompt-text <text>', 'Prompt text for prompt() dialogs')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveHandleDialogInputSchema, {\n session_id: options.sessionId,\n action: options.action,\n promptText: options.promptText,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/handle_dialog', payload);\n });\n });\n\n drive\n .command('key-press')\n .description('Press a keyboard key')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--key <key>', 'Key to press (e.g. Enter, ArrowDown)')\n .option('--ctrl', 'Hold control modifier')\n .option('--alt', 'Hold alt modifier')\n .option('--shift', 'Hold shift modifier')\n .option('--meta', 'Hold meta modifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveKeyPressInputSchema, {\n session_id: options.sessionId,\n key: options.key,\n modifiers: {\n ctrl: Boolean(options.ctrl),\n alt: Boolean(options.alt),\n shift: Boolean(options.shift),\n meta: Boolean(options.meta),\n },\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/key_press', payload);\n });\n });\n\n drive\n .command('key')\n .description('Press a keyboard key with modifiers')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--key <key>', 'Key to press (e.g. Enter, ArrowDown)')\n .option(\n '--modifier <modifier>',\n 'Modifier key (ctrl, alt, shift, meta)',\n (value: string, previous: string[]) => [...(previous ?? []), value],\n []\n )\n .option('--repeat <count>', 'Number of times to press')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveKeyInputSchema, {\n session_id: options.sessionId,\n key: options.key,\n modifiers: options.modifier,\n repeat: parseNumber(options.repeat),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/key', payload);\n });\n });\n\n drive\n .command('scroll')\n .description('Scroll the page')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--delta-x <px>', 'Scroll delta X')\n .option('--delta-y <px>', 'Scroll delta Y')\n .option('--top <px>', 'Scroll top position')\n .option('--left <px>', 'Scroll left position')\n .option('--behavior <mode>', 'Scroll behavior (auto, smooth)')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveScrollInputSchema, {\n session_id: options.sessionId,\n delta_x: parseNumber(options.deltaX),\n delta_y: parseNumber(options.deltaY),\n top: parseNumber(options.top),\n left: parseNumber(options.left),\n behavior: options.behavior,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/scroll', payload);\n });\n });\n\n drive\n .command('wait-for')\n .description('Wait for a condition')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--tab-id <id>', 'Tab identifier (defaults to agent window/tab)')\n .requiredOption(\n '--kind <kind>',\n 'Condition kind (locator_visible, text_present, url_matches)'\n )\n .requiredOption('--value <value>', 'Condition value')\n .option('--timeout-ms <ms>', 'Timeout in milliseconds')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveWaitForInputSchema, {\n session_id: options.sessionId,\n condition: {\n kind: options.kind,\n value: options.value,\n },\n timeout_ms: parseNumber(options.timeoutMs),\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/wait_for', payload);\n });\n });\n\n drive\n .command('tab-list')\n .description('List browser tabs')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveTabListInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/drive/tab_list', payload);\n });\n });\n\n drive\n .command('tab-activate')\n .description('Activate a tab')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--tab-id <id>', 'Tab identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveTabActivateInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/tab_activate', payload);\n });\n });\n\n drive\n .command('tab-close')\n .description('Close a tab')\n .requiredOption('--session-id <id>', 'Session identifier')\n .requiredOption('--tab-id <id>', 'Tab identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(DriveTabCloseInputSchema, {\n session_id: options.sessionId,\n tab_id: parseNumber(options.tabId),\n });\n return client.post('/drive/tab_close', payload);\n });\n });\n};\n", "import { Command } from 'commander';\nimport {\n InspectConsoleListInputSchema,\n InspectDomDiffInputSchema,\n InspectDomSnapshotInputSchema,\n InspectExtractContentInputSchema,\n InspectEvaluateInputSchema,\n InspectFindInputSchema,\n InspectNetworkHarInputSchema,\n InspectPageStateInputSchema,\n InspectPerformanceMetricsInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { CliError, parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nexport const registerInspectCommands = (program: Command): void => {\n const inspect = program.command('inspect').description('Inspect commands');\n\n inspect\n .command('dom-snapshot')\n .description('Fetch a DOM snapshot')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--format <format>', 'Snapshot format (ax, html)')\n .option('--consistency <mode>', 'Consistency mode (best_effort, quiesce)')\n .option('-i, --interactive', 'Only include interactive elements')\n .option('-c, --compact', 'Remove empty/decorative nodes')\n .option('--max-nodes <n>', 'Limit AX snapshot to at most n nodes')\n .option('-s, --selector <selector>', 'Limit snapshot to selector')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectDomSnapshotInputSchema, {\n session_id: options.sessionId,\n format: options.format,\n consistency: options.consistency,\n interactive: options.interactive,\n compact: options.compact,\n max_nodes: options.maxNodes,\n selector: options.selector,\n });\n return client.post('/inspect/dom_snapshot', payload);\n });\n });\n\n inspect\n .command('dom-diff')\n .description('Compare recent DOM snapshots')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectDomDiffInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/dom_diff', payload);\n });\n });\n\n inspect\n .command('find')\n .description('Find elements and return refs')\n .requiredOption('--session-id <id>', 'Session identifier')\n .argument('<kind>', 'Find kind (role, text, label)')\n .argument('<value>', 'Role name or text to match')\n .option('--name <name>', 'Accessible name to match (role only)')\n .action(async (kind, value, options, command) => {\n await runCommand(command, (client) => {\n const normalizedKind = String(kind ?? '').toLowerCase();\n let payload: unknown;\n if (normalizedKind === 'role') {\n payload = {\n session_id: options.sessionId,\n kind: 'role',\n role: value,\n name: options.name,\n };\n } else if (normalizedKind === 'text') {\n payload = {\n session_id: options.sessionId,\n kind: 'text',\n text: value,\n };\n } else if (normalizedKind === 'label') {\n payload = {\n session_id: options.sessionId,\n kind: 'label',\n label: value,\n };\n } else {\n throw new CliError({\n code: 'INVALID_ARGUMENT',\n message: 'kind must be role, text, or label.',\n retryable: false,\n details: { field: 'kind' },\n });\n }\n const parsed = parseInput(InspectFindInputSchema, payload);\n return client.post('/inspect/find', parsed);\n });\n });\n\n inspect\n .command('extract-content')\n .description('Extract main content from the page')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--format <format>', 'Output format (markdown, text, article_json)')\n .option('--include-metadata', 'Include article metadata')\n .option('--no-include-metadata', 'Exclude article metadata')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectExtractContentInputSchema, {\n session_id: options.sessionId,\n format: options.format,\n include_metadata: options.includeMetadata,\n });\n return client.post('/inspect/extract_content', payload);\n });\n });\n\n inspect\n .command('page-state')\n .description('Capture form, storage, and cookie state')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectPageStateInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/page_state', payload);\n });\n });\n\n inspect\n .command('console-list')\n .description('Fetch console entries')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectConsoleListInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/console_list', payload);\n });\n });\n\n inspect\n .command('network-har')\n .description('Fetch network HAR')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectNetworkHarInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/network_har', payload);\n });\n });\n\n inspect\n .command('evaluate')\n .description('Evaluate a JavaScript expression')\n .requiredOption('--session-id <id>', 'Session identifier')\n .option('--expression <expr>', 'Expression to evaluate')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectEvaluateInputSchema, {\n session_id: options.sessionId,\n expression: options.expression,\n });\n return client.post('/inspect/evaluate', payload);\n });\n });\n\n inspect\n .command('performance-metrics')\n .description('Fetch performance metrics')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(InspectPerformanceMetricsInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/inspect/performance_metrics', payload);\n });\n });\n};\n", "import {\n ApiEnvelope,\n JsonlLogger,\n createJsonlLogger,\n resolveCoreRuntime,\n} from '@btraut/browser-bridge-shared';\n\ntype FetchLike = typeof fetch;\n\nexport type CoreClientOptions = {\n host?: string;\n port?: number | string;\n cwd?: string;\n timeoutMs?: number;\n fetchImpl?: FetchLike;\n logger?: JsonlLogger;\n};\n\nexport type CoreClient = {\n baseUrl: string;\n post: <T>(path: string, body?: unknown) => Promise<ApiEnvelope<T>>;\n};\n\n// Must be long enough to accommodate user-approval prompts in the extension.\nconst DEFAULT_TIMEOUT_MS = 30000;\n\nconst normalizePath = (path: string): string =>\n path.startsWith('/') ? path : `/${path}`;\n\nconst durationMs = (startedAt: bigint): number =>\n Number((Number(process.hrtime.bigint() - startedAt) / 1_000_000).toFixed(3));\n\nexport const createCoreClient = (\n options: CoreClientOptions = {}\n): CoreClient => {\n const logger =\n options.logger ??\n createJsonlLogger({\n stream: 'mcp-adapter',\n cwd: options.cwd,\n }).child({ scope: 'core-client' });\n\n const runtime = resolveCoreRuntime({\n host: options.host,\n port: options.port,\n cwd: options.cwd,\n strictEnvPort: true,\n });\n const host = runtime.host;\n const port = runtime.port;\n const baseUrl = `http://${host}:${port}`;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const fetchImpl = options.fetchImpl ?? fetch;\n\n const requestJson = async <T>(path: string, body?: unknown): Promise<T> => {\n const requestPath = normalizePath(path);\n const startedAt = process.hrtime.bigint();\n logger.debug('mcp.core.request.start', {\n path: requestPath,\n base_url: baseUrl,\n });\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetchImpl(`${baseUrl}${requestPath}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller.signal,\n });\n\n const raw = await response.text();\n if (!raw) {\n logger.warn('mcp.core.request.empty_response', {\n path: requestPath,\n base_url: baseUrl,\n status: response.status,\n duration_ms: durationMs(startedAt),\n });\n throw new Error(`Empty response from Core (${response.status}).`);\n }\n\n try {\n const parsed = JSON.parse(raw) as T;\n logger.debug('mcp.core.request.end', {\n path: requestPath,\n base_url: baseUrl,\n status: response.status,\n duration_ms: durationMs(startedAt),\n });\n return parsed;\n } catch (error) {\n const message =\n error instanceof Error ? error.message : 'Unknown JSON parse error';\n logger.error('mcp.core.request.invalid_json', {\n path: requestPath,\n base_url: baseUrl,\n status: response.status,\n duration_ms: durationMs(startedAt),\n error,\n });\n throw new Error(`Failed to parse Core response: ${message}`);\n }\n } catch (error) {\n logger.error('mcp.core.request.failed', {\n path: requestPath,\n base_url: baseUrl,\n duration_ms: durationMs(startedAt),\n error,\n });\n throw error;\n } finally {\n clearTimeout(timeout);\n }\n };\n\n const post = async <T>(\n path: string,\n body?: unknown\n ): Promise<ApiEnvelope<T>> => {\n return requestJson<ApiEnvelope<T>>(path, body);\n };\n\n return { baseUrl, post };\n};\n", "import {\n successEnvelopeSchema,\n ArtifactsScreenshotInputSchema,\n ArtifactsScreenshotOutputSchema,\n DiagnosticsDoctorInputSchema,\n DiagnosticsDoctorOutputSchema,\n DialogAcceptInputSchema,\n DialogAcceptOutputSchema,\n DialogDismissInputSchema,\n DialogDismissOutputSchema,\n HealthCheckInputSchema,\n HealthCheckOutputSchema,\n ErrorEnvelopeSchema,\n DriveClickInputSchema,\n DriveClickOutputSchema,\n DriveDragInputSchema,\n DriveDragOutputSchema,\n DriveFillFormInputSchema,\n DriveFillFormOutputSchema,\n DriveBackInputSchema,\n DriveBackOutputSchema,\n DriveForwardInputSchema,\n DriveForwardOutputSchema,\n DriveGoBackInputSchema,\n DriveGoBackOutputSchema,\n DriveGoForwardInputSchema,\n DriveGoForwardOutputSchema,\n DriveHandleDialogInputSchema,\n DriveHandleDialogOutputSchema,\n DriveHoverInputSchema,\n DriveHoverOutputSchema,\n DriveSelectInputSchema,\n DriveSelectOutputSchema,\n DriveKeyInputSchema,\n DriveKeyOutputSchema,\n DriveKeyPressInputSchema,\n DriveKeyPressOutputSchema,\n DriveNavigateInputSchema,\n DriveNavigateOutputSchema,\n DriveScrollInputSchema,\n DriveScrollOutputSchema,\n DriveTabActivateInputSchema,\n DriveTabActivateOutputSchema,\n DriveTabCloseInputSchema,\n DriveTabCloseOutputSchema,\n DriveTabListInputSchema,\n DriveTabListOutputSchema,\n DriveTypeInputSchema,\n DriveTypeOutputSchema,\n DriveWaitForInputSchema,\n DriveWaitForOutputSchema,\n InspectConsoleListInputSchema,\n InspectConsoleListOutputSchema,\n InspectDomDiffInputSchema,\n InspectDomDiffOutputSchema,\n InspectExtractContentInputSchema,\n InspectExtractContentOutputSchema,\n InspectDomSnapshotInputSchema,\n InspectDomSnapshotOutputSchema,\n InspectEvaluateInputSchema,\n InspectEvaluateOutputSchema,\n InspectFindInputSchema,\n InspectFindOutputSchema,\n InspectPageStateInputSchema,\n InspectPageStateOutputSchema,\n InspectNetworkHarInputSchema,\n InspectNetworkHarOutputSchema,\n InspectPerformanceMetricsInputSchema,\n InspectPerformanceMetricsOutputSchema,\n SessionCloseInputSchema,\n SessionCloseOutputSchema,\n SessionCreateInputSchema,\n SessionCreateOutputSchema,\n SessionRecoverInputSchema,\n SessionRecoverOutputSchema,\n SessionStatusInputSchema,\n SessionStatusOutputSchema,\n} from '@btraut/browser-bridge-shared';\nimport type {\n AnySchema,\n ZodRawShapeCompat,\n} from '@modelcontextprotocol/sdk/server/zod-compat';\nimport type {\n McpServer,\n ToolCallback,\n} from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport { CoreClient } from './core-client';\n\ntype ToolResult = CallToolResult;\n\ntype ToolConfig = {\n title: string;\n description: string;\n inputSchema: AnySchema | ZodRawShapeCompat;\n outputSchema: AnySchema | ZodRawShapeCompat;\n corePath: string;\n};\n\ntype ToolRegistrar = Pick<McpServer, 'registerTool'>;\n\ntype EnvelopeInput = Parameters<typeof successEnvelopeSchema>[0];\n\nconst toToolResult = (payload: unknown): ToolResult => {\n const content = [{ type: 'text' as const, text: JSON.stringify(payload) }];\n if (payload && typeof payload === 'object') {\n const isErrorEnvelope = ErrorEnvelopeSchema.safeParse(payload).success;\n return {\n content,\n structuredContent: payload as Record<string, unknown>,\n isError: isErrorEnvelope,\n };\n }\n return { content };\n};\n\nconst toInternalErrorEnvelope = (error: unknown) => ({\n ok: false as const,\n error: {\n code: 'INTERNAL' as const,\n message: error instanceof Error ? error.message : 'Unknown error.',\n retryable: false,\n },\n});\n\nconst envelope = (schema: EnvelopeInput) => successEnvelopeSchema(schema);\n\nexport const TOOL_DEFINITIONS: Array<{ name: string; config: ToolConfig }> = [\n {\n name: 'session.create',\n config: {\n title: 'Session Create',\n description: 'Create a new browser session.',\n inputSchema: SessionCreateInputSchema,\n outputSchema: envelope(SessionCreateOutputSchema),\n corePath: '/session/create',\n },\n },\n {\n name: 'session.status',\n config: {\n title: 'Session Status',\n description: 'Fetch session status.',\n inputSchema: SessionStatusInputSchema,\n outputSchema: envelope(SessionStatusOutputSchema),\n corePath: '/session/status',\n },\n },\n {\n name: 'session.recover',\n config: {\n title: 'Session Recover',\n description: 'Recover a session after errors.',\n inputSchema: SessionRecoverInputSchema,\n outputSchema: envelope(SessionRecoverOutputSchema),\n corePath: '/session/recover',\n },\n },\n {\n name: 'session.close',\n config: {\n title: 'Session Close',\n description: 'Close a session.',\n inputSchema: SessionCloseInputSchema,\n outputSchema: envelope(SessionCloseOutputSchema),\n corePath: '/session/close',\n },\n },\n {\n name: 'drive.navigate',\n config: {\n title: 'Drive Navigate',\n description: 'Navigate to a URL.',\n inputSchema: DriveNavigateInputSchema,\n outputSchema: envelope(DriveNavigateOutputSchema),\n corePath: '/drive/navigate',\n },\n },\n {\n name: 'drive.go_back',\n config: {\n title: 'Drive Go Back',\n description: 'Go back in browser history.',\n inputSchema: DriveGoBackInputSchema,\n outputSchema: envelope(DriveGoBackOutputSchema),\n corePath: '/drive/go_back',\n },\n },\n {\n name: 'drive.go_forward',\n config: {\n title: 'Drive Go Forward',\n description: 'Go forward in browser history.',\n inputSchema: DriveGoForwardInputSchema,\n outputSchema: envelope(DriveGoForwardOutputSchema),\n corePath: '/drive/go_forward',\n },\n },\n {\n name: 'drive.back',\n config: {\n title: 'Drive Back',\n description: 'Go back in browser history.',\n inputSchema: DriveBackInputSchema,\n outputSchema: envelope(DriveBackOutputSchema),\n corePath: '/drive/back',\n },\n },\n {\n name: 'drive.forward',\n config: {\n title: 'Drive Forward',\n description: 'Go forward in browser history.',\n inputSchema: DriveForwardInputSchema,\n outputSchema: envelope(DriveForwardOutputSchema),\n corePath: '/drive/forward',\n },\n },\n {\n name: 'drive.click',\n config: {\n title: 'Drive Click',\n description: 'Click an element.',\n inputSchema: DriveClickInputSchema,\n outputSchema: envelope(DriveClickOutputSchema),\n corePath: '/drive/click',\n },\n },\n {\n name: 'drive.hover',\n config: {\n title: 'Drive Hover',\n description: 'Hover over an element.',\n inputSchema: DriveHoverInputSchema,\n outputSchema: envelope(DriveHoverOutputSchema),\n corePath: '/drive/hover',\n },\n },\n {\n name: 'drive.select',\n config: {\n title: 'Drive Select',\n description: 'Select an option in a dropdown.',\n inputSchema: DriveSelectInputSchema,\n outputSchema: envelope(DriveSelectOutputSchema),\n corePath: '/drive/select',\n },\n },\n {\n name: 'drive.type',\n config: {\n title: 'Drive Type',\n description: 'Type into an element.',\n inputSchema: DriveTypeInputSchema,\n outputSchema: envelope(DriveTypeOutputSchema),\n corePath: '/drive/type',\n },\n },\n {\n name: 'drive.fill_form',\n config: {\n title: 'Drive Fill Form',\n description: 'Fill multiple form fields.',\n inputSchema: DriveFillFormInputSchema,\n outputSchema: envelope(DriveFillFormOutputSchema),\n corePath: '/drive/fill_form',\n },\n },\n {\n name: 'drive.drag',\n config: {\n title: 'Drive Drag',\n description: 'Drag an element to a target.',\n inputSchema: DriveDragInputSchema,\n outputSchema: envelope(DriveDragOutputSchema),\n corePath: '/drive/drag',\n },\n },\n {\n name: 'drive.handle_dialog',\n config: {\n title: 'Drive Handle Dialog',\n description: 'Handle a JavaScript dialog.',\n inputSchema: DriveHandleDialogInputSchema,\n outputSchema: envelope(DriveHandleDialogOutputSchema),\n corePath: '/drive/handle_dialog',\n },\n },\n {\n name: 'dialog.accept',\n config: {\n title: 'Dialog Accept',\n description: 'Accept a JavaScript dialog.',\n inputSchema: DialogAcceptInputSchema,\n outputSchema: envelope(DialogAcceptOutputSchema),\n corePath: '/dialog/accept',\n },\n },\n {\n name: 'dialog.dismiss',\n config: {\n title: 'Dialog Dismiss',\n description: 'Dismiss a JavaScript dialog.',\n inputSchema: DialogDismissInputSchema,\n outputSchema: envelope(DialogDismissOutputSchema),\n corePath: '/dialog/dismiss',\n },\n },\n {\n name: 'drive.key',\n config: {\n title: 'Drive Key',\n description: 'Press a keyboard key.',\n inputSchema: DriveKeyInputSchema,\n outputSchema: envelope(DriveKeyOutputSchema),\n corePath: '/drive/key',\n },\n },\n {\n name: 'drive.key_press',\n config: {\n title: 'Drive Key Press',\n description: 'Press a key on the active element.',\n inputSchema: DriveKeyPressInputSchema,\n outputSchema: envelope(DriveKeyPressOutputSchema),\n corePath: '/drive/key_press',\n },\n },\n {\n name: 'drive.scroll',\n config: {\n title: 'Drive Scroll',\n description:\n 'Scroll the default tab (agent window/tab unless tab_id is provided).',\n inputSchema: DriveScrollInputSchema,\n outputSchema: envelope(DriveScrollOutputSchema),\n corePath: '/drive/scroll',\n },\n },\n {\n name: 'drive.wait_for',\n config: {\n title: 'Drive Wait For',\n description: 'Wait for a drive condition.',\n inputSchema: DriveWaitForInputSchema,\n outputSchema: envelope(DriveWaitForOutputSchema),\n corePath: '/drive/wait_for',\n },\n },\n {\n name: 'drive.tab_list',\n config: {\n title: 'Drive Tab List',\n description: 'List browser tabs.',\n inputSchema: DriveTabListInputSchema,\n outputSchema: envelope(DriveTabListOutputSchema),\n corePath: '/drive/tab_list',\n },\n },\n {\n name: 'drive.tab_activate',\n config: {\n title: 'Drive Tab Activate',\n description: 'Activate a browser tab.',\n inputSchema: DriveTabActivateInputSchema,\n outputSchema: envelope(DriveTabActivateOutputSchema),\n corePath: '/drive/tab_activate',\n },\n },\n {\n name: 'drive.tab_close',\n config: {\n title: 'Drive Tab Close',\n description: 'Close a browser tab.',\n inputSchema: DriveTabCloseInputSchema,\n outputSchema: envelope(DriveTabCloseOutputSchema),\n corePath: '/drive/tab_close',\n },\n },\n {\n name: 'inspect.dom_snapshot',\n config: {\n title: 'Inspect DOM Snapshot',\n description: 'Capture a DOM snapshot.',\n inputSchema: InspectDomSnapshotInputSchema,\n outputSchema: envelope(InspectDomSnapshotOutputSchema),\n corePath: '/inspect/dom_snapshot',\n },\n },\n {\n name: 'inspect.dom_diff',\n config: {\n title: 'Inspect DOM Diff',\n description: 'Compare recent DOM snapshots.',\n inputSchema: InspectDomDiffInputSchema,\n outputSchema: envelope(InspectDomDiffOutputSchema),\n corePath: '/inspect/dom_diff',\n },\n },\n {\n name: 'inspect.find',\n config: {\n title: 'Inspect Find',\n description: 'Find elements in the accessibility tree and return refs.',\n inputSchema: InspectFindInputSchema,\n outputSchema: envelope(InspectFindOutputSchema),\n corePath: '/inspect/find',\n },\n },\n {\n name: 'inspect.extract_content',\n config: {\n title: 'Inspect Extract Content',\n description: 'Extract main content as markdown or text.',\n inputSchema: InspectExtractContentInputSchema,\n outputSchema: envelope(InspectExtractContentOutputSchema),\n corePath: '/inspect/extract_content',\n },\n },\n {\n name: 'inspect.page_state',\n config: {\n title: 'Inspect Page State',\n description: 'Capture form, storage, and cookie state.',\n inputSchema: InspectPageStateInputSchema,\n outputSchema: envelope(InspectPageStateOutputSchema),\n corePath: '/inspect/page_state',\n },\n },\n {\n name: 'inspect.console_list',\n config: {\n title: 'Inspect Console List',\n description: 'List console entries.',\n inputSchema: InspectConsoleListInputSchema,\n outputSchema: envelope(InspectConsoleListOutputSchema),\n corePath: '/inspect/console_list',\n },\n },\n {\n name: 'inspect.network_har',\n config: {\n title: 'Inspect Network HAR',\n description: 'Capture network HAR data.',\n inputSchema: InspectNetworkHarInputSchema,\n outputSchema: envelope(InspectNetworkHarOutputSchema),\n corePath: '/inspect/network_har',\n },\n },\n {\n name: 'inspect.evaluate',\n config: {\n title: 'Inspect Evaluate',\n description: 'Evaluate an expression in the target.',\n inputSchema: InspectEvaluateInputSchema,\n outputSchema: envelope(InspectEvaluateOutputSchema),\n corePath: '/inspect/evaluate',\n },\n },\n {\n name: 'inspect.performance_metrics',\n config: {\n title: 'Inspect Performance Metrics',\n description: 'Collect performance metrics.',\n inputSchema: InspectPerformanceMetricsInputSchema,\n outputSchema: envelope(InspectPerformanceMetricsOutputSchema),\n corePath: '/inspect/performance_metrics',\n },\n },\n {\n name: 'artifacts.screenshot',\n config: {\n title: 'Artifacts Screenshot',\n description: 'Capture a screenshot artifact.',\n inputSchema: ArtifactsScreenshotInputSchema,\n outputSchema: envelope(ArtifactsScreenshotOutputSchema),\n corePath: '/artifacts/screenshot',\n },\n },\n {\n name: 'health_check',\n config: {\n title: 'Health Check',\n description:\n 'Check server health including uptime, memory usage, active session count, and extension connection status.',\n inputSchema: HealthCheckInputSchema,\n outputSchema: envelope(HealthCheckOutputSchema),\n corePath: '/health_check',\n },\n },\n {\n name: 'diagnostics.doctor',\n config: {\n title: 'Diagnostics Doctor',\n description: 'Run diagnostics checks.',\n inputSchema: DiagnosticsDoctorInputSchema,\n outputSchema: envelope(DiagnosticsDoctorOutputSchema),\n corePath: '/diagnostics/doctor',\n },\n },\n];\n\nexport const createToolHandler = (\n client: CoreClient,\n corePath: string\n): ToolCallback<AnySchema> => {\n return (async (args: unknown, _extra: unknown): Promise<ToolResult> => {\n void _extra;\n try {\n const envelopeResult = await client.post(corePath, args);\n return toToolResult(envelopeResult);\n } catch (error) {\n const parsed = ErrorEnvelopeSchema.safeParse(error);\n if (parsed.success) {\n return toToolResult(parsed.data);\n }\n return toToolResult(toInternalErrorEnvelope(error));\n }\n }) as ToolCallback<AnySchema>;\n};\n\nexport const registerBrowserBridgeTools = (\n server: ToolRegistrar,\n client: CoreClient\n): void => {\n for (const tool of TOOL_DEFINITIONS) {\n server.registerTool(\n tool.name,\n {\n title: tool.config.title,\n description: tool.config.description,\n inputSchema: tool.config.inputSchema,\n outputSchema: tool.config.outputSchema,\n },\n createToolHandler(client, tool.config.corePath)\n );\n }\n};\n", "import { createServer } from 'node:http';\nimport type { IncomingMessage } from 'node:http';\nimport { randomUUID } from 'node:crypto';\nimport { JsonlLogger, createJsonlLogger } from '@btraut/browser-bridge-shared';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';\nimport { CoreClient, CoreClientOptions, createCoreClient } from './core-client';\nimport { registerBrowserBridgeTools } from './tools';\n\nexport type McpAdapterOptions = CoreClientOptions & {\n name?: string;\n version?: string;\n coreClient?: CoreClient;\n};\n\nexport type McpAdapterHandle = {\n server: McpServer;\n client: CoreClient;\n};\n\nexport type McpAdapterStartHandle = McpAdapterHandle & {\n transport: StdioServerTransport;\n};\n\nexport type McpAdapterHttpOptions = {\n host?: string;\n port?: number;\n path?: string;\n};\n\nexport type McpAdapterHttpStartHandle = {\n client: CoreClient;\n host: string;\n port: number;\n path: string;\n close: () => Promise<void>;\n};\n\nconst DEFAULT_SERVER_NAME = 'browser-bridge';\nconst DEFAULT_SERVER_VERSION = '0.0.0';\nconst DEFAULT_HTTP_HOST = '127.0.0.1';\nconst DEFAULT_HTTP_PATH = '/mcp';\n\nconst durationMs = (startedAt: bigint): number =>\n Number((Number(process.hrtime.bigint() - startedAt) / 1_000_000).toFixed(3));\n\nconst resolveAdapterLogger = (\n options: McpAdapterOptions & { logger?: JsonlLogger }\n): JsonlLogger =>\n options.logger ??\n createJsonlLogger({\n stream: 'mcp-adapter',\n cwd: options.cwd,\n });\n\nexport const createMcpServer = (\n options: McpAdapterOptions = {}\n): McpAdapterHandle => {\n const logger = resolveAdapterLogger(options);\n const server = new McpServer({\n name: options.name ?? DEFAULT_SERVER_NAME,\n version: options.version ?? DEFAULT_SERVER_VERSION,\n });\n const client =\n options.coreClient ??\n createCoreClient({\n ...options,\n logger: logger.child({ scope: 'core-client' }),\n });\n\n registerBrowserBridgeTools(server, client);\n logger.info('mcp.server.created', {\n name: options.name ?? DEFAULT_SERVER_NAME,\n version: options.version ?? DEFAULT_SERVER_VERSION,\n core_base_url: client.baseUrl,\n });\n\n return { server, client };\n};\n\nexport const startMcpServer = async (\n options: McpAdapterOptions = {}\n): Promise<McpAdapterStartHandle> => {\n const logger = resolveAdapterLogger(options);\n logger.info('mcp.stdio.start.begin', {\n name: options.name ?? DEFAULT_SERVER_NAME,\n version: options.version ?? DEFAULT_SERVER_VERSION,\n });\n\n const handle = createMcpServer({\n ...options,\n logger,\n });\n const transport = new StdioServerTransport();\n try {\n await handle.server.connect(transport);\n logger.info('mcp.stdio.start.ready', {\n core_base_url: handle.client.baseUrl,\n });\n } catch (error) {\n logger.error('mcp.stdio.start.failed', {\n error,\n });\n throw error;\n }\n return { ...handle, transport };\n};\n\nconst readJsonBody = async (\n req: IncomingMessage,\n maxBytes = 5 * 1024 * 1024\n): Promise<unknown> => {\n const chunks: Buffer[] = [];\n let total = 0;\n await new Promise<void>((resolve, reject) => {\n req.on('data', (chunk: Buffer) => {\n total += chunk.length;\n if (total > maxBytes) {\n reject(new Error('Request body too large.'));\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => resolve());\n req.on('error', (err: unknown) => reject(err));\n });\n const raw = Buffer.concat(chunks).toString('utf8');\n if (!raw) {\n return undefined;\n }\n return JSON.parse(raw) as unknown;\n};\n\nconst getHeaderValue = (\n value: string | string[] | undefined\n): string | undefined => {\n if (typeof value === 'string') {\n return value;\n }\n if (Array.isArray(value)) {\n return value[0];\n }\n return undefined;\n};\n\nexport const startMcpHttpServer = async (\n options: McpAdapterOptions & McpAdapterHttpOptions = {}\n): Promise<McpAdapterHttpStartHandle> => {\n const logger = resolveAdapterLogger(options).child({ scope: 'http-server' });\n const host = options.host ?? DEFAULT_HTTP_HOST;\n const port = typeof options.port === 'number' ? options.port : 0;\n const path = options.path ?? DEFAULT_HTTP_PATH;\n logger.info('mcp.http.start.begin', {\n host,\n port,\n path,\n });\n\n const client =\n options.coreClient ??\n createCoreClient({\n ...options,\n logger: logger.child({ scope: 'core-client' }),\n });\n\n const sessions = new Map<\n string,\n {\n transport: StreamableHTTPServerTransport;\n server: McpServer;\n }\n >();\n\n const closeAllSessions = async (): Promise<void> => {\n const entries = Array.from(sessions.values());\n sessions.clear();\n await Promise.all(\n entries.map(async (entry) => {\n try {\n await entry.transport.close();\n } catch {\n // Ignore.\n }\n try {\n await entry.server.close();\n } catch {\n // Ignore.\n }\n })\n );\n };\n\n const httpServer = createServer(async (req, res) => {\n const startedAt = process.hrtime.bigint();\n const requestLogger = logger.child({\n scope: 'http-request',\n request_id: randomUUID(),\n });\n requestLogger.debug('mcp.http.request.start', {\n method: req.method,\n url: req.url ?? '',\n });\n\n try {\n const url = new URL(req.url ?? '', `http://${host}`);\n if (url.pathname !== path) {\n res.writeHead(404, { 'content-type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not Found' }));\n requestLogger.warn('mcp.http.request.not_found', {\n method: req.method,\n pathname: url.pathname,\n expected_path: path,\n status: 404,\n duration_ms: durationMs(startedAt),\n });\n return;\n }\n\n const sessionId = getHeaderValue(req.headers['mcp-session-id']);\n requestLogger.debug('mcp.http.request.session', {\n session_id: sessionId ?? null,\n });\n\n const parsedBody =\n req.method === 'POST' ? await readJsonBody(req) : undefined;\n\n if (sessionId) {\n const entry = sessions.get(sessionId);\n if (!entry) {\n res.writeHead(404, { 'content-type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unknown session.' }));\n requestLogger.warn('mcp.http.request.unknown_session', {\n session_id: sessionId,\n status: 404,\n duration_ms: durationMs(startedAt),\n });\n return;\n }\n await entry.transport.handleRequest(req, res, parsedBody);\n requestLogger.info('mcp.http.request.forwarded', {\n session_id: sessionId,\n status: res.statusCode,\n duration_ms: durationMs(startedAt),\n });\n return;\n }\n\n if (req.method !== 'POST' || !isInitializeRequest(parsedBody)) {\n res.writeHead(400, { 'content-type': 'application/json' });\n res.end(\n JSON.stringify({\n error:\n 'Missing mcp-session-id header. First request must be initialize.',\n })\n );\n requestLogger.warn('mcp.http.request.invalid_initialize', {\n method: req.method,\n status: 400,\n duration_ms: durationMs(startedAt),\n });\n return;\n }\n\n let sessionEntry:\n | {\n transport: StreamableHTTPServerTransport;\n server: McpServer;\n }\n | undefined;\n\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (sid) => {\n if (sessionEntry) {\n sessions.set(sid, sessionEntry);\n logger.info('mcp.http.session.opened', {\n session_id: sid,\n });\n }\n },\n onsessionclosed: async (sid) => {\n const entry = sessions.get(sid);\n sessions.delete(sid);\n if (!entry) {\n return;\n }\n await Promise.allSettled([\n entry.transport.close(),\n entry.server.close(),\n ]);\n logger.info('mcp.http.session.closed', {\n session_id: sid,\n });\n },\n });\n\n const sessionServer = new McpServer({\n name: options.name ?? DEFAULT_SERVER_NAME,\n version: options.version ?? DEFAULT_SERVER_VERSION,\n });\n registerBrowserBridgeTools(sessionServer, client);\n await sessionServer.connect(transport);\n sessionEntry = { transport, server: sessionServer };\n\n await transport.handleRequest(req, res, parsedBody);\n requestLogger.info('mcp.http.request.initialized', {\n status: res.statusCode,\n duration_ms: durationMs(startedAt),\n });\n } catch (error) {\n requestLogger.error('mcp.http.request.error', {\n method: req.method,\n url: req.url ?? '',\n status: 500,\n duration_ms: durationMs(startedAt),\n error,\n });\n res.writeHead(500, { 'content-type': 'application/json' });\n res.end(\n JSON.stringify({\n error: error instanceof Error ? error.message : 'Internal error.',\n })\n );\n }\n });\n\n const resolvedPort = await new Promise<number>((resolve, reject) => {\n httpServer.listen(port, host, () => {\n const address = httpServer.address();\n resolve(typeof address === 'object' && address ? address.port : port);\n });\n httpServer.on('error', reject);\n });\n logger.info('mcp.http.start.ready', {\n host,\n port: resolvedPort,\n path,\n core_base_url: client.baseUrl,\n });\n\n return {\n client,\n host,\n port: resolvedPort,\n path,\n close: async () => {\n logger.info('mcp.http.stop.begin', {\n host,\n port: resolvedPort,\n });\n await new Promise<void>((resolve, reject) => {\n httpServer.close((err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n await closeAllSessions();\n logger.info('mcp.http.stop.complete', {\n host,\n port: resolvedPort,\n });\n },\n };\n};\n", "type CheckboxChoice<T> = {\n value: T;\n label: string;\n checked?: boolean;\n disabled?: boolean | string;\n};\n\nexport const requireTty = (): void => {\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n throw new Error('Interactive install requires a TTY.');\n }\n};\n\nexport const checkboxPrompt = async <T>(options: {\n message: string;\n choices: CheckboxChoice<T>[];\n}): Promise<T[]> => {\n // @inquirer/prompts is ESM; load lazily from our CommonJS bundle.\n const mod = (await import('@inquirer/prompts')) as unknown as {\n checkbox: (args: {\n message: string;\n loop?: boolean;\n choices: Array<{\n value: unknown;\n name: string;\n checked?: boolean;\n disabled?: boolean | string;\n }>;\n }) => Promise<unknown[]>;\n };\n\n const { checkbox } = mod;\n const values = await checkbox({\n message: options.message,\n // Avoid wrapping from bottom -> top (and top -> bottom) when navigating long lists.\n loop: false,\n choices: options.choices.map((c) => ({\n value: c.value as unknown,\n name: c.label,\n checked: c.checked,\n disabled: c.disabled,\n })),\n });\n return values as T[];\n};\n", "import { spawn } from 'node:child_process';\nimport { installCursorMcp } from './cursor-mcp';\n\nexport type McpHarnessId = 'codex' | 'claude' | 'cursor';\n\nexport type McpInstallResult =\n | { ok: true; details?: { cursorSettingsPath?: string } }\n | { ok: false; error: { code: string; message: string } };\n\nconst runQuiet = async (cmd: string, args: string[]): Promise<void> => {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(cmd, args, { stdio: ['ignore', 'pipe', 'pipe'] });\n let stderr = '';\n child.stderr?.on('data', (chunk) => {\n stderr += String(chunk);\n });\n child.on('error', reject);\n child.on('exit', (code) => {\n if (code === 0) resolve();\n else {\n const suffix = stderr.trim() ? `: ${stderr.trim()}` : '';\n reject(new Error(`${cmd} exited with ${code ?? 'unknown'}${suffix}`));\n }\n });\n });\n};\n\nconst tryRun = async (cmd: string, args: string[]): Promise<void> => {\n try {\n await runQuiet(cmd, args);\n } catch {\n // best-effort (used for remove)\n }\n};\n\nexport const installMcp = async (\n harness: McpHarnessId\n): Promise<McpInstallResult> => {\n try {\n if (harness === 'codex') {\n await tryRun('codex', ['mcp', 'remove', 'browser-bridge']);\n await runQuiet('codex', [\n 'mcp',\n 'add',\n 'browser-bridge',\n '--',\n 'browser-bridge',\n 'mcp',\n ]);\n return { ok: true };\n }\n\n if (harness === 'claude') {\n // Remove any existing config, then install user-scoped so it \"just works\" across projects.\n await tryRun('claude', [\n 'mcp',\n 'remove',\n '--scope',\n 'local',\n 'browser-bridge',\n ]);\n await tryRun('claude', [\n 'mcp',\n 'remove',\n '--scope',\n 'project',\n 'browser-bridge',\n ]);\n await tryRun('claude', [\n 'mcp',\n 'remove',\n '--scope',\n 'user',\n 'browser-bridge',\n ]);\n\n await runQuiet('claude', [\n 'mcp',\n 'add',\n '--scope',\n 'user',\n '--transport',\n 'stdio',\n 'browser-bridge',\n '--',\n 'browser-bridge',\n 'mcp',\n ]);\n return { ok: true };\n }\n\n // Cursor supports `--add-mcp`, but in practice its argv parsing breaks when\n // passing JSON that includes commas (it gets split and stops being valid\n // JSON). Install by directly updating Cursor's user settings instead.\n const cursor = await installCursorMcp();\n return { ok: true, details: { cursorSettingsPath: cursor.settingsPath } };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error.';\n return {\n ok: false,\n error: { code: 'MCP_INSTALL_FAILED', message },\n };\n }\n};\n", "import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\ntype JsonObject = Record<string, unknown>;\n\nconst isObject = (value: unknown): value is JsonObject =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\ntype Platform = string;\n\nexport const resolveCursorUserSettingsPath = (options?: {\n platform?: Platform;\n homeDir?: string;\n env?: Record<string, string | undefined>;\n}): string => {\n const platform = options?.platform ?? process.platform;\n const homeDir = options?.homeDir ?? os.homedir();\n const env = options?.env ?? process.env;\n\n if (platform === 'darwin') {\n return path.join(\n homeDir,\n 'Library',\n 'Application Support',\n 'Cursor',\n 'User',\n 'settings.json'\n );\n }\n\n if (platform === 'win32') {\n const appData = env.APPDATA;\n if (!appData) {\n throw new Error(\n 'APPDATA is not set; cannot resolve Cursor settings path.'\n );\n }\n return path.join(appData, 'Cursor', 'User', 'settings.json');\n }\n\n // Linux and other unix-like platforms: follow VS Code convention.\n return path.join(homeDir, '.config', 'Cursor', 'User', 'settings.json');\n};\n\nexport const installCursorMcp = async (\n settingsPath?: string\n): Promise<{ settingsPath: string }> => {\n const filePath = settingsPath ?? resolveCursorUserSettingsPath();\n const dir = path.dirname(filePath);\n await fs.mkdir(dir, { recursive: true });\n\n let settings: JsonObject = {};\n try {\n const raw = await fs.readFile(filePath, 'utf8');\n const parsed = JSON.parse(raw) as unknown;\n if (isObject(parsed)) {\n settings = parsed;\n } else {\n throw new Error('Cursor settings.json is not a JSON object.');\n }\n } catch (error) {\n // If it doesn't exist, initialize a new settings object.\n if (\n error &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as { code?: unknown }).code === 'ENOENT'\n ) {\n settings = {};\n } else {\n throw error;\n }\n }\n\n const mcp = isObject(settings.mcp) ? settings.mcp : {};\n const servers = isObject(mcp.servers) ? mcp.servers : {};\n servers['browser-bridge'] = {\n command: 'browser-bridge',\n args: ['mcp'],\n };\n mcp.servers = servers;\n settings.mcp = mcp;\n\n await fs.writeFile(\n filePath,\n JSON.stringify(settings, null, 2) + '\\n',\n 'utf8'\n );\n\n return { settingsPath: filePath };\n};\n", "import { Command } from 'commander';\nimport {\n startMcpHttpServer,\n startMcpServer,\n} from '@btraut/browser-bridge-mcp-adapter';\nimport { createCoreClient } from '../core-client';\nimport { getGlobalOptions, runLocal } from '../cli-runtime';\nimport { checkboxPrompt, requireTty } from '../tui';\nimport { installMcp } from '../installer/mcp-install';\n\ntype McpCommandOptions = {\n name?: string;\n version?: string;\n};\n\nexport const registerMcpCommand = (program: Command): void => {\n const startServer = async (\n options: McpCommandOptions,\n command: Command\n ): Promise<void> => {\n const globals = getGlobalOptions(command);\n const coreClient = createCoreClient({\n host: globals.host,\n port: globals.port,\n ensureDaemon: globals.daemon !== false,\n });\n\n try {\n await startMcpServer({\n name: options.name,\n version: options.version,\n coreClient,\n });\n } catch (error) {\n console.error(error);\n process.exitCode = 1;\n }\n };\n\n const mcp = program.command('mcp').description('MCP server and helpers');\n\n mcp\n .command('install')\n .description('Install Browser Bridge as an MCP server in supported clients')\n .action(async (_options, command: Command) => {\n await runLocal(command, async ({ json }) => {\n if (json) {\n throw new Error('mcp install is interactive; omit --json.');\n }\n\n requireTty();\n\n const selected = await checkboxPrompt<'codex' | 'claude' | 'cursor'>({\n message: 'Install MCP into clients:',\n choices: [\n { value: 'codex', label: 'Codex', checked: true },\n { value: 'claude', label: 'Claude', checked: true },\n { value: 'cursor', label: 'Cursor', checked: true },\n ],\n });\n\n const results: Record<string, unknown> = {};\n let hadError = false;\n for (const harness of selected) {\n const result = await installMcp(harness);\n results[harness] = result;\n if (result.ok === false) {\n hadError = true;\n }\n }\n\n if (hadError) {\n process.exitCode = 1;\n }\n\n return { ok: true, result: { installed: results } };\n });\n });\n\n // Keep `browser-bridge mcp` working (backwards compatible), but also expose\n // `browser-bridge mcp serve` for clarity.\n mcp\n .option('--name <name>', 'MCP server name')\n .option('--version <version>', 'MCP server version')\n .action(startServer);\n\n mcp\n .command('serve')\n .description('Run the MCP server over stdio')\n .option('--name <name>', 'MCP server name')\n .option('--version <version>', 'MCP server version')\n .action(startServer);\n\n mcp\n .command('serve-http')\n .description('Run the MCP server over Streamable HTTP')\n .option('--name <name>', 'MCP server name')\n .option('--version <version>', 'MCP server version')\n .option('--host <host>', 'HTTP host (default 127.0.0.1)')\n .option('--port <port>', 'HTTP port (default random available port)')\n .option('--path <path>', 'HTTP path (default /mcp)')\n .action(async (options, command: Command) => {\n const globals = getGlobalOptions(command);\n const coreClient = createCoreClient({\n host: globals.host,\n port: globals.port,\n ensureDaemon: globals.daemon !== false,\n });\n\n const parsedPort =\n typeof options.port === 'string' && options.port.length > 0\n ? Number(options.port)\n : undefined;\n\n try {\n const handle = await startMcpHttpServer({\n name: options.name,\n version: options.version,\n host: options.host,\n port:\n typeof parsedPort === 'number' && Number.isFinite(parsedPort)\n ? parsedPort\n : undefined,\n path: options.path,\n coreClient,\n });\n\n console.error(\n `MCP HTTP server listening on http://${handle.host}:${handle.port}${handle.path}`\n );\n } catch (error) {\n console.error(error);\n process.exitCode = 1;\n }\n });\n};\n", "import { createServer } from 'http';\nimport express, { Express } from 'express';\nimport {\n JsonlLogger,\n createBoundedPortProbeSequence,\n createJsonlLogger,\n resolveCoreRuntime,\n writeRuntimeMetadata,\n} from '@btraut/browser-bridge-shared';\nimport { createSessionRouter } from './routes/session';\nimport { registerArtifactsRoutes } from './routes/artifacts';\nimport { registerDiagnosticsRoutes } from './routes/diagnostics';\nimport { registerDriveRoutes, registerInspectRoutes } from './routes';\nimport { SessionRegistry } from './session';\nimport { ExtensionBridge } from './extension-bridge';\nimport { DriveController } from './drive';\nimport { InspectService, createInspectService } from './inspect';\nimport { RecoveryTracker } from './recovery';\nimport { DebuggerBridge } from './debugger-bridge';\n\nexport type CoreServer = {\n app: Express;\n registry: SessionRegistry;\n extensionBridge: ExtensionBridge;\n debuggerBridge: DebuggerBridge;\n drive: DriveController;\n inspect: InspectService;\n recoveryTracker: RecoveryTracker;\n};\n\nexport type CoreServerOptions = {\n registry?: SessionRegistry;\n logger?: JsonlLogger;\n};\n\nexport const createCoreServer = (\n options: CoreServerOptions = {}\n): CoreServer => {\n const logger = options.logger;\n const app = express();\n const registry = options.registry ?? new SessionRegistry();\n const extensionBridge = new ExtensionBridge({ registry });\n const debuggerBridge = new DebuggerBridge({ extensionBridge });\n const drive = new DriveController(extensionBridge, registry);\n const inspect = createInspectService({\n registry,\n debuggerBridge,\n extensionBridge,\n });\n const recoveryTracker = new RecoveryTracker();\n\n app.use(express.json({ limit: '1mb' }));\n if (logger) {\n app.use((req, res, next) => {\n const startedAt = process.hrtime.bigint();\n res.on('finish', () => {\n const elapsedMs =\n Number(process.hrtime.bigint() - startedAt) / 1_000_000;\n logger.info('core.http.request', {\n method: req.method,\n path: req.originalUrl || req.url,\n status: res.statusCode,\n duration_ms: Number(elapsedMs.toFixed(3)),\n });\n });\n next();\n });\n }\n\n app.get('/health', (_req, res) => {\n res.status(200).json({ ok: true });\n });\n\n app.use(\n '/session',\n createSessionRouter(registry, {\n driveConnected: () => extensionBridge.isConnected(),\n inspectRecover: (sessionId) => inspect.reconnect(sessionId),\n recordRecovery: (attempt) => recoveryTracker.record(attempt),\n })\n );\n\n registerDriveRoutes(app, { drive });\n registerInspectRoutes(app, {\n registry,\n extensionBridge,\n inspectService: inspect,\n });\n registerArtifactsRoutes(app, {\n registry,\n extensionBridge,\n inspectService: inspect,\n });\n registerDiagnosticsRoutes(app, {\n registry,\n extensionBridge,\n debuggerBridge,\n drive,\n inspectService: inspect,\n recoveryTracker,\n });\n\n return {\n app,\n registry,\n extensionBridge,\n debuggerBridge,\n drive,\n inspect,\n recoveryTracker,\n };\n};\n\nexport type CoreServerStartOptions = {\n host?: string;\n port?: number;\n registry?: SessionRegistry;\n logger?: JsonlLogger;\n};\n\nexport type CoreServerHandle = {\n app: Express;\n registry: SessionRegistry;\n server: ReturnType<typeof createServer>;\n host: string;\n port: number;\n};\n\nconst CORE_PORT_PROBE_ATTEMPTS = 20;\n\nconst resolveSessionTtlMs = (): number => {\n const env =\n process.env.BROWSER_BRIDGE_SESSION_TTL_MS ||\n process.env.BROWSER_VISION_SESSION_TTL_MS;\n if (env) {\n const parsed = Number(env);\n if (Number.isFinite(parsed) && parsed >= 0) {\n return parsed;\n }\n }\n return 60 * 60 * 1000;\n};\n\nconst resolveSessionCleanupIntervalMs = (ttlMs: number): number => {\n const env =\n process.env.BROWSER_BRIDGE_SESSION_CLEANUP_INTERVAL_MS ||\n process.env.BROWSER_VISION_SESSION_CLEANUP_INTERVAL_MS;\n if (env) {\n const parsed = Number(env);\n if (Number.isFinite(parsed) && parsed > 0) {\n return parsed;\n }\n }\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n return 60 * 1000;\n }\n return Math.min(60 * 1000, Math.max(1000, Math.floor(ttlMs / 2)));\n};\n\nconst isAddressInUseError = (error: unknown): boolean =>\n Boolean(\n error &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as { code?: string }).code === 'EADDRINUSE'\n );\n\nconst listenOnPort = (\n app: Express,\n extensionBridge: ExtensionBridge,\n host: string,\n port: number\n): Promise<ReturnType<typeof createServer>> =>\n new Promise((resolve, reject) => {\n const server = createServer(app);\n extensionBridge.attach(server);\n\n const onError = (error: unknown) => {\n server.off('listening', onListening);\n reject(error);\n };\n\n const onListening = () => {\n server.off('error', onError);\n resolve(server);\n };\n\n server.once('error', onError);\n server.once('listening', onListening);\n server.listen(port, host);\n });\n\nconst maybeStartSessionCleanup = (\n server: ReturnType<typeof createServer>,\n registry: SessionRegistry,\n logger: JsonlLogger\n): void => {\n const ttlMs = resolveSessionTtlMs();\n if (ttlMs <= 0) {\n return;\n }\n const intervalMs = resolveSessionCleanupIntervalMs(ttlMs);\n const timer = setInterval(() => {\n try {\n registry.cleanupIdleSessions(ttlMs);\n } catch (error) {\n logger.warn('core.session_cleanup.failed', {\n ttl_ms: ttlMs,\n interval_ms: intervalMs,\n error,\n });\n console.warn('Session cleanup failed:', error);\n }\n }, intervalMs);\n timer.unref();\n server.on('close', () => clearInterval(timer));\n};\n\nexport const startCoreServer = async (\n options: CoreServerStartOptions = {}\n): Promise<CoreServerHandle> => {\n const logger =\n options.logger ??\n createJsonlLogger({\n stream: 'core',\n });\n\n logger.info('core.start.begin', {\n host_option: options.host ?? null,\n port_option: options.port ?? null,\n });\n\n const runtime = resolveCoreRuntime({\n host: options.host,\n port: options.port,\n strictEnvPort: false,\n });\n logger.info('core.runtime.resolved', {\n host: runtime.host,\n port: runtime.port,\n host_source: runtime.hostSource,\n port_source: runtime.portSource,\n metadata_path: runtime.metadataPath,\n git_root: runtime.gitRoot,\n worktree_id: runtime.worktreeId,\n deterministic_port: runtime.deterministicPort,\n });\n\n const { app, registry, extensionBridge } = createCoreServer({\n registry: options.registry,\n logger,\n });\n\n const probePorts =\n runtime.portSource === 'metadata' || runtime.portSource === 'deterministic'\n ? createBoundedPortProbeSequence(runtime.port, CORE_PORT_PROBE_ATTEMPTS)\n : [runtime.port];\n\n let lastAddressInUseError: unknown;\n for (const candidatePort of probePorts) {\n const listenStart = process.hrtime.bigint();\n try {\n const server = await listenOnPort(\n app,\n extensionBridge,\n runtime.host,\n candidatePort\n );\n const address = server.address();\n const resolvedPort =\n typeof address === 'object' && address !== null\n ? address.port\n : candidatePort;\n\n maybeStartSessionCleanup(server, registry, logger);\n const startupDurationMs =\n Number(process.hrtime.bigint() - listenStart) / 1_000_000;\n logger.info('core.start.ready', {\n host: runtime.host,\n port: resolvedPort,\n candidate_port: candidatePort,\n duration_ms: Number(startupDurationMs.toFixed(3)),\n });\n\n try {\n writeRuntimeMetadata(\n {\n host: runtime.host,\n port: resolvedPort,\n git_root: runtime.gitRoot ?? undefined,\n worktree_id: runtime.worktreeId ?? undefined,\n updated_at: new Date().toISOString(),\n },\n { metadataPath: runtime.metadataPath }\n );\n logger.info('core.runtime_metadata.persisted', {\n metadata_path: runtime.metadataPath,\n host: runtime.host,\n port: resolvedPort,\n });\n } catch (error) {\n logger.warn('core.runtime_metadata.persist_failed', {\n metadata_path: runtime.metadataPath,\n error,\n });\n console.warn('Failed to persist runtime metadata:', error);\n }\n\n return {\n app,\n registry,\n server,\n host: runtime.host,\n port: resolvedPort,\n };\n } catch (error) {\n if (isAddressInUseError(error) && probePorts.length > 1) {\n lastAddressInUseError = error;\n logger.warn('core.start.port_in_use', {\n host: runtime.host,\n candidate_port: candidatePort,\n error,\n });\n continue;\n }\n logger.error('core.start.failed', {\n host: runtime.host,\n candidate_port: candidatePort,\n error,\n });\n throw error;\n }\n }\n\n logger.error('core.start.failed_all_ports', {\n host: runtime.host,\n initial_port: runtime.port,\n attempts: probePorts.length,\n error: lastAddressInUseError,\n });\n throw (\n lastAddressInUseError ??\n new Error(`Unable to bind Core server on ${runtime.host}:${runtime.port}.`)\n );\n};\n", "import { Router } from 'express';\nimport { InvalidSessionTransition, SessionState } from '../state';\nimport { SessionError, SessionRegistry } from '../session';\nimport { isRecord, sendError, sendResult } from './shared';\n\nconst readSessionId = (body: unknown): string | undefined => {\n if (!isRecord(body)) {\n return undefined;\n }\n\n const sessionId = body.session_id;\n if (typeof sessionId !== 'string' || sessionId.length === 0) {\n return undefined;\n }\n\n return sessionId;\n};\n\ntype SessionRouterOptions = {\n driveConnected?: () => boolean;\n inspectRecover?: (sessionId: string) => Promise<boolean>;\n recordRecovery?: (attempt: {\n sessionId: string;\n recovered: boolean;\n state: SessionState;\n message?: string;\n at: string;\n }) => void;\n};\n\nexport const createSessionRouter = (\n registry: SessionRegistry,\n options: SessionRouterOptions = {}\n): Router => {\n const router = Router();\n\n router.post('/create', (req, res) => {\n const body = req.body;\n if (body !== undefined) {\n if (!isRecord(body)) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'Request body must be an object.',\n retryable: false,\n });\n }\n if (Object.keys(body).length > 0) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session.create does not accept any input fields.',\n retryable: false,\n });\n }\n }\n\n const session = registry.create();\n if (options.driveConnected?.()) {\n try {\n registry.apply(session.id, 'DRIVE_CONNECTED');\n } catch {\n // Ignore invalid transitions.\n }\n }\n return sendResult(res, {\n session_id: session.id,\n state: session.state,\n created_at: session.createdAt.toISOString(),\n });\n });\n\n router.post('/status', (req, res) => {\n const sessionId = readSessionId(req.body);\n if (!sessionId) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session_id is required',\n retryable: false,\n });\n }\n\n try {\n const session = registry.require(sessionId);\n return sendResult(res, {\n session_id: session.id,\n state: session.state,\n updated_at: session.updatedAt.toISOString(),\n });\n } catch (error) {\n if (error instanceof SessionError) {\n return sendError(res, 404, {\n code: error.code,\n message: error.message,\n retryable: false,\n });\n }\n\n return sendError(res, 500, {\n code: 'INTERNAL',\n message: 'Unexpected error while fetching status.',\n retryable: false,\n });\n }\n });\n\n router.post('/recover', async (req, res) => {\n const sessionId = readSessionId(req.body);\n if (!sessionId) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session_id is required',\n retryable: false,\n });\n }\n\n try {\n const session = registry.require(sessionId);\n let outcome:\n | {\n recovered: boolean;\n message?: string;\n }\n | undefined;\n\n if (session.state === SessionState.DEGRADED_DRIVE) {\n const connected = options.driveConnected?.() ?? false;\n outcome = {\n recovered: connected,\n message: connected\n ? 'Drive recovery succeeded.'\n : 'Drive recovery failed.',\n };\n } else if (session.state === SessionState.DEGRADED_INSPECT) {\n const recovered = options.inspectRecover\n ? await options.inspectRecover(sessionId)\n : false;\n outcome = {\n recovered,\n message: recovered\n ? 'Inspect recovery succeeded.'\n : 'Inspect recovery failed.',\n };\n }\n\n const result = registry.recover(sessionId, outcome);\n if (outcome) {\n const attempt = {\n sessionId,\n recovered: result.recovered,\n state: result.state,\n message: result.message,\n at: new Date().toISOString(),\n };\n options.recordRecovery?.(attempt);\n const status = result.recovered ? 'succeeded' : 'failed';\n console.info(\n `[recovery] session ${sessionId} ${status}: ${result.message ?? ''}`\n );\n }\n return sendResult(res, {\n session_id: result.sessionId,\n recovered: result.recovered,\n state: result.state,\n message: result.message,\n });\n } catch (error) {\n if (error instanceof SessionError) {\n const status = error.code === 'SESSION_CLOSED' ? 409 : 404;\n return sendError(res, status, {\n code: error.code,\n message: error.message,\n retryable: false,\n });\n }\n\n if (error instanceof InvalidSessionTransition) {\n return sendError(res, 409, {\n code: 'FAILED_PRECONDITION',\n message: error.message,\n retryable: false,\n });\n }\n\n return sendError(res, 500, {\n code: 'INTERNAL',\n message: 'Unexpected error while recovering session.',\n retryable: false,\n });\n }\n });\n\n router.post('/close', (req, res) => {\n const sessionId = readSessionId(req.body);\n if (!sessionId) {\n return sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session_id is required',\n retryable: false,\n });\n }\n\n try {\n registry.close(sessionId);\n return sendResult(res, { ok: true });\n } catch (error) {\n if (error instanceof SessionError) {\n return sendError(res, 404, {\n code: error.code,\n message: error.message,\n retryable: false,\n });\n }\n\n if (error instanceof InvalidSessionTransition) {\n return sendError(res, 409, {\n code: 'FAILED_PRECONDITION',\n message: error.message,\n retryable: false,\n });\n }\n\n return sendError(res, 500, {\n code: 'INTERNAL',\n message: 'Unexpected error while closing session.',\n retryable: false,\n });\n }\n });\n\n return router;\n};\n", "import { randomUUID } from 'crypto';\nimport { writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { Readability } from '@mozilla/readability';\nimport { JSDOM } from 'jsdom';\nimport TurndownService from 'turndown';\nimport { ensureArtifactRootDir } from '../artifacts';\nimport { driveMutex } from '../drive';\nimport type { DebuggerBridge } from '../debugger-bridge';\nimport type {\n DriveAction,\n DriveErrorInfo,\n DriveResponse,\n DriveScreenshotResult,\n DriveTabInfo,\n} from '../drive-protocol';\nimport {\n applyAxSnapshotFilters,\n getAxName,\n getAxNodes,\n getAxRole,\n LABEL_AX_ROLES,\n matchesAxText,\n matchesTextValue,\n normalizeQuery,\n truncateAxSnapshot,\n} from './ax-snapshot';\nimport { toConsoleEntry } from './console';\nimport { buildHar } from './har';\nimport { captureHtml } from './html-snapshot';\nimport { SnapshotHistory } from './snapshot-history';\nimport {\n applySnapshotRefs,\n assignRefsToAxSnapshot,\n resolveNodeIdForSelector,\n} from './snapshot-refs';\nimport { InspectError } from './errors';\nimport type {\n ArtifactInfo,\n ConsoleEntry,\n ConsoleListResult,\n DomSnapshotResult,\n EvaluateResult,\n ExtractContentResult,\n FormInfo,\n InspectErrorCode,\n InspectServiceOptions,\n PageStateResult,\n PerformanceMetricsResult,\n StorageEntry,\n} from './types';\nimport { PAGE_STATE_SCRIPT } from '../page-state-script';\nimport { SessionError, SessionRegistry, SessionRecord } from '../session';\nimport { SessionState } from '../state';\nimport { pickBestTarget } from '../target-matching';\nimport type { TargetHint } from '../target-matching';\n\nconst DEFAULT_MAX_SNAPSHOTS_PER_SESSION = 20;\nconst DEFAULT_MAX_SNAPSHOT_HISTORY = 100;\n\nexport class InspectService {\n private readonly registry: SessionRegistry;\n private readonly debugger?: DebuggerBridge;\n private readonly extensionBridge?: {\n isConnected: () => boolean;\n getStatus: () => { tabs: DriveTabInfo[] };\n request?: <T = unknown>(\n action: DriveAction,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ) => Promise<DriveResponse<T>>;\n };\n private lastError?: InspectError;\n private lastErrorAt?: string;\n private readonly snapshots: SnapshotHistory;\n\n constructor(options: InspectServiceOptions) {\n this.registry = options.registry;\n this.debugger = options.debuggerBridge;\n this.extensionBridge = options.extensionBridge;\n const maxSnapshotsPerSession =\n options.maxSnapshotsPerSession ?? DEFAULT_MAX_SNAPSHOTS_PER_SESSION;\n const maxSnapshotHistory =\n options.maxSnapshotHistory ?? DEFAULT_MAX_SNAPSHOT_HISTORY;\n this.snapshots = new SnapshotHistory({\n maxSnapshotsPerSession,\n maxSnapshotHistory,\n });\n }\n\n isConnected(): boolean {\n return this.debugger?.hasAttachments() ?? false;\n }\n\n getLastError(): { error: InspectError; at: string } | undefined {\n if (!this.lastError || !this.lastErrorAt) {\n const debuggerError = this.debugger?.getLastError();\n if (!debuggerError) {\n return undefined;\n }\n return {\n error: new InspectError(\n 'INSPECT_UNAVAILABLE',\n debuggerError.error.message,\n {\n retryable: debuggerError.error.retryable,\n details: {\n code: debuggerError.error.code,\n ...(debuggerError.error.details\n ? debuggerError.error.details\n : {}),\n },\n }\n ),\n at: debuggerError.at,\n };\n }\n return { error: this.lastError, at: this.lastErrorAt };\n }\n\n async reconnect(sessionId: string): Promise<boolean> {\n try {\n this.requireSession(sessionId);\n const selection = await this.resolveTab();\n const debuggerBridge = this.ensureDebugger();\n const result = await debuggerBridge.attach(selection.tabId);\n if (result.ok) {\n this.markInspectConnected(sessionId);\n return true;\n }\n const error = this.mapDebuggerError(result.error);\n this.recordError(error);\n return false;\n } catch (error) {\n if (error instanceof InspectError) {\n this.recordError(error);\n }\n return false;\n }\n }\n\n async domSnapshot(input: {\n sessionId: string;\n format: 'ax' | 'html';\n consistency: 'best_effort' | 'quiesce';\n interactive?: boolean;\n compact?: boolean;\n maxNodes?: number;\n selector?: string;\n targetHint?: TargetHint;\n }): Promise<DomSnapshotResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n const debuggerCommand = this.debuggerCommand.bind(this);\n\n const work = async (): Promise<DomSnapshotResult> => {\n if (input.format === 'html') {\n const html = await captureHtml(selection.tabId, {\n selector: input.selector,\n debuggerCommand,\n onEvaluationFailed: () => {\n const error = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to evaluate HTML snapshot.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n },\n });\n const warnings = [...(selection.warnings ?? [])];\n if (input.interactive) {\n warnings.push(\n 'Interactive filter is only supported for AX snapshots.'\n );\n }\n if (input.compact) {\n warnings.push('Compact filter is only supported for AX snapshots.');\n }\n if (input.maxNodes !== undefined) {\n warnings.push('max_nodes is only supported for AX snapshots.');\n }\n if (input.selector && html === '') {\n warnings.push(`Selector not found: ${input.selector}`);\n }\n return {\n format: 'html',\n snapshot: html,\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n\n try {\n await this.enableAccessibility(selection.tabId);\n const selectorWarnings: string[] = [];\n let result: unknown;\n if (input.selector) {\n const resolved = await resolveNodeIdForSelector(\n selection.tabId,\n input.selector,\n debuggerCommand\n );\n selectorWarnings.push(...(resolved.warnings ?? []));\n if (!resolved.nodeId) {\n let refWarnings: string[] = [];\n try {\n refWarnings = await applySnapshotRefs(\n selection.tabId,\n new Map(),\n debuggerCommand\n );\n } catch {\n refWarnings = ['Failed to clear prior snapshot refs.'];\n }\n const warnings = [\n ...(selection.warnings ?? []),\n ...selectorWarnings,\n ...refWarnings,\n ];\n return {\n format: 'ax',\n snapshot: { nodes: [] },\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n result = await this.debuggerCommand(\n selection.tabId,\n 'Accessibility.getPartialAXTree',\n { nodeId: resolved.nodeId }\n );\n } else {\n result = await this.debuggerCommand(\n selection.tabId,\n 'Accessibility.getFullAXTree',\n {}\n );\n }\n let snapshot =\n input.interactive || input.compact\n ? applyAxSnapshotFilters(result, {\n interactiveOnly: input.interactive,\n compact: input.compact,\n })\n : result;\n let truncated = false;\n const truncationWarnings: string[] = [];\n if (input.maxNodes !== undefined) {\n const truncatedResult = truncateAxSnapshot(snapshot, input.maxNodes);\n snapshot = truncatedResult.snapshot;\n truncated = truncatedResult.truncated;\n if (truncated) {\n truncationWarnings.push(\n `AX snapshot truncated to ${input.maxNodes} nodes.`\n );\n }\n }\n const refMap = assignRefsToAxSnapshot(snapshot);\n const refWarnings = await applySnapshotRefs(\n selection.tabId,\n refMap,\n debuggerCommand\n );\n const warnings = [\n ...(selection.warnings ?? []),\n ...selectorWarnings,\n ...truncationWarnings,\n ...(refWarnings ?? []),\n ];\n return {\n format: 'ax',\n snapshot,\n ...(truncated ? { truncated: true } : {}),\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n } catch (error) {\n if (error instanceof InspectError) {\n const fallbackCodes: InspectErrorCode[] = [\n 'NOT_SUPPORTED',\n 'INSPECT_UNAVAILABLE',\n 'EVALUATION_FAILED',\n ];\n if (!fallbackCodes.includes(error.code)) {\n throw error;\n }\n const html = await captureHtml(selection.tabId, {\n selector: input.selector,\n debuggerCommand,\n onEvaluationFailed: () => {\n const error = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to evaluate HTML snapshot.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n },\n });\n const warnings = [\n ...(selection.warnings ?? []),\n 'AX snapshot failed; returned HTML instead.',\n ...(input.maxNodes !== undefined\n ? ['max_nodes is only supported for AX snapshots.']\n : []),\n ...(input.interactive\n ? ['Interactive filter is only supported for AX snapshots.']\n : []),\n ...(input.compact\n ? ['Compact filter is only supported for AX snapshots.']\n : []),\n ...(input.selector && html === ''\n ? [`Selector not found: ${input.selector}`]\n : []),\n ];\n return {\n format: 'html',\n snapshot: html,\n warnings,\n };\n }\n throw error;\n }\n };\n\n if (input.consistency === 'quiesce') {\n const result = await driveMutex.runExclusive(work);\n this.snapshots.record(input.sessionId, result);\n this.markInspectConnected(input.sessionId);\n return result;\n }\n const result = await work();\n this.snapshots.record(input.sessionId, result);\n this.markInspectConnected(input.sessionId);\n return result;\n }\n\n domDiff(input: { sessionId: string }): {\n added: string[];\n removed: string[];\n changed: string[];\n summary: string;\n } {\n this.requireSession(input.sessionId);\n this.markInspectConnected(input.sessionId);\n return this.snapshots.diff(input.sessionId);\n }\n\n async find(input: {\n sessionId: string;\n kind: 'role' | 'text' | 'label';\n role?: string;\n name?: string;\n text?: string;\n label?: string;\n targetHint?: TargetHint;\n }): Promise<{\n matches: Array<{ ref: string; role?: string; name?: string }>;\n warnings?: string[];\n }> {\n const snapshot = await this.domSnapshot({\n sessionId: input.sessionId,\n format: 'ax',\n consistency: 'best_effort',\n targetHint: input.targetHint,\n });\n const warnings = [...(snapshot.warnings ?? [])];\n if (snapshot.format !== 'ax') {\n warnings.push('AX snapshot unavailable; cannot resolve refs.');\n return {\n matches: [],\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n\n const nodes = getAxNodes(snapshot.snapshot);\n const matches: Array<{ ref: string; role?: string; name?: string }> = [];\n\n const nameQuery =\n typeof input.name === 'string' ? normalizeQuery(input.name) : '';\n const textQuery =\n typeof input.text === 'string' ? normalizeQuery(input.text) : '';\n const labelQuery =\n typeof input.label === 'string' ? normalizeQuery(input.label) : '';\n const roleQuery =\n typeof input.role === 'string' ? normalizeQuery(input.role) : '';\n\n for (const node of nodes) {\n if (!node || typeof node !== 'object') {\n continue;\n }\n if (typeof node.ref !== 'string' || node.ref.length === 0) {\n continue;\n }\n const role = getAxRole(node);\n const name = getAxName(node);\n\n if (input.kind === 'role') {\n if (!role || role !== roleQuery) {\n continue;\n }\n if (nameQuery && !matchesTextValue(name, nameQuery)) {\n continue;\n }\n } else if (input.kind === 'text') {\n if (!textQuery || !matchesAxText(node, textQuery)) {\n continue;\n }\n } else if (input.kind === 'label') {\n if (!labelQuery || !LABEL_AX_ROLES.has(role)) {\n continue;\n }\n if (!matchesTextValue(name, labelQuery)) {\n continue;\n }\n }\n\n matches.push({\n ref: node.ref,\n ...(role ? { role } : {}),\n ...(name ? { name } : {}),\n });\n }\n\n return {\n matches,\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n\n async consoleList(input: {\n sessionId: string;\n targetHint?: TargetHint;\n }): Promise<ConsoleListResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n await this.enableConsole(selection.tabId);\n\n const events = this.ensureDebugger().getConsoleEvents(selection.tabId);\n const entries = events\n .map((event) => toConsoleEntry(event))\n .filter((entry): entry is ConsoleEntry => entry !== null);\n\n const result = {\n entries,\n warnings: selection.warnings,\n };\n this.markInspectConnected(input.sessionId);\n return result;\n }\n\n async networkHar(input: {\n sessionId: string;\n targetHint?: TargetHint;\n }): Promise<ArtifactInfo> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n await this.enableNetwork(selection.tabId);\n\n const events = this.ensureDebugger().getNetworkEvents(selection.tabId);\n const har = buildHar(events, selection.tab.title);\n\n try {\n const rootDir = await ensureArtifactRootDir(input.sessionId);\n const artifactId = randomUUID();\n const filePath = path.join(rootDir, `har-${artifactId}.json`);\n await writeFile(filePath, JSON.stringify(har, null, 2), 'utf-8');\n const result = {\n artifact_id: artifactId,\n path: filePath,\n mime: 'application/json',\n };\n this.markInspectConnected(input.sessionId);\n return result;\n } catch {\n const error = new InspectError(\n 'ARTIFACT_IO_ERROR',\n 'Failed to write HAR file.'\n );\n this.recordError(error);\n throw error;\n }\n }\n\n async evaluate(input: {\n sessionId: string;\n expression?: string;\n targetHint?: TargetHint;\n }): Promise<EvaluateResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n const expression = input.expression ?? 'undefined';\n\n await this.debuggerCommand(selection.tabId, 'Runtime.enable', {});\n const result = await this.debuggerCommand(\n selection.tabId,\n 'Runtime.evaluate',\n {\n expression,\n returnByValue: true,\n awaitPromise: true,\n }\n );\n\n if (result && typeof result === 'object' && 'exceptionDetails' in result) {\n const output = {\n exception: (result as { exceptionDetails?: unknown }).exceptionDetails,\n warnings: selection.warnings,\n };\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n const output = {\n value: (result as { result?: { value?: unknown } })?.result?.value,\n warnings: selection.warnings,\n };\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n async extractContent(input: {\n sessionId: string;\n format: 'markdown' | 'text' | 'article_json';\n includeMetadata?: boolean;\n targetHint?: TargetHint;\n }): Promise<ExtractContentResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n\n const debuggerCommand = this.debuggerCommand.bind(this);\n const html = await captureHtml(selection.tabId, {\n debuggerCommand,\n onEvaluationFailed: () => {\n const error = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to evaluate HTML snapshot.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n },\n });\n const url = selection.tab.url ?? 'about:blank';\n let article: ReturnType<Readability['parse']> | null = null;\n try {\n const dom = new JSDOM(html, { url });\n const reader = new Readability(dom.window.document);\n article = reader.parse();\n } catch {\n const err = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to parse page content.',\n { retryable: false }\n );\n this.recordError(err);\n throw err;\n }\n\n if (!article) {\n const err = new InspectError(\n 'NOT_SUPPORTED',\n 'Readability could not extract content.',\n { retryable: false }\n );\n this.recordError(err);\n throw err;\n }\n\n let content = '';\n if (input.format === 'article_json') {\n content = JSON.stringify(article, null, 2);\n } else if (input.format === 'text') {\n content = article.textContent ?? '';\n } else {\n const turndown = new TurndownService();\n content = turndown.turndown(article.content ?? '');\n }\n\n const warnings = selection.warnings ?? [];\n const includeMetadata = input.includeMetadata ?? true;\n const output: ExtractContentResult = {\n content,\n ...(includeMetadata\n ? {\n title: article.title ?? undefined,\n byline: article.byline ?? undefined,\n excerpt: article.excerpt ?? undefined,\n siteName: (article as { siteName?: string }).siteName ?? undefined,\n }\n : {}),\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n async pageState(input: {\n sessionId: string;\n targetHint?: TargetHint;\n }): Promise<PageStateResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n\n await this.debuggerCommand(selection.tabId, 'Runtime.enable', {});\n const expression = PAGE_STATE_SCRIPT;\n\n const result = await this.debuggerCommand(\n selection.tabId,\n 'Runtime.evaluate',\n {\n expression,\n returnByValue: true,\n awaitPromise: true,\n }\n );\n\n if (result && typeof result === 'object' && 'exceptionDetails' in result) {\n const error = new InspectError(\n 'EVALUATION_FAILED',\n 'Failed to capture page state.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n }\n\n const value = (result as { result?: { value?: unknown } })?.result?.value;\n const raw =\n value && typeof value === 'object'\n ? (value as Partial<PageStateResult>)\n : {};\n const warnings = [\n ...(Array.isArray(raw.warnings) ? raw.warnings : []),\n ...(selection.warnings ?? []),\n ];\n const output: PageStateResult = {\n forms: Array.isArray(raw.forms) ? (raw.forms as FormInfo[]) : [],\n localStorage: Array.isArray(raw.localStorage)\n ? (raw.localStorage as StorageEntry[])\n : [],\n sessionStorage: Array.isArray(raw.sessionStorage)\n ? (raw.sessionStorage as StorageEntry[])\n : [],\n cookies: Array.isArray(raw.cookies)\n ? (raw.cookies as StorageEntry[])\n : [],\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n async performanceMetrics(input: {\n sessionId: string;\n targetHint?: TargetHint;\n }): Promise<PerformanceMetricsResult> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n\n await this.debuggerCommand(selection.tabId, 'Performance.enable', {});\n const result = await this.debuggerCommand(\n selection.tabId,\n 'Performance.getMetrics',\n {}\n );\n const metrics = Array.isArray((result as { metrics?: unknown[] })?.metrics)\n ? (\n result as { metrics: Array<{ name: string; value: number }> }\n ).metrics.map((metric) => ({\n name: metric.name,\n value: metric.value,\n }))\n : [];\n\n const output = { metrics, warnings: selection.warnings };\n this.markInspectConnected(input.sessionId);\n return output;\n }\n\n async screenshot(input: {\n sessionId: string;\n target: 'viewport' | 'full';\n selector?: string;\n format?: 'png' | 'jpeg' | 'webp';\n quality?: number;\n targetHint?: TargetHint;\n }): Promise<ArtifactInfo> {\n this.requireSession(input.sessionId);\n const selection = await this.resolveTab(input.targetHint);\n\n const format = input.format ?? 'png';\n const writeArtifact = async (data: string): Promise<ArtifactInfo> => {\n try {\n const rootDir = await ensureArtifactRootDir(input.sessionId);\n const artifactId = randomUUID();\n const extension = format === 'jpeg' ? 'jpg' : format;\n const filePath = path.join(\n rootDir,\n `screenshot-${artifactId}.${extension}`\n );\n await writeFile(filePath, Buffer.from(data, 'base64'));\n const mime = format === 'jpeg' ? 'image/jpeg' : `image/${format}`;\n const output = {\n artifact_id: artifactId,\n path: filePath,\n mime,\n };\n this.markInspectConnected(input.sessionId);\n return output;\n } catch {\n const error = new InspectError(\n 'ARTIFACT_IO_ERROR',\n 'Failed to write screenshot file.'\n );\n this.recordError(error);\n throw error;\n }\n };\n\n if (input.selector) {\n if (!this.extensionBridge?.request) {\n const error = new InspectError(\n 'NOT_SUPPORTED',\n 'Element screenshots require an extension that supports drive.screenshot.'\n );\n this.recordError(error);\n throw error;\n }\n\n const response =\n await this.extensionBridge.request<DriveScreenshotResult>(\n 'drive.screenshot',\n {\n tab_id: selection.tabId,\n mode: 'element',\n selector: input.selector,\n format,\n ...(typeof input.quality === 'number'\n ? { quality: input.quality }\n : {}),\n },\n 120000\n );\n\n if (response.status === 'error') {\n const error = new InspectError(\n (response.error?.code as InspectErrorCode) ?? 'INSPECT_UNAVAILABLE',\n response.error?.message ?? 'Failed to capture element screenshot.',\n {\n retryable: response.error?.retryable ?? false,\n ...(response.error?.details\n ? { details: response.error.details }\n : {}),\n }\n );\n this.recordError(error);\n throw error;\n }\n\n const result = response.result;\n if (!result?.data_base64 || typeof result.data_base64 !== 'string') {\n const error = new InspectError(\n 'INSPECT_UNAVAILABLE',\n 'Failed to capture element screenshot.'\n );\n this.recordError(error);\n throw error;\n }\n\n return await writeArtifact(result.data_base64);\n }\n\n if (input.target === 'full' && this.extensionBridge?.request) {\n try {\n const response =\n await this.extensionBridge.request<DriveScreenshotResult>(\n 'drive.screenshot',\n {\n tab_id: selection.tabId,\n mode: 'full_page',\n format,\n ...(typeof input.quality === 'number'\n ? { quality: input.quality }\n : {}),\n },\n 120000\n );\n\n if (response.status === 'error') {\n const error = new InspectError(\n (response.error?.code as InspectErrorCode) ?? 'INSPECT_UNAVAILABLE',\n response.error?.message ??\n 'Failed to capture full page screenshot.',\n {\n retryable: response.error?.retryable ?? false,\n ...(response.error?.details\n ? { details: response.error.details }\n : {}),\n }\n );\n this.recordError(error);\n throw error;\n }\n\n const result = response.result;\n if (!result?.data_base64 || typeof result.data_base64 !== 'string') {\n const error = new InspectError(\n 'INSPECT_UNAVAILABLE',\n 'Failed to capture full page screenshot.'\n );\n this.recordError(error);\n throw error;\n }\n\n return await writeArtifact(result.data_base64);\n } catch (error) {\n // Fall back to CDP screenshots for environments that don't yet support\n // extension-driven full page capture.\n if (error instanceof InspectError) {\n const code = String(error.code);\n if (\n ![\n 'NOT_SUPPORTED',\n 'NOT_IMPLEMENTED',\n 'INSPECT_UNAVAILABLE',\n ].includes(code)\n ) {\n throw error;\n }\n }\n }\n }\n\n await this.debuggerCommand(selection.tabId, 'Page.enable', {});\n\n let captureParams: Record<string, unknown> = {\n format,\n fromSurface: true,\n };\n if (format !== 'png' && typeof input.quality === 'number') {\n captureParams = { ...captureParams, quality: input.quality };\n }\n\n if (input.target === 'full') {\n const layout = await this.debuggerCommand(\n selection.tabId,\n 'Page.getLayoutMetrics',\n {}\n );\n const contentSize = (\n layout as { contentSize?: { width: number; height: number } }\n )?.contentSize;\n if (contentSize) {\n captureParams = {\n ...captureParams,\n clip: {\n x: 0,\n y: 0,\n width: contentSize.width,\n height: contentSize.height,\n scale: 1,\n },\n };\n } else {\n captureParams = { ...captureParams, captureBeyondViewport: true };\n }\n }\n\n const result = await this.debuggerCommand(\n selection.tabId,\n 'Page.captureScreenshot',\n captureParams\n );\n const data = (result as { data?: string }).data;\n if (!data) {\n const error = new InspectError(\n 'INSPECT_UNAVAILABLE',\n 'Failed to capture screenshot.',\n { retryable: false }\n );\n this.recordError(error);\n throw error;\n }\n\n return await writeArtifact(data);\n }\n\n private ensureDebugger(): DebuggerBridge {\n if (!this.debugger) {\n const error = this.buildUnavailableError();\n this.recordError(error);\n throw error;\n }\n return this.debugger;\n }\n\n private async resolveTab(\n hint?: TargetHint\n ): Promise<{ tabId: number; tab: DriveTabInfo; warnings?: string[] }> {\n if (!this.extensionBridge || !this.extensionBridge.isConnected()) {\n const error = new InspectError(\n 'EXTENSION_DISCONNECTED',\n 'Extension is not connected.',\n { retryable: true }\n );\n this.recordError(error);\n throw error;\n }\n\n const tabs = this.extensionBridge.getStatus().tabs ?? [];\n if (!Array.isArray(tabs) || tabs.length === 0) {\n const error = new InspectError(\n 'TAB_NOT_FOUND',\n 'No tabs available to inspect.'\n );\n this.recordError(error);\n throw error;\n }\n\n const candidates = tabs.map((tab) => ({\n id: String(tab.tab_id),\n url: tab.url ?? '',\n title: tab.title,\n lastSeenAt: tab.last_active_at\n ? Date.parse(tab.last_active_at)\n : undefined,\n }));\n\n const ranked = pickBestTarget(candidates, hint);\n if (!ranked) {\n const error = new InspectError('TAB_NOT_FOUND', 'No matching tab found.');\n this.recordError(error);\n throw error;\n }\n\n const tabId = Number(ranked.candidate.id);\n if (!Number.isFinite(tabId)) {\n const error = new InspectError(\n 'TAB_NOT_FOUND',\n 'Resolved tab id is invalid.'\n );\n this.recordError(error);\n throw error;\n }\n\n const tab = tabs.find((entry) => entry.tab_id === tabId) ?? tabs[0];\n const warnings: string[] = [];\n if (!hint) {\n warnings.push('No target hint provided; using the most recent tab.');\n } else if (ranked.score < 20) {\n warnings.push('Weak target match; using best available tab.');\n }\n\n return {\n tabId,\n tab,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n\n private async enableConsole(tabId: number): Promise<void> {\n await this.debuggerCommand(tabId, 'Runtime.enable', {});\n await this.debuggerCommand(tabId, 'Log.enable', {});\n }\n\n private async enableNetwork(tabId: number): Promise<void> {\n await this.debuggerCommand(tabId, 'Network.enable', {});\n }\n\n private async enableAccessibility(tabId: number): Promise<void> {\n await this.debuggerCommand(tabId, 'Accessibility.enable', {});\n }\n\n private async debuggerCommand(\n tabId: number,\n method: string,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ): Promise<unknown> {\n const debuggerBridge = this.ensureDebugger();\n const result = await debuggerBridge.command(\n tabId,\n method,\n params,\n timeoutMs\n );\n if (!result.ok) {\n const error = this.mapDebuggerError(result.error);\n this.recordError(error);\n throw error;\n }\n return result.result;\n }\n\n private mapDebuggerError(error: DriveErrorInfo): InspectError {\n const allowed: InspectErrorCode[] = [\n 'INSPECT_UNAVAILABLE',\n 'EXTENSION_DISCONNECTED',\n 'DEBUGGER_IN_USE',\n 'ATTACH_DENIED',\n 'TAB_NOT_FOUND',\n 'NOT_SUPPORTED',\n 'TIMEOUT',\n 'EVALUATION_FAILED',\n 'ARTIFACT_IO_ERROR',\n 'INVALID_ARGUMENT',\n 'INTERNAL',\n ];\n\n const code = allowed.includes(error.code as InspectErrorCode)\n ? (error.code as InspectErrorCode)\n : 'INSPECT_UNAVAILABLE';\n return new InspectError(code, error.message, {\n retryable: error.retryable,\n details: error.details,\n });\n }\n\n private markInspectConnected(sessionId: string): void {\n this.clearLastError();\n try {\n const session = this.registry.require(sessionId);\n if (\n session.state === SessionState.INIT ||\n session.state === SessionState.DRIVE_READY\n ) {\n this.registry.apply(sessionId, 'INSPECT_CONNECTED');\n } else if (session.state === SessionState.DEGRADED_INSPECT) {\n this.registry.apply(sessionId, 'RECOVER_SUCCEEDED');\n }\n } catch {\n // Ignore invalid transitions.\n }\n }\n\n private recordError(error: InspectError): void {\n this.lastError = error;\n this.lastErrorAt = new Date().toISOString();\n }\n\n private clearLastError(): void {\n this.lastError = undefined;\n this.lastErrorAt = undefined;\n }\n\n private buildUnavailableError(): InspectError {\n return new InspectError(\n 'INSPECT_UNAVAILABLE',\n 'Inspect is not available until the debugger bridge is configured.',\n { retryable: false }\n );\n }\n\n private requireSession(sessionId: string): SessionRecord {\n try {\n return this.registry.require(sessionId);\n } catch (error) {\n if (error instanceof SessionError) {\n const code =\n error.code === 'SESSION_CLOSED'\n ? 'SESSION_CLOSED'\n : 'SESSION_NOT_FOUND';\n const wrapped = new InspectError(code, error.message);\n this.recordError(wrapped);\n throw wrapped;\n }\n const wrapped = new InspectError('INTERNAL', 'Failed to load session.');\n this.recordError(wrapped);\n throw wrapped;\n }\n }\n}\n\nexport const createInspectService = (\n options: InspectServiceOptions\n): InspectService => new InspectService(options);\n", "import { mkdir } from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\nconst ARTIFACTS_DIR_NAME = 'browser-agent';\n\nconst resolveTempRoot = (): string =>\n process.env.TMPDIR || process.env.TEMP || process.env.TMP || os.tmpdir();\n\nexport const getArtifactRootDir = (sessionId: string): string =>\n path.join(resolveTempRoot(), ARTIFACTS_DIR_NAME, sessionId);\n\nexport const ensureArtifactRootDir = async (\n sessionId: string\n): Promise<string> => {\n const rootDir = getArtifactRootDir(sessionId);\n await mkdir(rootDir, { recursive: true });\n return rootDir;\n};\n", "import { randomUUID } from 'crypto';\nimport type { Server } from 'http';\nimport type { RawData } from 'ws';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport type {\n DebuggerEvent,\n DebuggerRequestAction,\n DebuggerResponse,\n DriveAction,\n DriveErrorInfo,\n DriveResponse,\n DriveTabInfo,\n ExtensionEvent,\n ExtensionMessage,\n ExtensionRequest,\n ExtensionRequestAction,\n ExtensionResponse,\n} from './drive-protocol';\nimport { SessionRegistry } from './session';\nimport { SessionState } from './state';\n\nexport type ExtensionBridgeStatus = {\n connected: boolean;\n lastSeenAt?: string;\n tabs: DriveTabInfo[];\n};\n\ntype PendingRequest = {\n resolve: (response: ExtensionResponse) => void;\n reject: (error: ExtensionBridgeError) => void;\n timeout: ReturnType<typeof setTimeout>;\n};\n\ntype DebuggerEventListener = (event: DebuggerEvent) => void;\n\nexport class ExtensionBridgeError extends Error {\n public readonly code: string;\n public readonly retryable: boolean;\n public readonly details?: Record<string, unknown>;\n\n constructor(\n code: string,\n message: string,\n retryable = false,\n details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'ExtensionBridgeError';\n this.code = code;\n this.retryable = retryable;\n this.details = details;\n }\n}\n\nexport type ExtensionBridgeOptions = {\n path?: string;\n registry?: SessionRegistry;\n heartbeatIntervalMs?: number;\n heartbeatTimeoutMs?: number;\n};\n\nexport class ExtensionBridge {\n private readonly wss: WebSocketServer;\n private socket: WebSocket | null = null;\n private pending = new Map<string, PendingRequest>();\n private connected = false;\n private lastSeenAt?: string;\n private tabs: DriveTabInfo[] = [];\n private badMessageLogsRemaining = 3;\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n private awaitingHeartbeat = false;\n private readonly heartbeatIntervalMs: number;\n private readonly heartbeatTimeoutMs: number;\n private readonly path: string;\n private readonly registry?: SessionRegistry;\n private readonly debuggerListeners = new Set<DebuggerEventListener>();\n\n constructor(options: ExtensionBridgeOptions = {}) {\n this.wss = new WebSocketServer({ noServer: true });\n this.path = options.path ?? '/drive';\n this.registry = options.registry;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? 15000;\n this.heartbeatTimeoutMs = options.heartbeatTimeoutMs ?? 5000;\n\n this.wss.on('connection', (socket) => {\n this.handleConnection(socket);\n });\n }\n\n attach(server: Server): void {\n server.on('upgrade', (request, socket, head) => {\n const url = new URL(request.url ?? '', 'ws://127.0.0.1');\n if (url.pathname !== this.path) {\n socket.destroy();\n return;\n }\n\n this.wss.handleUpgrade(request, socket, head, (ws) => {\n this.wss.emit('connection', ws, request);\n });\n });\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n getStatus(): ExtensionBridgeStatus {\n return {\n connected: this.connected,\n lastSeenAt: this.lastSeenAt,\n tabs: this.tabs,\n };\n }\n\n async request<T = unknown>(\n action: DriveAction,\n params?: Record<string, unknown>,\n timeoutMs = 30000\n ): Promise<DriveResponse<T>> {\n const response = await this.requestInternal(action, params, timeoutMs);\n return response as DriveResponse<T>;\n }\n\n async requestDebugger<T = unknown>(\n action: DebuggerRequestAction,\n params?: Record<string, unknown>,\n timeoutMs = 30000\n ): Promise<DebuggerResponse<T>> {\n const response = await this.requestInternal(action, params, timeoutMs);\n return response as DebuggerResponse<T>;\n }\n\n onDebuggerEvent(listener: DebuggerEventListener): () => void {\n this.debuggerListeners.add(listener);\n return () => {\n this.debuggerListeners.delete(listener);\n };\n }\n\n private async requestInternal(\n action: ExtensionRequestAction,\n params?: Record<string, unknown>,\n timeoutMs = 30000\n ): Promise<ExtensionResponse> {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n throw new ExtensionBridgeError(\n 'EXTENSION_DISCONNECTED',\n 'Extension is not connected.',\n true\n );\n }\n\n const id = randomUUID();\n const request: ExtensionRequest =\n typeof action === 'string' && action.startsWith('debugger.')\n ? {\n id,\n action: action as DebuggerRequestAction,\n status: 'request',\n params,\n }\n : {\n id,\n action: action as DriveAction,\n status: 'request',\n params,\n };\n\n const response = await new Promise<ExtensionResponse>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(id);\n reject(\n new ExtensionBridgeError(\n 'TIMEOUT',\n `Extension request timed out after ${timeoutMs}ms.`,\n true,\n { action }\n )\n );\n }, timeoutMs);\n\n this.pending.set(id, {\n resolve,\n reject,\n timeout,\n });\n\n this.socket?.send(JSON.stringify(request));\n });\n\n return response;\n }\n\n private startHeartbeat(): void {\n if (this.heartbeatInterval) {\n return;\n }\n this.heartbeatInterval = setInterval(() => {\n void this.sendHeartbeat();\n }, this.heartbeatIntervalMs);\n void this.sendHeartbeat();\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n this.awaitingHeartbeat = false;\n }\n\n private async sendHeartbeat(): Promise<void> {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n return;\n }\n if (this.awaitingHeartbeat) {\n return;\n }\n this.awaitingHeartbeat = true;\n try {\n await this.requestInternal(\n 'drive.ping',\n undefined,\n this.heartbeatTimeoutMs\n );\n } catch (error) {\n console.warn('Extension heartbeat failed:', error);\n this.forceDisconnect();\n } finally {\n this.awaitingHeartbeat = false;\n }\n }\n\n private forceDisconnect(): void {\n if (this.socket && this.socket.readyState === WebSocket.OPEN) {\n try {\n this.socket.terminate();\n } catch (error) {\n console.debug(\n 'Extension socket terminate failed; falling back to close().',\n error\n );\n this.socket.close();\n }\n }\n this.handleDisconnect();\n }\n\n private handleConnection(socket: WebSocket): void {\n if (this.socket && this.socket.readyState === WebSocket.OPEN) {\n this.socket.close();\n }\n\n this.socket = socket;\n this.connected = true;\n this.lastSeenAt = new Date().toISOString();\n\n this.applyDriveConnected();\n this.startHeartbeat();\n\n socket.on('message', (data) => {\n this.handleMessage(data);\n });\n\n socket.on('close', () => {\n this.handleDisconnect();\n });\n\n socket.on('error', () => {\n this.handleDisconnect();\n });\n }\n\n private handleDisconnect(): void {\n if (!this.connected) {\n return;\n }\n\n this.stopHeartbeat();\n this.connected = false;\n this.socket = null;\n this.lastSeenAt = new Date().toISOString();\n this.applyDriveDisconnected();\n\n for (const [id, pending] of this.pending.entries()) {\n clearTimeout(pending.timeout);\n pending.reject(\n new ExtensionBridgeError(\n 'EXTENSION_DISCONNECTED',\n 'Extension disconnected before responding.',\n true,\n { request_id: id }\n )\n );\n this.pending.delete(id);\n }\n }\n\n private handleMessage(data: RawData): void {\n const text = typeof data === 'string' ? data : data.toString();\n\n let message: ExtensionMessage | null = null;\n try {\n message = JSON.parse(text) as ExtensionMessage;\n } catch (error) {\n if (this.badMessageLogsRemaining > 0) {\n this.badMessageLogsRemaining -= 1;\n console.debug('Failed to parse extension message.', error);\n }\n return;\n }\n\n if (!message || typeof message !== 'object') {\n return;\n }\n\n this.lastSeenAt = new Date().toISOString();\n\n if (message.status === 'event') {\n this.handleEvent(message as ExtensionEvent);\n return;\n }\n\n if (\n message.status === 'ok' ||\n message.status === 'error' ||\n message.status === 'ack'\n ) {\n const pending = this.pending.get(message.id);\n if (!pending) {\n return;\n }\n clearTimeout(pending.timeout);\n this.pending.delete(message.id);\n pending.resolve(message as ExtensionResponse);\n }\n }\n\n private handleEvent(message: ExtensionEvent): void {\n if (\n message.action === 'drive.hello' ||\n message.action === 'drive.tab_report'\n ) {\n const tabs = (message.params as { tabs?: DriveTabInfo[] } | undefined)\n ?.tabs;\n if (Array.isArray(tabs)) {\n this.tabs = tabs;\n }\n }\n\n if (\n typeof message.action === 'string' &&\n message.action.startsWith('debugger.')\n ) {\n this.emitDebuggerEvent(message as DebuggerEvent);\n }\n }\n\n private emitDebuggerEvent(event: DebuggerEvent): void {\n for (const listener of this.debuggerListeners) {\n try {\n listener(event);\n } catch (error) {\n console.debug('Debugger event listener failed.', error);\n }\n }\n }\n\n private applyDriveConnected(): void {\n if (!this.registry) {\n return;\n }\n\n for (const session of this.registry.list()) {\n try {\n if (session.state === SessionState.INIT) {\n this.registry.apply(session.id, 'DRIVE_CONNECTED');\n } else if (session.state === SessionState.INSPECT_READY) {\n this.registry.apply(session.id, 'DRIVE_CONNECTED');\n } else if (session.state === SessionState.DEGRADED_DRIVE) {\n this.registry.apply(session.id, 'RECOVER_SUCCEEDED');\n }\n } catch (error) {\n console.debug(\n `Drive connect transition ignored for session ${session.id} (${session.state}).`,\n error\n );\n }\n }\n }\n\n private applyDriveDisconnected(): void {\n if (!this.registry) {\n return;\n }\n\n for (const session of this.registry.list()) {\n try {\n if (session.state === SessionState.READY) {\n this.registry.apply(session.id, 'DRIVE_DISCONNECTED');\n }\n } catch (error) {\n console.debug(\n `Drive disconnect transition ignored for session ${session.id} (${session.state}).`,\n error\n );\n }\n }\n }\n}\n\nexport const toDriveError = (error: ExtensionBridgeError): DriveErrorInfo => ({\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n ...(error.details ? { details: error.details } : {}),\n});\n", "import type { DriveAction, DriveErrorInfo } from './drive-protocol';\nimport {\n ExtensionBridge,\n ExtensionBridgeError,\n toDriveError,\n} from './extension-bridge';\nimport { SessionError, SessionRegistry } from './session';\nimport { SessionState, shouldRetryDriveOp } from './state';\n\nexport type DriveResult<T> =\n | { ok: true; result: T }\n | { ok: false; error: DriveErrorInfo };\n\nclass DriveMutex {\n private tail = Promise.resolve();\n\n async runExclusive<T>(work: () => T | Promise<T>): Promise<T> {\n const result = this.tail.then(work, work);\n this.tail = result.then(\n () => undefined,\n () => undefined\n );\n return await result;\n }\n}\n\nexport const driveMutex = new DriveMutex();\n\nexport class DriveController {\n private readonly bridge: ExtensionBridge;\n private readonly registry: SessionRegistry;\n private lastError?: DriveErrorInfo;\n private lastErrorAt?: string;\n\n constructor(bridge: ExtensionBridge, registry: SessionRegistry) {\n this.bridge = bridge;\n this.registry = registry;\n }\n\n getLastError(): { error: DriveErrorInfo; at: string } | undefined {\n if (!this.lastError || !this.lastErrorAt) {\n return undefined;\n }\n return { error: this.lastError, at: this.lastErrorAt };\n }\n\n private recordError(error: DriveErrorInfo): void {\n this.lastError = error;\n this.lastErrorAt = new Date().toISOString();\n }\n\n private clearLastError(): void {\n this.lastError = undefined;\n this.lastErrorAt = undefined;\n }\n\n async execute<T>(\n sessionId: string,\n action: DriveAction,\n params?: Record<string, unknown>,\n timeoutMs?: number\n ): Promise<DriveResult<T>> {\n return await driveMutex.runExclusive(async () => {\n try {\n this.registry.require(sessionId);\n } catch (error) {\n if (error instanceof SessionError) {\n const errorInfo: DriveErrorInfo = {\n code: error.code,\n message: error.message,\n retryable: false,\n };\n this.recordError(errorInfo);\n return {\n ok: false,\n error: errorInfo,\n };\n }\n const errorInfo: DriveErrorInfo = {\n code: 'INTERNAL',\n message: 'Unexpected error while validating session.',\n retryable: false,\n };\n this.recordError(errorInfo);\n return {\n ok: false,\n error: errorInfo,\n };\n }\n\n if (this.bridge.isConnected()) {\n this.ensureDriveReady(sessionId);\n }\n\n let attempt = 0;\n while (true) {\n try {\n const response = await this.bridge.request<T>(\n action,\n params,\n timeoutMs\n );\n if (response.status === 'ok') {\n this.clearLastError();\n return {\n ok: true,\n result: response.result as T,\n };\n }\n\n const errorInfo: DriveErrorInfo = response.error ?? {\n code: 'UNKNOWN',\n message: 'Drive operation failed.',\n retryable: false,\n };\n\n if (shouldRetryDriveOp({ attempt, retryable: errorInfo.retryable })) {\n attempt += 1;\n continue;\n }\n\n this.recordError(errorInfo);\n return { ok: false, error: errorInfo };\n } catch (error) {\n if (error instanceof ExtensionBridgeError) {\n if (error.code === 'EXTENSION_DISCONNECTED') {\n this.applyDriveDisconnected(sessionId);\n }\n const errorInfo = toDriveError(error);\n if (\n shouldRetryDriveOp({ attempt, retryable: errorInfo.retryable })\n ) {\n attempt += 1;\n continue;\n }\n this.recordError(errorInfo);\n return { ok: false, error: errorInfo };\n }\n\n const errorInfo: DriveErrorInfo = {\n code: 'INTERNAL',\n message: 'Unexpected error while executing drive action.',\n retryable: false,\n };\n this.recordError(errorInfo);\n return {\n ok: false,\n error: errorInfo,\n };\n }\n }\n });\n }\n\n private ensureDriveReady(sessionId: string): void {\n try {\n const session = this.registry.require(sessionId);\n if (session.state === SessionState.INIT) {\n this.registry.apply(sessionId, 'DRIVE_CONNECTED');\n } else if (session.state === SessionState.INSPECT_READY) {\n this.registry.apply(sessionId, 'DRIVE_CONNECTED');\n } else if (session.state === SessionState.DEGRADED_DRIVE) {\n this.registry.apply(sessionId, 'RECOVER_SUCCEEDED');\n }\n } catch (error) {\n console.debug(\n `Drive ready transition ignored for session ${sessionId}.`,\n error\n );\n }\n }\n\n private applyDriveDisconnected(sessionId: string): void {\n try {\n const session = this.registry.require(sessionId);\n if (session.state === SessionState.READY) {\n this.registry.apply(sessionId, 'DRIVE_DISCONNECTED');\n }\n } catch (error) {\n console.debug(\n `Drive disconnect transition ignored for session ${sessionId}.`,\n error\n );\n }\n }\n}\n", "export const PAGE_STATE_SCRIPT = [\n '(() => {',\n ' const escape = (value) => {',\n \" if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\",\n ' return CSS.escape(value);',\n ' }',\n \" return String(value).replace(/[\\\"'\\\\\\\\]/g, '\\\\\\\\$&');\",\n ' };',\n ' const truncate = (value, max) => {',\n \" const text = String(value ?? '');\",\n ' return text.length > max ? text.slice(0, max) : text;',\n ' };',\n ' const selectorFor = (element) => {',\n ' if (element.id) {',\n ' return `#${escape(element.id)}`;',\n ' }',\n \" const name = element.getAttribute('name');\",\n ' if (name) {',\n ' return `${element.tagName.toLowerCase()}[name=\"${escape(name)}\"]`;',\n ' }',\n ' const parts = [];',\n ' let node = element;',\n ' while (node && node.nodeType === 1 && parts.length < 4) {',\n ' let part = node.tagName.toLowerCase();',\n ' const parent = node.parentElement;',\n ' if (parent) {',\n ' const siblings = Array.from(parent.children).filter(',\n ' (child) => child.tagName === node.tagName',\n ' );',\n ' if (siblings.length > 1) {',\n ' part += `:nth-of-type(${siblings.indexOf(node) + 1})`;',\n ' }',\n ' }',\n ' parts.unshift(part);',\n ' node = parent;',\n ' }',\n \" return parts.join('>');\",\n ' };',\n ' const readStorage = (storage, limit) => {',\n ' try {',\n ' return Object.keys(storage)',\n ' .slice(0, limit)',\n ' .map((key) => ({',\n ' key,',\n ' value: truncate(storage.getItem(key), 500),',\n ' }));',\n ' } catch {',\n ' return [];',\n ' }',\n ' };',\n \" const forms = Array.from(document.querySelectorAll('form')).map((form) => {\",\n ' const fields = Array.from(form.elements)',\n ' .filter((element) => element && element.tagName)',\n ' .map((element) => {',\n ' const tag = element.tagName.toLowerCase();',\n \" const type = 'type' in element && element.type ? element.type : tag;\",\n \" const name = element.name || element.getAttribute('name') || element.id || '';\",\n \" let value = '';\",\n ' let options;',\n \" if (tag === 'select') {\",\n ' const select = element;',\n \" value = select.value ?? '';\",\n ' options = Array.from(select.options).map((option) => option.text);',\n \" } else if (tag === 'input' && element.type === 'password') {\",\n \" value = '[redacted]';\",\n \" } else if (tag === 'input' || tag === 'textarea') {\",\n \" value = element.value ?? '';\",\n ' } else if (element.isContentEditable) {',\n \" value = element.textContent ?? '';\",\n \" } else if ('value' in element) {\",\n \" value = element.value ?? '';\",\n ' }',\n ' return {',\n ' name,',\n ' type,',\n ' value: truncate(value, 500),',\n ' ...(options ? { options } : {}),',\n ' };',\n ' });',\n ' return {',\n ' selector: selectorFor(form),',\n \" action: form.getAttribute('action') || undefined,\",\n \" method: form.getAttribute('method') || undefined,\",\n ' fields,',\n ' };',\n ' });',\n ' const localStorage = readStorage(window.localStorage, 100);',\n ' const sessionStorage = readStorage(window.sessionStorage, 100);',\n \" const cookies = (document.cookie ? document.cookie.split(';') : [])\",\n ' .map((entry) => entry.trim())',\n ' .filter((entry) => entry.length > 0)',\n ' .slice(0, 50)',\n ' .map((entry) => {',\n \" const [key, ...rest] = entry.split('=');\",\n \" return { key, value: truncate(rest.join('='), 500) };\",\n ' });',\n ' return { forms, localStorage, sessionStorage, cookies };',\n '})()',\n].join('\\n');\n", "import { getArtifactRootDir } from './artifacts';\nimport type { RecoveryAttempt, RecoveryMetrics } from './recovery';\n\nexport type DiagnosticCheck = {\n name: string;\n ok: boolean;\n message?: string;\n details?: Record<string, unknown>;\n};\n\nexport type DiagnosticReport = {\n ok: boolean;\n session_id?: string;\n checks?: DiagnosticCheck[];\n sessions?: {\n count?: number;\n max_age_ms?: number;\n max_idle_ms?: number;\n };\n extension?: {\n connected?: boolean;\n version?: string;\n last_seen_at?: string;\n };\n debugger?: {\n attached?: boolean;\n idle_timeout_ms?: number;\n console_buffer_size?: number;\n network_buffer_size?: number;\n last_error?: {\n code: string;\n message: string;\n retryable: boolean;\n details?: Record<string, unknown>;\n };\n };\n artifacts?: {\n root_dir?: string;\n };\n recovery?: {\n last_attempt?: {\n session_id: string;\n recovered: boolean;\n state: string;\n message?: string;\n at: string;\n };\n attempts?: {\n session_id: string;\n recovered: boolean;\n state: string;\n message?: string;\n at: string;\n }[];\n success_count?: number;\n failure_count?: number;\n success_rate?: number;\n recent_failure_count?: number;\n loop_detected?: boolean;\n };\n warnings?: string[];\n notes?: string[];\n};\n\nexport type DiagnosticsContext = {\n sessionState?: string;\n sessions?: {\n count: number;\n maxAgeMs?: number;\n maxIdleMs?: number;\n };\n extension?: {\n connected: boolean;\n lastSeenAt?: string;\n };\n debugger?: {\n attached: boolean;\n idle_timeout_ms: number;\n console_buffer_size: number;\n network_buffer_size: number;\n last_error?: {\n code: string;\n message: string;\n retryable: boolean;\n details?: Record<string, unknown>;\n };\n };\n driveLastError?: {\n code: string;\n message: string;\n retryable: boolean;\n at: string;\n };\n inspectLastError?: {\n code: string;\n message: string;\n retryable: boolean;\n at: string;\n };\n recoveryAttempt?: RecoveryAttempt;\n recoveryMetrics?: RecoveryMetrics;\n};\n\nconst STALE_ERROR_THRESHOLD_MS = 2 * 60 * 1000;\n\nconst getErrorAgeMs = (timestamp: string): number | undefined => {\n const parsed = Date.parse(timestamp);\n if (!Number.isFinite(parsed)) {\n return undefined;\n }\n return Math.max(0, Date.now() - parsed);\n};\n\nexport const buildDiagnosticReport = (\n sessionId?: string,\n context: DiagnosticsContext = {}\n): DiagnosticReport => {\n const extensionConnected = context.extension?.connected ?? false;\n const debuggerAttached = context.debugger?.attached ?? false;\n const sessionState = context.sessionState;\n const hasSessionId = Boolean(sessionId);\n const warnings: string[] = [];\n\n const checks: DiagnosticCheck[] = [\n {\n name: 'extension.connected',\n ok: extensionConnected,\n message: extensionConnected\n ? 'Extension is connected.'\n : 'Extension is not connected.',\n },\n {\n name: 'debugger.attached',\n ok: true,\n message: debuggerAttached\n ? 'Debugger is attached.'\n : 'Debugger is not attached (inspect is idle).',\n },\n {\n name: 'session.state',\n ok: hasSessionId ? Boolean(sessionState) : true,\n message: sessionState\n ? `Session state is ${sessionState}.`\n : hasSessionId\n ? 'Session state unavailable.'\n : 'Session id not provided.',\n details: {\n session_id: sessionId || null,\n state: sessionState ?? 'UNKNOWN',\n },\n },\n ];\n\n if (context.driveLastError) {\n const ageMs = getErrorAgeMs(context.driveLastError.at);\n const isStale = ageMs !== undefined && ageMs > STALE_ERROR_THRESHOLD_MS;\n if (isStale) {\n warnings.push(\n `Ignoring stale drive error (${Math.round(ageMs / 1000)}s old): ${context.driveLastError.message}`\n );\n }\n checks.push({\n name: 'drive.last_error',\n ok: isStale,\n message: context.driveLastError.message,\n details: {\n code: context.driveLastError.code,\n retryable: context.driveLastError.retryable,\n at: context.driveLastError.at,\n ...(ageMs !== undefined ? { age_ms: ageMs } : {}),\n },\n });\n }\n\n if (context.inspectLastError) {\n const ageMs = getErrorAgeMs(context.inspectLastError.at);\n const isStale = ageMs !== undefined && ageMs > STALE_ERROR_THRESHOLD_MS;\n if (isStale) {\n warnings.push(\n `Ignoring stale inspect error (${Math.round(ageMs / 1000)}s old): ${context.inspectLastError.message}`\n );\n }\n checks.push({\n name: 'inspect.last_error',\n ok: isStale,\n message: context.inspectLastError.message,\n details: {\n code: context.inspectLastError.code,\n retryable: context.inspectLastError.retryable,\n at: context.inspectLastError.at,\n ...(ageMs !== undefined ? { age_ms: ageMs } : {}),\n },\n });\n }\n\n if (context.recoveryAttempt) {\n checks.push({\n name: 'recovery.last_attempt',\n ok: context.recoveryAttempt.recovered,\n message: context.recoveryAttempt.message ?? 'Recovery attempt recorded.',\n details: {\n session_id: context.recoveryAttempt.sessionId,\n state: context.recoveryAttempt.state,\n at: context.recoveryAttempt.at,\n },\n });\n }\n\n const formatRecoveryAttempt = (attempt: RecoveryAttempt) => ({\n session_id: attempt.sessionId,\n recovered: attempt.recovered,\n state: attempt.state,\n message: attempt.message,\n at: attempt.at,\n });\n const recoveryAttempts = context.recoveryMetrics?.attempts;\n const lastRecoveryAttempt =\n context.recoveryAttempt ??\n (recoveryAttempts && recoveryAttempts[recoveryAttempts.length - 1]);\n\n const report: DiagnosticReport = {\n ok: checks.every((check) => check.ok),\n session_id: sessionId,\n checks,\n sessions: context.sessions\n ? {\n count: context.sessions.count,\n max_age_ms: context.sessions.maxAgeMs,\n max_idle_ms: context.sessions.maxIdleMs,\n }\n : undefined,\n extension: {\n connected: extensionConnected,\n last_seen_at: context.extension?.lastSeenAt,\n },\n debugger: context.debugger\n ? {\n attached: debuggerAttached,\n idle_timeout_ms: context.debugger.idle_timeout_ms,\n console_buffer_size: context.debugger.console_buffer_size,\n network_buffer_size: context.debugger.network_buffer_size,\n last_error: context.debugger.last_error,\n }\n : undefined,\n artifacts: sessionId\n ? {\n root_dir: getArtifactRootDir(sessionId),\n }\n : undefined,\n recovery:\n context.recoveryMetrics || lastRecoveryAttempt\n ? {\n ...(lastRecoveryAttempt\n ? { last_attempt: formatRecoveryAttempt(lastRecoveryAttempt) }\n : {}),\n ...(recoveryAttempts\n ? { attempts: recoveryAttempts.map(formatRecoveryAttempt) }\n : {}),\n ...(context.recoveryMetrics\n ? {\n success_count: context.recoveryMetrics.successCount,\n failure_count: context.recoveryMetrics.failureCount,\n success_rate: context.recoveryMetrics.successRate,\n recent_failure_count:\n context.recoveryMetrics.recentFailureCount,\n loop_detected: context.recoveryMetrics.loopDetected,\n }\n : {}),\n }\n : undefined,\n ...(warnings.length > 0 ? { warnings } : {}),\n notes: ['Diagnostics include runtime status; some checks may be stubbed.'],\n };\n\n return report;\n};\n", "import { DiagnosticsContext, buildDiagnosticReport } from '../diagnostics';\nimport type { SessionRegistry } from '../session';\nimport type { ExtensionBridge } from '../extension-bridge';\nimport type { DriveController } from '../drive';\nimport type { InspectService } from '../inspect';\nimport type { DebuggerBridge } from '../debugger-bridge';\nimport type { RecoveryTracker } from '../recovery';\nimport { HealthCheckInputSchema } from '@btraut/browser-bridge-shared';\nimport { ResponseLike, isRecord, sendError, sendResult } from './shared';\n\ntype RequestLike = {\n body?: unknown;\n};\n\ntype RouteRegistry = {\n post: (\n path: string,\n handler: (req: RequestLike, res: ResponseLike) => void\n ) => void;\n};\n\ntype DiagnosticsRoutesOptions = {\n registry?: SessionRegistry;\n extensionBridge?: ExtensionBridge;\n debuggerBridge?: DebuggerBridge;\n drive?: DriveController;\n inspectService?: InspectService;\n recoveryTracker?: RecoveryTracker;\n};\n\nconst PROCESS_STARTED_AT = new Date(\n Date.now() - Math.floor(process.uptime() * 1000)\n).toISOString();\n\nexport const registerDiagnosticsRoutes = (\n router: RouteRegistry,\n options: DiagnosticsRoutesOptions = {}\n): void => {\n router.post('/health_check', (req, res) => {\n const body = req.body ?? {};\n if (!isRecord(body)) {\n sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'Request body must be an object.',\n retryable: false,\n });\n return;\n }\n\n const parsed = HealthCheckInputSchema.safeParse(body);\n if (!parsed.success) {\n const issue = parsed.error.issues[0];\n sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: issue?.message ?? 'Invalid health check request.',\n retryable: false,\n details: issue?.path.length\n ? { field: issue.path.map((part) => String(part)).join('.') }\n : undefined,\n });\n return;\n }\n\n const sessionsActive = options.registry\n ? options.registry.list().length\n : 0;\n const extensionStatus = options.extensionBridge?.getStatus();\n\n sendResult(res, {\n started_at: PROCESS_STARTED_AT,\n uptime_ms: Math.floor(process.uptime() * 1000),\n memory: process.memoryUsage(),\n sessions: { active: sessionsActive },\n extension: {\n connected: extensionStatus?.connected ?? false,\n ...(extensionStatus?.lastSeenAt\n ? { last_seen_at: extensionStatus.lastSeenAt }\n : {}),\n },\n });\n });\n\n router.post('/diagnostics/doctor', (req, res) => {\n let sessionId: string | undefined;\n if (req.body !== undefined) {\n if (!isRecord(req.body)) {\n sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'Request body must be an object.',\n retryable: false,\n });\n return;\n }\n const raw = req.body.session_id;\n if (raw !== undefined && (typeof raw !== 'string' || raw.length === 0)) {\n sendError(res, 400, {\n code: 'INVALID_ARGUMENT',\n message: 'session_id must be a non-empty string.',\n retryable: false,\n details: { field: 'session_id' },\n });\n return;\n }\n sessionId = raw as string | undefined;\n }\n\n try {\n const context: DiagnosticsContext = {};\n if (options.registry && sessionId) {\n try {\n const session = options.registry.require(sessionId);\n context.sessionState = session.state;\n } catch {\n // Ignore missing session for diagnostics.\n }\n }\n\n if (options.registry) {\n const now = Date.now();\n const sessions = options.registry.list();\n let maxAgeMs = 0;\n let maxIdleMs = 0;\n for (const session of sessions) {\n const ageMs = now - session.createdAt.getTime();\n const idleMs = now - session.lastAccessedAt.getTime();\n if (ageMs > maxAgeMs) {\n maxAgeMs = ageMs;\n }\n if (idleMs > maxIdleMs) {\n maxIdleMs = idleMs;\n }\n }\n context.sessions = {\n count: sessions.length,\n ...(sessions.length > 0 ? { maxAgeMs, maxIdleMs } : {}),\n };\n }\n\n if (options.extensionBridge) {\n const status = options.extensionBridge.getStatus();\n context.extension = {\n connected: status.connected,\n lastSeenAt: status.lastSeenAt,\n };\n }\n\n if (options.debuggerBridge) {\n const settings = options.debuggerBridge.getSettings();\n const lastError = options.debuggerBridge.getLastError();\n context.debugger = {\n attached: options.debuggerBridge.hasAttachments(),\n idle_timeout_ms: settings.idleTimeoutMs,\n console_buffer_size: settings.consoleBufferSize,\n network_buffer_size: settings.networkBufferSize,\n last_error: lastError\n ? {\n code: lastError.error.code,\n message: lastError.error.message,\n retryable: lastError.error.retryable,\n details: lastError.error.details,\n }\n : undefined,\n };\n }\n\n if (options.drive) {\n const lastError = options.drive.getLastError();\n if (lastError) {\n context.driveLastError = {\n code: lastError.error.code,\n message: lastError.error.message,\n retryable: lastError.error.retryable,\n at: lastError.at,\n };\n }\n }\n\n if (options.inspectService) {\n const lastError = options.inspectService.getLastError();\n if (lastError) {\n context.inspectLastError = {\n code: lastError.error.code,\n message: lastError.error.message,\n retryable: lastError.error.retryable,\n at: lastError.at,\n };\n }\n }\n\n if (options.recoveryTracker) {\n const attempt = options.recoveryTracker.getLastAttempt();\n if (attempt) {\n context.recoveryAttempt = {\n sessionId: attempt.sessionId,\n recovered: attempt.recovered,\n state: attempt.state,\n message: attempt.message,\n at: attempt.at,\n };\n }\n context.recoveryMetrics = options.recoveryTracker.getMetrics();\n }\n\n const report = buildDiagnosticReport(sessionId, context);\n sendResult(res, report);\n } catch {\n sendError(res, 500, {\n code: 'INTERNAL',\n message: 'Failed to build diagnostics report.',\n retryable: false,\n });\n }\n });\n};\n", "import { Command } from 'commander';\nimport { ensureArtifactRootDir } from '@btraut/browser-bridge-core';\nimport { SessionIdSchema } from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runLocal } from '../cli-runtime';\nimport { openPath } from '../open-path';\n\nexport const registerOpenArtifactsCommand = (program: Command): void => {\n program\n .command('open-artifacts')\n .description('Open the artifact folder for a session')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runLocal(command, async () => {\n const payload = parseInput(SessionIdSchema, {\n session_id: options.sessionId,\n });\n const rootDir = await ensureArtifactRootDir(payload.session_id);\n await openPath(rootDir);\n return { ok: true, result: { path: rootDir, opened: true } };\n });\n });\n};\n", "import { Command } from 'commander';\nimport {\n SessionCloseInputSchema,\n SessionCreateInputSchema,\n SessionRecoverInputSchema,\n SessionStatusInputSchema,\n} from '@btraut/browser-bridge-shared';\nimport { parseInput } from '../cli-output';\nimport { runCommand } from '../cli-runtime';\n\nexport const registerSessionCommands = (program: Command): void => {\n const session = program\n .command('session')\n .description('Manage Core sessions');\n\n session\n .command('create')\n .description('Create a new session')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(SessionCreateInputSchema, {});\n return client.post('/session/create', payload);\n });\n });\n\n session\n .command('status')\n .description('Get session status')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(SessionStatusInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/session/status', payload);\n });\n });\n\n session\n .command('recover')\n .description('Attempt to recover a session')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(SessionRecoverInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/session/recover', payload);\n });\n });\n\n session\n .command('close')\n .description('Close a session')\n .requiredOption('--session-id <id>', 'Session identifier')\n .action(async (options, command) => {\n await runCommand(command, (client) => {\n const payload = parseInput(SessionCloseInputSchema, {\n session_id: options.sessionId,\n });\n return client.post('/session/close', payload);\n });\n });\n};\n", "import { Command } from 'commander';\nimport fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { runLocal } from '../cli-runtime';\nimport { checkboxPrompt, requireTty } from '../tui';\nimport {\n getDefaultHarnessTargets,\n HarnessId,\n} from '../installer/harness-targets';\nimport {\n resolveSkillSourceDir,\n readCliPackageVersion,\n} from '../installer/package-info';\nimport { installBrowserBridgeSkill } from '../installer/skill-install';\nimport { readSkillManifest } from '../installer/skill-manifest';\n\nconst getHarnessMarkerDir = (homeDir: string, harness: HarnessId): string => {\n switch (harness) {\n case 'codex':\n return path.join(homeDir, '.agents');\n default:\n return path.join(homeDir, `.${harness}`);\n }\n};\n\ntype SkillStatusRow = {\n harness: HarnessId;\n skillsDir: string;\n installed: boolean;\n installedVersion: string | null;\n expectedVersion: string;\n upToDate: boolean;\n};\n\nexport const registerSkillCommands = (program: Command): void => {\n const skill = program.command('skill').description('Skill commands');\n\n skill\n .command('install')\n .description('Install the Browser Bridge skill into one or more clients')\n .option(\n '--client <id...>',\n 'Client ids to install into (codex, claude, cursor, factory, opencode, gemini, github, ampcode)'\n )\n .option('--harness <id...>', 'Alias for --client')\n .action(\n async (\n options: { client?: string[]; harness?: string[] },\n command: Command\n ) => {\n await runLocal(command, async ({ json }) => {\n if (json) {\n throw new Error('skill install is interactive; omit --json.');\n }\n\n const version = await readCliPackageVersion();\n const srcSkillDir = await resolveSkillSourceDir();\n\n const targets = getDefaultHarnessTargets();\n const byId = new Map(targets.map((t) => [t.id, t]));\n\n let selected: HarnessId[];\n const requested = options.client?.length\n ? options.client\n : options.harness;\n\n if (requested && requested.length > 0) {\n selected = requested.map((id) => {\n if (!byId.has(id as HarnessId)) {\n throw new Error(`Unknown client: ${id}`);\n }\n return id as HarnessId;\n });\n } else {\n requireTty();\n\n // Default to clients whose home dirs exist, otherwise select Codex.\n const homeDir = os.homedir();\n\n const checked = new Set<HarnessId>();\n for (const t of targets) {\n try {\n const marker = getHarnessMarkerDir(homeDir, t.id);\n await fs.stat(marker);\n checked.add(t.id);\n } catch {\n // ignore\n }\n }\n if (checked.size === 0) {\n checked.add('codex');\n }\n\n selected = await checkboxPrompt<HarnessId>({\n message: 'Install Browser Bridge skill into clients:',\n choices: targets.map((t) => ({\n value: t.id,\n label: `${t.label} (${t.skillsDir})`,\n checked: checked.has(t.id),\n })),\n });\n }\n\n const results: Record<string, { destDir: string }> = {};\n for (const client of selected) {\n const target = byId.get(client);\n if (!target) continue;\n const installed = await installBrowserBridgeSkill({\n srcSkillDir,\n destSkillsDir: target.skillsDir,\n version,\n });\n results[client] = { destDir: installed.destDir };\n }\n\n return {\n ok: true,\n result: {\n version,\n installed: results,\n },\n };\n });\n }\n );\n\n skill\n .command('status')\n .description('Show Browser Bridge skill install status across clients')\n .action(async (_options, command: Command) => {\n await runLocal(command, async () => {\n const version = await readCliPackageVersion();\n const targets = getDefaultHarnessTargets();\n\n const rows: SkillStatusRow[] = [];\n for (const t of targets) {\n const skillDir = path.join(t.skillsDir, 'browser-bridge');\n let installed = false;\n try {\n await fs.stat(skillDir);\n installed = true;\n } catch {\n installed = false;\n }\n\n const manifest = installed ? await readSkillManifest(skillDir) : null;\n const installedVersion = manifest?.version ?? null;\n const upToDate = installedVersion === version;\n\n rows.push({\n harness: t.id,\n skillsDir: t.skillsDir,\n installed,\n installedVersion,\n expectedVersion: version,\n upToDate,\n });\n }\n\n return { ok: true, result: { rows } };\n });\n });\n};\n", "import os from 'node:os';\nimport path from 'node:path';\n\nexport type HarnessId =\n | 'codex'\n | 'claude'\n | 'cursor'\n | 'factory'\n | 'opencode'\n | 'gemini'\n | 'github'\n | 'ampcode';\n\nexport type HarnessTarget = {\n id: HarnessId;\n label: string;\n skillsDir: string;\n // Whether we can install MCP config automatically.\n supportsMcpInstall: boolean;\n};\n\nexport const getDefaultHarnessTargets = (homeDir?: string): HarnessTarget[] => {\n const home = homeDir ?? os.homedir();\n\n // Note: Codex now reads skills from ~/.agents/skills (and may symlink from ~/.codex/skills).\n return [\n {\n id: 'codex',\n label: 'Codex',\n skillsDir: path.join(home, '.agents', 'skills'),\n supportsMcpInstall: true,\n },\n {\n id: 'claude',\n label: 'Claude',\n skillsDir: path.join(home, '.claude', 'skills'),\n supportsMcpInstall: true,\n },\n {\n id: 'cursor',\n label: 'Cursor',\n skillsDir: path.join(home, '.cursor', 'skills'),\n supportsMcpInstall: true,\n },\n {\n id: 'factory',\n label: 'Factory',\n skillsDir: path.join(home, '.factory', 'skills'),\n supportsMcpInstall: false,\n },\n {\n id: 'opencode',\n label: 'OpenCode',\n skillsDir: path.join(home, '.opencode', 'skills'),\n supportsMcpInstall: false,\n },\n {\n id: 'gemini',\n label: 'Gemini',\n skillsDir: path.join(home, '.gemini', 'skills'),\n supportsMcpInstall: false,\n },\n {\n id: 'github',\n label: 'GitHub',\n skillsDir: path.join(home, '.github', 'skills'),\n supportsMcpInstall: false,\n },\n {\n id: 'ampcode',\n label: 'Ampcode',\n skillsDir: path.join(home, '.ampcode', 'skills'),\n supportsMcpInstall: false,\n },\n ];\n};\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nconst PACKAGE_NAME = '@btraut/browser-bridge';\n\nconst tryReadJson = async (filePath: string): Promise<unknown | null> => {\n try {\n const raw = await fs.readFile(filePath, 'utf8');\n return JSON.parse(raw) as unknown;\n } catch {\n return null;\n }\n};\n\nexport const resolveCliPackageRootDir = async (): Promise<string> => {\n // When bundled, `__dirname` may be something like dist/ or dist/installer/\n // (depending on how the bundler preserves module paths). Find the nearest\n // parent directory that contains this package's package.json.\n let dir = __dirname;\n for (let i = 0; i < 12; i++) {\n const candidate = path.join(dir, 'package.json');\n const parsed = (await tryReadJson(candidate)) as { name?: unknown } | null;\n if (parsed && parsed.name === PACKAGE_NAME) {\n return dir;\n }\n\n const parent = path.dirname(dir);\n if (parent === dir) {\n break;\n }\n dir = parent;\n }\n\n throw new Error(\n 'Unable to locate Browser Bridge package root (package.json).'\n );\n};\n\nexport const readCliPackageVersion = async (): Promise<string> => {\n const rootDir = await resolveCliPackageRootDir();\n const pkgPath = path.join(rootDir, 'package.json');\n const parsed = (await tryReadJson(pkgPath)) as { version?: unknown } | null;\n if (!parsed || typeof parsed.version !== 'string' || !parsed.version) {\n throw new Error(`Unable to read version from ${pkgPath}`);\n }\n return parsed.version;\n};\n\nexport const resolveSkillSourceDir = async (): Promise<string> => {\n const rootDir = await resolveCliPackageRootDir();\n\n const packaged = path.join(rootDir, 'skills', 'browser-bridge');\n try {\n await fs.stat(packaged);\n return packaged;\n } catch {\n // In-repo dev usage: `npm run build` does not stage `packages/cli/skills/*`\n // (that happens at npm pack time). Fall back to docs/skills.\n }\n\n const repoRoot = path.resolve(rootDir, '..', '..');\n const docsSkill = path.join(repoRoot, 'docs', 'skills', 'browser-bridge');\n try {\n await fs.stat(docsSkill);\n return docsSkill;\n } catch {\n // ignore\n }\n\n throw new Error(\n `Unable to locate packaged skill. Expected ${packaged} (npm install) or ${docsSkill} (repo dev).`\n );\n};\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { writeSkillManifest } from './skill-manifest';\n\nexport type SkillInstallResult = {\n ok: true;\n destDir: string;\n};\n\nexport const installBrowserBridgeSkill = async (options: {\n srcSkillDir: string;\n destSkillsDir: string;\n version: string;\n}): Promise<SkillInstallResult> => {\n const destDir = path.join(options.destSkillsDir, 'browser-bridge');\n\n await fs.mkdir(options.destSkillsDir, { recursive: true });\n await fs.rm(destDir, { recursive: true, force: true });\n await fs.cp(options.srcSkillDir, destDir, { recursive: true });\n\n // Ensure the installed copy has a version marker that matches the app.\n await writeSkillManifest(destDir, options.version);\n\n return { ok: true, destDir };\n};\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport type SkillManifest = {\n name: 'browser-bridge';\n version: string;\n};\n\nexport const SKILL_MANIFEST_FILENAME = 'skill.json';\n\nexport const readSkillManifest = async (\n skillDir: string\n): Promise<SkillManifest | null> => {\n try {\n const raw = await fs.readFile(\n path.join(skillDir, SKILL_MANIFEST_FILENAME),\n 'utf8'\n );\n const parsed = JSON.parse(raw) as unknown;\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n (parsed as { name?: unknown }).name === 'browser-bridge' &&\n typeof (parsed as { version?: unknown }).version === 'string'\n ) {\n return parsed as SkillManifest;\n }\n return null;\n } catch {\n return null;\n }\n};\n\nexport const writeSkillManifest = async (\n skillDir: string,\n version: string\n): Promise<void> => {\n const payload: SkillManifest = { name: 'browser-bridge', version };\n await fs.writeFile(\n path.join(skillDir, SKILL_MANIFEST_FILENAME),\n JSON.stringify(payload, null, 2) + '\\n',\n 'utf8'\n );\n};\n", "import { Command } from 'commander';\nimport fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { runLocal } from '../cli-runtime';\nimport { checkboxPrompt, requireTty } from '../tui';\nimport {\n getDefaultHarnessTargets,\n HarnessId,\n} from '../installer/harness-targets';\nimport {\n resolveSkillSourceDir,\n readCliPackageVersion,\n} from '../installer/package-info';\nimport { installBrowserBridgeSkill } from '../installer/skill-install';\nimport { installMcp } from '../installer/mcp-install';\n\ntype SetupItem = 'skill' | 'mcp';\n\ntype HarnessInstallResult = {\n harness: HarnessId;\n skill?: { ok: true; destDir: string };\n mcp?:\n | { ok: true; details?: { cursorSettingsPath?: string } }\n | { ok: false; error: { code: string; message: string } };\n};\n\nconst formatInstallSummary = (options: {\n setup: SetupItem[];\n results: HarnessInstallResult[];\n}): string => {\n const wantsSkill = options.setup.includes('skill');\n const wantsMcp = options.setup.includes('mcp');\n\n const lines: string[] = [];\n\n if (wantsSkill) {\n const skillInstalled = options.results\n .filter((r) => r.skill?.ok)\n .map((r) => `- ${r.harness}: ${r.skill?.destDir ?? ''}`);\n if (skillInstalled.length > 0) {\n lines.push('Skill installed:');\n lines.push(...skillInstalled);\n lines.push('');\n }\n }\n\n if (wantsMcp) {\n const mcpOk = options.results\n .filter((r) => r.mcp?.ok)\n .map((r) => `- ${r.harness}`);\n\n const mcpFailed = options.results\n .filter((r) => r.mcp && r.mcp.ok === false)\n .map((r) =>\n r.mcp && r.mcp.ok === false\n ? `- ${r.harness}: ${r.mcp.error.message}`\n : `- ${r.harness}: unknown error`\n );\n\n if (mcpOk.length > 0) {\n lines.push('MCP installed:');\n lines.push(...mcpOk);\n lines.push('');\n }\n\n if (mcpFailed.length > 0) {\n lines.push('MCP failed:');\n lines.push(...mcpFailed);\n lines.push('');\n }\n }\n\n return lines.join('\\n').trimEnd();\n};\n\nconst getHarnessMarkerDir = (harness: HarnessId): string => {\n const homeDir = os.homedir();\n switch (harness) {\n case 'codex':\n return path.join(homeDir, '.agents');\n default:\n return path.join(homeDir, `.${harness}`);\n }\n};\n\nexport const registerInstallCommand = (program: Command): void => {\n program\n .command('install')\n .description('Install Browser Bridge integrations (Skill and/or MCP)')\n .action(async (_options, command: Command) => {\n await runLocal(command, async ({ json }) => {\n if (json) {\n throw new Error('install is interactive; omit --json.');\n }\n\n requireTty();\n\n console.log('Browser Bridge Installer');\n\n const setup = await checkboxPrompt<SetupItem>({\n message: \"Choose what you'd like to install:\",\n choices: [\n { value: 'skill', label: 'Skill (Recommended)', checked: true },\n { value: 'mcp', label: 'MCP (Optional)', checked: true },\n ],\n });\n\n if (setup.length === 0) {\n return { ok: true, result: 'No changes (nothing selected).' };\n }\n\n const wantsSkill = setup.includes('skill');\n const wantsMcp = setup.includes('mcp');\n\n const targets = getDefaultHarnessTargets();\n\n // Default to harnesses whose home dirs exist, otherwise select Codex.\n const checked = new Set<HarnessId>();\n for (const t of targets) {\n try {\n await fs.stat(getHarnessMarkerDir(t.id));\n checked.add(t.id);\n } catch {\n // ignore\n }\n }\n if (checked.size === 0) {\n checked.add('codex');\n }\n\n const selected = await checkboxPrompt<HarnessId>({\n message: 'Install into clients:',\n choices: targets.map((t) => {\n const mcpCapable = t.supportsMcpInstall;\n const enabled = wantsSkill || mcpCapable;\n const disabled = enabled\n ? false\n : wantsMcp\n ? 'MCP install not supported yet'\n : false;\n\n // Keep labels minimal: only annotate when the row is \"skill only\"\n // while the user selected Skill+MCP.\n const suffix =\n wantsMcp && wantsSkill && !mcpCapable ? ' (skill only)' : '';\n\n return {\n value: t.id,\n label: `${t.label}${suffix}`,\n checked: checked.has(t.id),\n disabled,\n };\n }),\n });\n\n const version = await readCliPackageVersion();\n const srcSkillDir = await resolveSkillSourceDir();\n const byId = new Map(targets.map((t) => [t.id, t]));\n\n const results: HarnessInstallResult[] = [];\n let hadError = false;\n for (const harness of selected) {\n const t = byId.get(harness);\n if (!t) continue;\n\n const row: HarnessInstallResult = { harness };\n\n if (wantsSkill) {\n const installed = await installBrowserBridgeSkill({\n srcSkillDir,\n destSkillsDir: t.skillsDir,\n version,\n });\n row.skill = { ok: true, destDir: installed.destDir };\n }\n\n if (wantsMcp && t.supportsMcpInstall) {\n // Only Codex/Claude/Cursor supported in v1.\n if (\n harness === 'codex' ||\n harness === 'claude' ||\n harness === 'cursor'\n ) {\n row.mcp = await installMcp(harness);\n if (row.mcp.ok === false) {\n hadError = true;\n }\n }\n }\n\n results.push(row);\n }\n\n if (hadError) {\n process.exitCode = 1;\n }\n\n const summary = formatInstallSummary({ setup, results });\n return { ok: true, result: summary || 'Done.' };\n });\n });\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_node_fs", "import_node_path", "path", "import_zod", "import_zod", "import_node_path", "path", "delay", "envelope", "durationMs", "envelope", "program", "parseNumber", "program", "program", "import_node_child_process", "child", "program", "parseNumber", "program", "program", "DEFAULT_TIMEOUT_MS", "normalizePath", "path", "durationMs", "createCoreClient", "durationMs", "createCoreClient", "resolve", "path", "import_node_child_process", "import_promises", "import_node_path", "os", "path", "fs", "resolve", "program", "import_express", "import_promises", "import_node_os", "import_node_path", "os", "path", "program", "program", "import_promises", "import_node_os", "import_node_path", "import_node_os", "import_node_path", "os", "path", "import_promises", "import_node_path", "fs", "path", "import_promises", "import_node_path", "import_promises", "import_node_path", "fs", "path", "path", "fs", "path", "program", "os", "fs", "import_promises", "import_node_os", "import_node_path", "getHarnessMarkerDir", "os", "path", "program", "fs"]
|
|
7
7
|
}
|