@neuralnomads/codenomad-dev 0.20.0-dev-20260922-f3834dd2 → 0.20.0-dev-20260922-5650ed9d

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.
Files changed (95) hide show
  1. package/dist/automation/developer-inspection-targets.js +25 -0
  2. package/dist/automation/developer-inspection-targets.js.map +1 -0
  3. package/dist/developer-cdp.js +5 -4
  4. package/dist/developer-cdp.js.map +1 -1
  5. package/dist/developer-cdp.test.js +18 -0
  6. package/dist/developer-cdp.test.js.map +1 -1
  7. package/dist/server/routes/automation-plugin.js +28 -15
  8. package/dist/server/routes/automation-plugin.js.map +1 -1
  9. package/dist/server/routes/automation-plugin.test.js +10 -6
  10. package/dist/server/routes/automation-plugin.test.js.map +1 -1
  11. package/dist/workspaces/__tests__/git-common-directory.test.js +97 -0
  12. package/dist/workspaces/__tests__/git-common-directory.test.js.map +1 -0
  13. package/dist/workspaces/git-common-directory.js +18 -0
  14. package/dist/workspaces/git-common-directory.js.map +1 -0
  15. package/dist/workspaces/git-process.js +90 -0
  16. package/dist/workspaces/git-process.js.map +1 -0
  17. package/dist/workspaces/git-status.js +32 -38
  18. package/dist/workspaces/git-status.js.map +1 -1
  19. package/dist/workspaces/git-status.test.js +28 -1
  20. package/dist/workspaces/git-status.test.js.map +1 -1
  21. package/dist/workspaces/git-worktrees.js +3 -9
  22. package/dist/workspaces/git-worktrees.js.map +1 -1
  23. package/package.json +1 -1
  24. package/public/assets/App-BInh9z8B.js +51 -0
  25. package/public/assets/App-BInh9z8B.js.map +1 -0
  26. package/public/assets/{FilesTab-CP3GICgc.js → FilesTab-Bz3ekii-.js} +3 -3
  27. package/public/assets/{FilesTab-CP3GICgc.js.map → FilesTab-Bz3ekii-.js.map} +1 -1
  28. package/public/assets/{GitChangesTab-DC5uIAYI.js → GitChangesTab-DEmFm9X9.js} +3 -3
  29. package/public/assets/{GitChangesTab-DC5uIAYI.js.map → GitChangesTab-DEmFm9X9.js.map} +1 -1
  30. package/public/assets/{SplitFilePanel-D4kbA67I.js → SplitFilePanel-D9KFC8Yo.js} +2 -2
  31. package/public/assets/{SplitFilePanel-D4kbA67I.js.map → SplitFilePanel-D9KFC8Yo.js.map} +1 -1
  32. package/public/assets/{StatusTab-B7-e7Jym.js → StatusTab-V8ZSDdnZ.js} +2 -2
  33. package/public/assets/{StatusTab-B7-e7Jym.js.map → StatusTab-V8ZSDdnZ.js.map} +1 -1
  34. package/public/assets/{align-justify-t6BvuuGq.js → align-justify-Bi3yHu8i.js} +2 -2
  35. package/public/assets/{align-justify-t6BvuuGq.js.map → align-justify-Bi3yHu8i.js.map} +1 -1
  36. package/public/assets/{bundle-full-LA4LRJvC.js → bundle-full-CSLya0fX.js} +2 -2
  37. package/public/assets/{bundle-full-LA4LRJvC.js.map → bundle-full-CSLya0fX.js.map} +1 -1
  38. package/public/assets/{client-state-BELVPVQK.js → client-state-BZr92Odb.js} +2 -2
  39. package/public/assets/{client-state-BELVPVQK.js.map → client-state-BZr92Odb.js.map} +1 -1
  40. package/public/assets/{diff-viewer-n0toXKZF.js → diff-viewer-DHy_0NiU.js} +2 -2
  41. package/public/assets/{diff-viewer-n0toXKZF.js.map → diff-viewer-DHy_0NiU.js.map} +1 -1
  42. package/public/assets/{index-BT4hx4H9.js → index-B80YtNDR.js} +2 -2
  43. package/public/assets/{index-BT4hx4H9.js.map → index-B80YtNDR.js.map} +1 -1
  44. package/public/assets/{index-DINKO8rw.js → index-BF4aeRZL.js} +2 -2
  45. package/public/assets/{index-DINKO8rw.js.map → index-BF4aeRZL.js.map} +1 -1
  46. package/public/assets/{index-fkx7BwtE.js → index-BMM7DX4E.js} +2 -2
  47. package/public/assets/{index-fkx7BwtE.js.map → index-BMM7DX4E.js.map} +1 -1
  48. package/public/assets/{index-BRo0m4HH.js → index-C5fAhE7q.js} +2 -2
  49. package/public/assets/{index-BRo0m4HH.js.map → index-C5fAhE7q.js.map} +1 -1
  50. package/public/assets/{index-sYGWeU2B.js → index-Cr0fq_1m.js} +2 -2
  51. package/public/assets/{index-sYGWeU2B.js.map → index-Cr0fq_1m.js.map} +1 -1
  52. package/public/assets/{index-CYrgGxN5.js → index-DTM4JCOg.js} +3 -3
  53. package/public/assets/{index-CYrgGxN5.js.map → index-DTM4JCOg.js.map} +1 -1
  54. package/public/assets/{index-CjsBXyUr.js → index-DUSHdfNt.js} +2 -2
  55. package/public/assets/{index-CjsBXyUr.js.map → index-DUSHdfNt.js.map} +1 -1
  56. package/public/assets/{index-DjwZf3Yh.js → index-DvzNUKxQ.js} +2 -2
  57. package/public/assets/{index-DjwZf3Yh.js.map → index-DvzNUKxQ.js.map} +1 -1
  58. package/public/assets/index-DyV5PLqt.js +2 -0
  59. package/public/assets/{index-mSrN15cu.js.map → index-DyV5PLqt.js.map} +1 -1
  60. package/public/assets/{index-mN9OrWRM.js → index-aeY5PFwo.js} +2 -2
  61. package/public/assets/{index-mN9OrWRM.js.map → index-aeY5PFwo.js.map} +1 -1
  62. package/public/assets/{index-CyxtFA9R.js → index-je4g4OjU.js} +2 -2
  63. package/public/assets/{index-CyxtFA9R.js.map → index-je4g4OjU.js.map} +1 -1
  64. package/public/assets/{index-CQPkLT1b.js → index-vOjZjElj.js} +2 -2
  65. package/public/assets/{index-CQPkLT1b.js.map → index-vOjZjElj.js.map} +1 -1
  66. package/public/assets/{loading-D4az9Vmg.js → loading-XXcoiSPg.js} +2 -2
  67. package/public/assets/{loading-D4az9Vmg.js.map → loading-XXcoiSPg.js.map} +1 -1
  68. package/public/assets/main-C_TdncJ5.js +42 -0
  69. package/public/assets/main-C_TdncJ5.js.map +1 -0
  70. package/public/assets/{markdown-Dtp2_t2x.js → markdown-DcIkkDVW.js} +4 -4
  71. package/public/assets/{markdown-Dtp2_t2x.js.map → markdown-DcIkkDVW.js.map} +1 -1
  72. package/public/assets/{monaco-viewer-ChA_iFmw.js → monaco-viewer-DWKuMLsd.js} +3 -3
  73. package/public/assets/monaco-viewer-DWKuMLsd.js.map +1 -0
  74. package/public/assets/{startup-state-settings-card-CwqMz9iE.js → startup-state-settings-card-DsQ6ZLN9.js} +2 -2
  75. package/public/assets/{startup-state-settings-card-CwqMz9iE.js.map → startup-state-settings-card-DsQ6ZLN9.js.map} +1 -1
  76. package/public/assets/{terminal-square-5uHstmTD.js → terminal-square-CvdvCOmv.js} +2 -2
  77. package/public/assets/{terminal-square-5uHstmTD.js.map → terminal-square-CvdvCOmv.js.map} +1 -1
  78. package/public/assets/{todo-rWdKPGRD.js → todo-DZCMHJBr.js} +2 -2
  79. package/public/assets/{todo-rWdKPGRD.js.map → todo-DZCMHJBr.js.map} +1 -1
  80. package/public/assets/{tool-call-B2lbL8ZE.js → tool-call-Bw7CQyE9.js} +17 -17
  81. package/public/assets/{tool-call-B2lbL8ZE.js.map → tool-call-Bw7CQyE9.js.map} +1 -1
  82. package/public/assets/{unified-picker-CyMBKInh.js → unified-picker-D3FIJGsM.js} +2 -2
  83. package/public/assets/{unified-picker-CyMBKInh.js.map → unified-picker-D3FIJGsM.js.map} +1 -1
  84. package/public/assets/{wrap-text-CSz4eer6.js → wrap-text-ma0EMBIk.js} +2 -2
  85. package/public/assets/{wrap-text-CSz4eer6.js.map → wrap-text-ma0EMBIk.js.map} +1 -1
  86. package/public/index.html +3 -3
  87. package/public/loading.html +3 -3
  88. package/public/sw.js +1 -1
  89. package/public/sw.js.map +1 -1
  90. package/public/assets/App-DljM3SwE.js +0 -51
  91. package/public/assets/App-DljM3SwE.js.map +0 -1
  92. package/public/assets/index-mSrN15cu.js +0 -2
  93. package/public/assets/main-pe2tFxvx.js +0 -42
  94. package/public/assets/main-pe2tFxvx.js.map +0 -1
  95. package/public/assets/monaco-viewer-ChA_iFmw.js.map +0 -1
@@ -0,0 +1,25 @@
1
+ /** Pin the inspected native window/run, independently of the selected project
2
+ * or conversation. A new native target requires a fresh inspection. */
3
+ export class DeveloperInspectionTargets {
4
+ constructor() {
5
+ this.targets = new Map();
6
+ }
7
+ remember(sessionId, identity) {
8
+ this.targets.delete(sessionId);
9
+ this.targets.set(sessionId, identity);
10
+ if (this.targets.size > 128)
11
+ this.targets.delete(this.targets.keys().next().value);
12
+ }
13
+ get(sessionId, native) {
14
+ const target = this.targets.get(sessionId);
15
+ if (!target || target.runId !== native.runId || target.windowId !== native.windowId || target.endpoint !== native.endpoint) {
16
+ this.targets.delete(sessionId);
17
+ throw new Error("Run codenomad.inspect before acting on or restarting this CodeNomad window");
18
+ }
19
+ return target;
20
+ }
21
+ forget(sessionId) {
22
+ this.targets.delete(sessionId);
23
+ }
24
+ }
25
+ //# sourceMappingURL=developer-inspection-targets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"developer-inspection-targets.js","sourceRoot":"","sources":["../../src/automation/developer-inspection-targets.ts"],"names":[],"mappings":"AAEA;uEACuE;AACvE,MAAM,OAAO,0BAA0B;IAAvC;QACmB,YAAO,GAAG,IAAI,GAAG,EAAgC,CAAA;IAoBpE,CAAC;IAlBC,QAAQ,CAAC,SAAiB,EAAE,QAA8B;QACxD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC9B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QACrC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG;YAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,CAAA;IACrF,CAAC;IAED,GAAG,CAAC,SAAiB,EAAE,MAA6D;QAClF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAC1C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC3H,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YAC9B,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAA;QAC/F,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED,MAAM,CAAC,SAAiB;QACtB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAChC,CAAC;CACF","sourcesContent":["import type { DeveloperCdpIdentity } from \"../developer-cdp\"\n\n/** Pin the inspected native window/run, independently of the selected project\n * or conversation. A new native target requires a fresh inspection. */\nexport class DeveloperInspectionTargets {\n private readonly targets = new Map<string, DeveloperCdpIdentity>()\n\n remember(sessionId: string, identity: DeveloperCdpIdentity): void {\n this.targets.delete(sessionId)\n this.targets.set(sessionId, identity)\n if (this.targets.size > 128) this.targets.delete(this.targets.keys().next().value!)\n }\n\n get(sessionId: string, native: { runId: string; windowId: string; endpoint: string }): DeveloperCdpIdentity {\n const target = this.targets.get(sessionId)\n if (!target || target.runId !== native.runId || target.windowId !== native.windowId || target.endpoint !== native.endpoint) {\n this.targets.delete(sessionId)\n throw new Error(\"Run codenomad.inspect before acting on or restarting this CodeNomad window\")\n }\n return target\n }\n\n forget(sessionId: string): void {\n this.targets.delete(sessionId)\n }\n}\n"]}
@@ -234,14 +234,15 @@ export class DeveloperCdp {
234
234
  returnByValue: true,
235
235
  });
236
236
  const value = response.result?.value;
237
- if (!value || typeof value.windowId !== "string" || typeof value.instanceId !== "string" || typeof value.sessionId !== "string"
238
- || value.windowId.length > 256 || value.instanceId.length > 256 || value.sessionId.length > 256) {
239
- throw new Error("CodeNomad page has no active session context");
237
+ const optionalId = (id) => id === null || (typeof id === "string" && id.length <= 256);
238
+ if (!value || typeof value.windowId !== "string" || value.windowId.length > 256
239
+ || !optionalId(value.instanceId) || !optionalId(value.sessionId)) {
240
+ throw new Error("CodeNomad page has no valid window context");
240
241
  }
241
242
  return { windowId: value.windowId, instanceId: value.instanceId, sessionId: value.sessionId };
242
243
  }
243
244
  matchesContext(state, context) {
244
- return context.windowId === state.windowId && context.sessionId === state.sessionId
245
+ return context.windowId === state.windowId && (state.sessionId === undefined || context.sessionId === state.sessionId)
245
246
  && (state.instanceId === undefined || context.instanceId === state.instanceId);
246
247
  }
247
248
  async connect(state, target) {
@@ -1 +1 @@
1
- {"version":3,"file":"developer-cdp.js","sourceRoot":"","sources":["../src/developer-cdp.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebSocket } from \"undici\"\n\nconst DEFAULT_TIMEOUT_MS = 5_000\nconst DEFAULT_MAX_SCREENSHOT_BYTES = 5 * 1024 * 1024\nconst DIAGNOSTIC_LIMIT = 1_000\nconst SNAPSHOT_NODE_LIMIT = 750\nconst SNAPSHOT_TEXT_LIMIT = 64 * 1024\nconst DIAGNOSTIC_TEXT_LIMIT = 512\nconst DISCOVERY_TEXT_LIMIT = 256 * 1024\nconst DISCOVERY_TARGET_LIMIT = 64\nconst DISCOVERY_PROBE_CONCURRENCY = 4\nconst CONTEXT_EXPRESSION = `(() => {\n const root = document.querySelector('[data-tab-visible=\"true\"][data-instance-id]');\n const pane = root?.querySelector('.session-cache-pane[data-session-active=\"true\"][data-session-id]');\n return {\n windowId: window.__CODENOMAD_WINDOW_ID__ ?? null,\n instanceId: root?.getAttribute('data-instance-id') ?? null,\n sessionId: pane?.getAttribute('data-session-id') ?? null,\n };\n})()`\n\nexport interface DeveloperCdpSelection {\n endpoint: string\n runId: string\n windowId: string\n sessionId: string\n}\n\nexport interface DeveloperCdpIdentity extends DeveloperCdpSelection {\n instanceId: string\n}\n\nexport interface DeveloperCdpContext {\n windowId: string\n instanceId: string\n sessionId: string\n}\n\nexport interface DeveloperCdpNode {\n ref?: string\n role: string\n name: string\n description?: string\n value?: string\n states?: string[]\n}\n\nexport interface DeveloperCdpDiagnostic {\n level: \"log\" | \"warning\" | \"error\"\n text: string\n}\n\nexport interface DeveloperCdpInspection {\n target: { id: string; title: string; url: string }\n context: DeveloperCdpContext\n nodes: DeveloperCdpNode[]\n diagnostics: DeveloperCdpDiagnostic[]\n}\n\nexport type DeveloperCdpAction =\n | (DeveloperCdpIdentity & { kind: \"click\"; ref: string })\n | (DeveloperCdpIdentity & { kind: \"type\"; ref: string; text: string })\n\nexport interface DeveloperCdpScreenshot {\n mediaType: \"image/png\"\n data: string\n bytes: number\n}\n\ninterface CdpSocket {\n onopen: ((event: unknown) => void) | null\n onmessage: ((event: { data: unknown }) => void) | null\n onclose: ((event: unknown) => void) | null\n onerror: ((event: unknown) => void) | null\n send(data: string): void\n close(): void\n}\n\ninterface DeveloperCdpDependencies {\n fetch: typeof globalThis.fetch\n connect: (url: string) => CdpSocket\n timeoutMs: number\n maxScreenshotBytes: number\n}\n\ninterface CdpTarget {\n id: string\n title: string\n type: string\n url: string\n webSocketDebuggerUrl: string\n}\n\ninterface CdpResponse {\n id?: number\n method?: string\n params?: Record<string, unknown>\n result?: Record<string, unknown>\n error?: { code?: number; message?: string }\n}\n\ninterface PendingCommand {\n resolve: (value: Record<string, unknown>) => void\n reject: (error: Error) => void\n timer: NodeJS.Timeout\n}\n\ninterface RunState {\n endpoint: string\n windowId: string\n sessionId: string\n instanceId?: string\n context?: DeveloperCdpContext\n target?: CdpTarget\n socket?: CdpSocket\n open?: Promise<void>\n nextCommandId: number\n navigationEpoch: number\n pending: Map<number, PendingCommand>\n refs: Map<string, { backendNodeId: number; targetId: string; epoch: number }>\n diagnostics: DeveloperCdpDiagnostic[]\n}\n\ninterface AxValue { value?: unknown }\ninterface AxNode {\n ignored?: boolean\n backendDOMNodeId?: number\n role?: AxValue\n name?: AxValue\n description?: AxValue\n value?: AxValue\n properties?: Array<{ name?: string; value?: AxValue }>\n}\n\nexport class DeveloperCdp {\n private readonly dependencies: DeveloperCdpDependencies\n private readonly runs = new Map<string, RunState>()\n private readonly operations = new Map<string, Promise<void>>()\n private nextRefId = 0\n\n constructor(dependencies: Partial<DeveloperCdpDependencies> = {}) {\n this.dependencies = {\n fetch: globalThis.fetch,\n connect: (url) => new WebSocket(url) as unknown as CdpSocket,\n timeoutMs: DEFAULT_TIMEOUT_MS,\n maxScreenshotBytes: DEFAULT_MAX_SCREENSHOT_BYTES,\n ...dependencies,\n }\n }\n\n async inspect(identity: DeveloperCdpIdentity): Promise<DeveloperCdpInspection> {\n return this.exclusive(identity.runId, async () => {\n const state = await this.ensure(identity)\n const epoch = state.navigationEpoch\n const result = await this.command(state, \"Accessibility.getFullAXTree\")\n await this.assertContextCurrent(state, epoch, \"Page changed during inspection; inspect again\")\n\n state.refs.clear()\n const nodes = Array.isArray(result.nodes) ? result.nodes as AxNode[] : []\n const snapshot: DeveloperCdpNode[] = []\n let textSize = 0\n for (const node of nodes) {\n if (node.ignored || !Number.isInteger(node.backendDOMNodeId)) continue\n const role = valueOf(node.role)\n const name = valueOf(node.name)\n if (!role || (!name && [\"generic\", \"none\", \"StaticText\", \"InlineTextBox\"].includes(role))) continue\n const description = valueOf(node.description)\n const value = valueOf(node.value)\n const states = (node.properties ?? [])\n .filter((property) => [\"checked\", \"disabled\", \"expanded\", \"focused\", \"selected\"].includes(property.name ?? \"\"))\n .map((property) => `${property.name}=${String(property.value?.value)}`)\n const size = role.length + name.length + description.length + value.length + states.join(\" \").length\n if (snapshot.length >= SNAPSHOT_NODE_LIMIT || textSize + size > SNAPSHOT_TEXT_LIMIT) break\n textSize += size\n const ref = `ax${++this.nextRefId}`\n state.refs.set(ref, {\n backendNodeId: node.backendDOMNodeId!,\n targetId: state.target!.id,\n epoch,\n })\n snapshot.push({\n ref,\n role,\n name,\n ...(description ? { description } : {}),\n ...(value ? { value } : {}),\n ...(states.length ? { states } : {}),\n })\n }\n return {\n target: { id: state.target!.id, title: state.target!.title, url: state.target!.url },\n context: state.context!,\n nodes: snapshot,\n diagnostics: state.diagnostics.splice(0),\n }\n })\n }\n\n async act(action: DeveloperCdpAction): Promise<void> {\n return this.exclusive(action.runId, async () => {\n const state = await this.ensure(action)\n const node = this.resolveRef(state, action.ref)\n if (action.kind === \"click\") {\n await this.click(state, node.backendNodeId, node.epoch)\n return\n }\n await this.command(state, \"DOM.focus\", { backendNodeId: node.backendNodeId })\n await this.assertContextCurrent(state, node.epoch, \"Page changed during action; inspect again\")\n await this.command(state, \"Input.insertText\", { text: action.text })\n await this.assertContextCurrent(state, node.epoch, \"Page changed during action; inspect again\")\n })\n }\n\n async screenshot(identity: DeveloperCdpIdentity): Promise<DeveloperCdpScreenshot> {\n return this.exclusive(identity.runId, async () => {\n const state = await this.ensure(identity)\n const epoch = state.navigationEpoch\n const result = await this.command(state, \"Page.captureScreenshot\", {\n format: \"png\",\n fromSurface: true,\n captureBeyondViewport: false,\n })\n await this.assertContextCurrent(state, epoch, \"Page changed during screenshot; capture again\")\n if (typeof result.data !== \"string\") throw new Error(\"Chrome returned an invalid screenshot\")\n const bytes = Buffer.from(result.data, \"base64\").byteLength\n if (bytes > this.dependencies.maxScreenshotBytes) {\n throw new Error(`Screenshot exceeds ${this.dependencies.maxScreenshotBytes} byte limit`)\n }\n return { mediaType: \"image/png\", data: result.data, bytes }\n })\n }\n\n close(runId?: string): void {\n for (const [id, state] of this.runs) {\n if (runId && id !== runId) continue\n this.disconnect(state, new Error(\"Developer CDP controller closed\"))\n this.runs.delete(id)\n }\n }\n\n async context(selection: DeveloperCdpSelection): Promise<DeveloperCdpContext> {\n return this.exclusive(selection.runId, async () => (await this.ensure(selection)).context!)\n }\n\n private async ensure(identity: DeveloperCdpSelection | DeveloperCdpIdentity): Promise<RunState> {\n if (!identity.runId.trim()) throw new Error(\"runId is required\")\n const endpoint = discoveryUrl(identity.endpoint)\n for (const [runId, previous] of this.runs) {\n if (runId === identity.runId) continue\n this.disconnect(previous, new Error(\"Developer run was replaced\"))\n this.runs.delete(runId)\n }\n let state = this.runs.get(identity.runId)\n if (!state || state.endpoint !== endpoint || state.windowId !== identity.windowId || state.sessionId !== identity.sessionId\n || (\"instanceId\" in identity && state.instanceId !== identity.instanceId)) {\n if (state) this.disconnect(state, new Error(\"CDP endpoint changed\"))\n state = this.newState(endpoint, identity.windowId, identity.sessionId, \"instanceId\" in identity ? identity.instanceId : undefined)\n this.runs.set(identity.runId, state)\n }\n return this.ensureTarget(state)\n }\n\n private newState(endpoint: string, windowId: string, sessionId: string, instanceId?: string): RunState {\n return {\n endpoint,\n windowId,\n sessionId,\n instanceId,\n nextCommandId: 0,\n navigationEpoch: 0,\n pending: new Map(),\n refs: new Map(),\n diagnostics: [],\n }\n }\n\n private async ensureTarget(state: RunState): Promise<RunState> {\n const response = await this.dependencies.fetch(state.endpoint, {\n signal: AbortSignal.timeout(this.dependencies.timeoutMs),\n })\n if (!response.ok) throw new Error(`Chrome target discovery failed (HTTP ${response.status})`)\n const contentLength = Number(response.headers.get(\"content-length\"))\n if (Number.isFinite(contentLength) && contentLength > DISCOVERY_TEXT_LIMIT) {\n throw new Error(\"Chrome target discovery response is too large\")\n }\n const text = await response.text()\n if (Buffer.byteLength(text) > DISCOVERY_TEXT_LIMIT) throw new Error(\"Chrome target discovery response is too large\")\n let candidates: unknown\n try { candidates = JSON.parse(text) } catch { throw new Error(\"Chrome target discovery returned invalid JSON\") }\n if (!Array.isArray(candidates)) throw new Error(\"Chrome target discovery returned invalid JSON\")\n const targets = candidates.slice(0, DISCOVERY_TARGET_LIMIT).filter(isTarget).filter((target) => target.type === \"page\")\n let target = state.target && targets.find((candidate) => candidate.id === state.target!.id)\n if (!target) {\n this.disconnect(state, new Error(\"Chrome target was replaced\"))\n target = await this.discoverTarget(state, targets)\n }\n\n const replaced = state.target?.id !== target.id || state.target.webSocketDebuggerUrl !== target.webSocketDebuggerUrl\n if (replaced) this.disconnect(state, new Error(\"Chrome target was replaced\"))\n state.target = target\n if (!state.socket) await this.connect(state, target)\n else await state.open\n const context = await this.readContext(state)\n if (!this.matchesContext(state, context)) {\n this.invalidateRefs(state)\n state.instanceId = undefined\n this.disconnect(state, new Error(\"CodeNomad window or active session changed; inspect again\"))\n throw new Error(\"CodeNomad window or active session changed; inspect again\")\n }\n state.context = context\n return state\n }\n\n private async discoverTarget(state: RunState, targets: CdpTarget[]): Promise<CdpTarget> {\n const matches: CdpTarget[] = []\n for (let index = 0; index < targets.length && matches.length < 2; index += DISCOVERY_PROBE_CONCURRENCY) {\n const batch = await Promise.all(targets.slice(index, index + DISCOVERY_PROBE_CONCURRENCY).map(async (target) => {\n const probe = this.newState(state.endpoint, state.windowId, state.sessionId, state.instanceId)\n probe.target = target\n try {\n await this.connect(probe, target)\n return this.matchesContext(state, await this.readContext(probe)) ? target : undefined\n } catch {\n // Targets can disappear while Chromium's target list is being inspected.\n return undefined\n } finally {\n this.disconnect(probe, new Error(\"CDP target probe completed\"))\n }\n }))\n matches.push(...batch.filter((target): target is CdpTarget => Boolean(target)))\n }\n if (matches.length === 0) throw new Error(\"No CodeNomad page matches the selected window and OpenCode session\")\n if (matches.length > 1) throw new Error(\"Multiple CodeNomad pages match the selected window and OpenCode session\")\n return matches[0]\n }\n\n private async readContext(state: RunState): Promise<DeveloperCdpContext> {\n const response = await this.command(state, \"Runtime.evaluate\", {\n expression: CONTEXT_EXPRESSION,\n returnByValue: true,\n })\n const value = (response.result as { value?: unknown } | undefined)?.value as Partial<DeveloperCdpContext> | undefined\n if (!value || typeof value.windowId !== \"string\" || typeof value.instanceId !== \"string\" || typeof value.sessionId !== \"string\"\n || value.windowId.length > 256 || value.instanceId.length > 256 || value.sessionId.length > 256) {\n throw new Error(\"CodeNomad page has no active session context\")\n }\n return { windowId: value.windowId, instanceId: value.instanceId, sessionId: value.sessionId }\n }\n\n private matchesContext(state: RunState, context: DeveloperCdpContext): boolean {\n return context.windowId === state.windowId && context.sessionId === state.sessionId\n && (state.instanceId === undefined || context.instanceId === state.instanceId)\n }\n\n private async connect(state: RunState, target: CdpTarget): Promise<void> {\n const socket = this.dependencies.connect(target.webSocketDebuggerUrl)\n state.socket = socket\n state.open = new Promise<void>((resolve, reject) => {\n const fail = (error: Error) => {\n clearTimeout(timer)\n if (state.socket === socket) {\n this.disconnect(state, error)\n } else socket.close()\n reject(error)\n }\n const timer = setTimeout(() => fail(new Error(\"CDP WebSocket connection timed out\")), this.dependencies.timeoutMs)\n socket.onopen = () => { clearTimeout(timer); resolve() }\n socket.onerror = () => fail(new Error(\"CDP WebSocket connection failed\"))\n })\n socket.onmessage = (event) => this.onMessage(state, socket, event.data)\n socket.onclose = () => {\n if (state.socket !== socket) return\n state.socket = undefined\n state.open = undefined\n this.invalidateRefs(state)\n this.rejectPending(state, new Error(\"CDP WebSocket closed\"))\n }\n await state.open\n await this.command(state, \"Page.enable\")\n await this.command(state, \"Runtime.enable\")\n await this.command(state, \"Accessibility.enable\")\n }\n\n private command(\n state: RunState,\n method: string,\n params?: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n if (!state.socket) return Promise.reject(new Error(\"CDP WebSocket is not connected\"))\n const id = ++state.nextCommandId\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n state.pending.delete(id)\n reject(new Error(`CDP command ${method} timed out`))\n }, this.dependencies.timeoutMs)\n state.pending.set(id, { resolve, reject, timer })\n state.socket!.send(JSON.stringify({ id, method, ...(params ? { params } : {}) }))\n })\n }\n\n private onMessage(state: RunState, socket: CdpSocket, data: unknown): void {\n if (state.socket !== socket) return\n let message: CdpResponse\n try {\n const text = typeof data === \"string\" ? data : Buffer.from(data as ArrayBuffer).toString(\"utf8\")\n message = JSON.parse(text) as CdpResponse\n } catch {\n return\n }\n if (typeof message.id === \"number\") {\n const pending = state.pending.get(message.id)\n if (!pending) return\n clearTimeout(pending.timer)\n state.pending.delete(message.id)\n if (message.error) pending.reject(new Error(message.error.message ?? `CDP error ${message.error.code ?? \"unknown\"}`))\n else pending.resolve(message.result ?? {})\n return\n }\n if (message.method === \"Page.frameNavigated\") {\n state.navigationEpoch++\n state.refs.clear()\n return\n }\n const diagnostic = readDiagnostic(message)\n if (diagnostic) {\n state.diagnostics.push(diagnostic)\n if (state.diagnostics.length > DIAGNOSTIC_LIMIT) state.diagnostics.splice(0, state.diagnostics.length - DIAGNOSTIC_LIMIT)\n }\n }\n\n private resolveRef(state: RunState, ref: string): { backendNodeId: number; epoch: number } {\n const node = state.refs.get(ref)\n if (!node || node.targetId !== state.target?.id || node.epoch !== state.navigationEpoch) {\n throw new Error(`Unknown or stale accessibility ref: ${ref}`)\n }\n return node\n }\n\n private async click(state: RunState, backendNodeId: number, epoch: number): Promise<void> {\n await this.command(state, \"DOM.scrollIntoViewIfNeeded\", { backendNodeId })\n await this.assertContextCurrent(state, epoch, \"Page changed during action; inspect again\")\n const result = await this.command(state, \"DOM.resolveNode\", { backendNodeId })\n await this.assertContextCurrent(state, epoch, \"Page changed during action; inspect again\")\n const objectId = (result.object as { objectId?: unknown } | undefined)?.objectId\n if (typeof objectId !== \"string\") throw new Error(\"Chrome could not resolve the element\")\n await this.command(state, \"Runtime.callFunctionOn\", {\n objectId,\n functionDeclaration: \"function () { const element = this.nodeType === Node.ELEMENT_NODE ? this : this.parentElement; if (!(element instanceof HTMLElement)) throw new Error('Element is unavailable'); element.click(); }\",\n })\n await this.assertContextCurrent(state, epoch, \"Page changed during action; inspect again\")\n }\n\n private async assertContextCurrent(state: RunState, epoch: number, message: string): Promise<void> {\n if (state.navigationEpoch !== epoch || !state.socket) {\n throw new Error(message)\n }\n const context = await this.readContext(state)\n if (!this.matchesContext(state, context)) {\n this.invalidateRefs(state)\n state.context = context\n throw new Error(message)\n }\n if (state.navigationEpoch !== epoch || !state.socket) {\n throw new Error(message)\n }\n state.context = context\n }\n\n private exclusive<T>(runId: string, operation: () => Promise<T>): Promise<T> {\n const previous = this.operations.get(runId) ?? Promise.resolve()\n const queued = previous.catch(() => undefined).then(operation)\n const tail = queued.then(() => undefined, () => undefined)\n this.operations.set(runId, tail)\n return queued.finally(() => {\n if (this.operations.get(runId) === tail) this.operations.delete(runId)\n })\n }\n\n private invalidateRefs(state: RunState): void {\n state.navigationEpoch++\n state.refs.clear()\n }\n\n private disconnect(state: RunState, error: Error): void {\n const socket = state.socket\n state.socket = undefined\n state.open = undefined\n this.invalidateRefs(state)\n this.rejectPending(state, error)\n socket?.close()\n }\n\n private rejectPending(state: RunState, error: Error): void {\n for (const pending of state.pending.values()) {\n clearTimeout(pending.timer)\n pending.reject(error)\n }\n state.pending.clear()\n }\n}\n\nfunction discoveryUrl(endpoint: string): string {\n let url: URL\n try {\n url = new URL(endpoint)\n } catch {\n throw new Error(\"CDP endpoint must be an HTTP or HTTPS URL\")\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"CDP endpoint must be an HTTP or HTTPS URL\")\n }\n if (url.hostname !== \"127.0.0.1\") throw new Error(\"CDP endpoint must use the IPv4 loopback address\")\n if (url.username || url.password) throw new Error(\"CDP endpoint must not contain credentials\")\n return new URL(\"/json/list\", url).href\n}\n\nfunction isTarget(value: unknown): value is CdpTarget {\n const target = value as Partial<CdpTarget> | null\n return !!target\n && typeof target.id === \"string\"\n && typeof target.title === \"string\"\n && typeof target.type === \"string\"\n && typeof target.url === \"string\"\n && typeof target.webSocketDebuggerUrl === \"string\"\n && isLoopbackWebSocketUrl(target.webSocketDebuggerUrl)\n}\n\nfunction isLoopbackWebSocketUrl(value: string): boolean {\n try {\n const url = new URL(value)\n return (url.protocol === \"ws:\" || url.protocol === \"wss:\")\n && url.hostname === \"127.0.0.1\"\n && !url.username\n && !url.password\n } catch {\n return false\n }\n}\n\nfunction valueOf(value: AxValue | undefined): string {\n return typeof value?.value === \"string\" ? value.value : \"\"\n}\n\nfunction readDiagnostic(message: CdpResponse): DeveloperCdpDiagnostic | undefined {\n if (message.method === \"Runtime.consoleAPICalled\") {\n const params = message.params as { type?: unknown; args?: Array<{ value?: unknown; description?: unknown }> } | undefined\n const text = params?.args?.map((arg) => String(arg.value ?? arg.description ?? \"\")).join(\" \") ?? \"\"\n const level = params?.type === \"error\" || params?.type === \"assert\" ? \"error\"\n : params?.type === \"warning\" ? \"warning\" : \"log\"\n return { level, text: boundedText(text) }\n }\n if (message.method === \"Runtime.exceptionThrown\") {\n const params = message.params as { exceptionDetails?: { text?: unknown; exception?: { description?: unknown } } } | undefined\n const detail = params?.exceptionDetails\n return { level: \"error\", text: boundedText(String(detail?.exception?.description ?? detail?.text ?? \"Runtime exception\")) }\n }\n return undefined\n}\n\nfunction boundedText(text: string): string {\n return text.length > DIAGNOSTIC_TEXT_LIMIT ? `${text.slice(0, DIAGNOSTIC_TEXT_LIMIT - 3)}...` : text\n}\n"]}
1
+ {"version":3,"file":"developer-cdp.js","sourceRoot":"","sources":["../src/developer-cdp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAElC,MAAM,kBAAkB,GAAG,KAAK,CAAA;AAChC,MAAM,4BAA4B,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA;AACpD,MAAM,gBAAgB,GAAG,KAAK,CAAA;AAC9B,MAAM,mBAAmB,GAAG,GAAG,CAAA;AAC/B,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAA;AACrC,MAAM,qBAAqB,GAAG,GAAG,CAAA;AACjC,MAAM,oBAAoB,GAAG,GAAG,GAAG,IAAI,CAAA;AACvC,MAAM,sBAAsB,GAAG,EAAE,CAAA;AACjC,MAAM,2BAA2B,GAAG,CAAC,CAAA;AACrC,MAAM,kBAAkB,GAAG;;;;;;;;KAQtB,CAAA;AAmHL,MAAM,OAAO,YAAY;IAMvB,YAAY,eAAkD,EAAE;QAJ/C,SAAI,GAAG,IAAI,GAAG,EAAoB,CAAA;QAClC,eAAU,GAAG,IAAI,GAAG,EAAyB,CAAA;QACtD,cAAS,GAAG,CAAC,CAAA;QAGnB,IAAI,CAAC,YAAY,GAAG;YAClB,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,GAAG,CAAyB;YAC5D,SAAS,EAAE,kBAAkB;YAC7B,kBAAkB,EAAE,4BAA4B;YAChD,GAAG,YAAY;SAChB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAA8B;QAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACzC,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,CAAA;YACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAA;YACvE,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,+CAA+C,CAAC,CAAA;YAE9F,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;YAClB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAiB,CAAC,CAAC,CAAC,EAAE,CAAA;YACzE,MAAM,QAAQ,GAAuB,EAAE,CAAA;YACvC,IAAI,QAAQ,GAAG,CAAC,CAAA;YAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC;oBAAE,SAAQ;gBACtE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAC/B,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;oBAAE,SAAQ;gBACnG,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gBAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBACjC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;qBACnC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;qBAC9G,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;gBACzE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;gBACpG,IAAI,QAAQ,CAAC,MAAM,IAAI,mBAAmB,IAAI,QAAQ,GAAG,IAAI,GAAG,mBAAmB;oBAAE,MAAK;gBAC1F,QAAQ,IAAI,IAAI,CAAA;gBAChB,MAAM,GAAG,GAAG,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,CAAA;gBACnC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;oBAClB,aAAa,EAAE,IAAI,CAAC,gBAAiB;oBACrC,QAAQ,EAAE,KAAK,CAAC,MAAO,CAAC,EAAE;oBAC1B,KAAK;iBACN,CAAC,CAAA;gBACF,QAAQ,CAAC,IAAI,CAAC;oBACZ,GAAG;oBACH,IAAI;oBACJ,IAAI;oBACJ,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3B,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACrC,CAAC,CAAA;YACJ,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,MAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAO,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,MAAO,CAAC,GAAG,EAAE;gBACpF,OAAO,EAAE,KAAK,CAAC,OAAQ;gBACvB,KAAK,EAAE,QAAQ;gBACf,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;aACzC,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAA0B;QAClC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACvC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAA;YAC/C,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5B,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;gBACvD,OAAM;YACR,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAA;YAC7E,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,2CAA2C,CAAC,CAAA;YAC/F,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;YACpE,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,2CAA2C,CAAC,CAAA;QACjG,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAA8B;QAC7C,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACzC,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,CAAA;YACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,wBAAwB,EAAE;gBACjE,MAAM,EAAE,KAAK;gBACb,WAAW,EAAE,IAAI;gBACjB,qBAAqB,EAAE,KAAK;aAC7B,CAAC,CAAA;YACF,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,+CAA+C,CAAC,CAAA;YAC9F,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;YAC7F,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,UAAU,CAAA;YAC3D,IAAI,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE,CAAC;gBACjD,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,YAAY,CAAC,kBAAkB,aAAa,CAAC,CAAA;YAC1F,CAAC;YACD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAA;QAC7D,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,KAAc;QAClB,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,KAAK,IAAI,EAAE,KAAK,KAAK;gBAAE,SAAQ;YACnC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAA;YACpE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAgC;QAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,OAAQ,CAAC,CAAA;IAC7F,CAAC;IAGO,KAAK,CAAC,MAAM,CAAC,QAAsD;QACzE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAChE,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAChD,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1C,IAAI,KAAK,KAAK,QAAQ,CAAC,KAAK;gBAAE,SAAQ;YACtC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAA;YAClE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACzB,CAAC;QACD,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACzC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,SAAS;eACtH,CAAC,YAAY,IAAI,QAAQ,IAAI,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5E,IAAI,KAAK;gBAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAA;YACpE,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,EAAE,YAAY,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YAClI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACtC,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IAEO,QAAQ,CAAC,QAAgB,EAAE,QAAgB,EAAE,SAAkB,EAAE,UAAmB;QAC1F,OAAO;YACL,QAAQ;YACR,QAAQ;YACR,SAAS;YACT,UAAU;YACV,aAAa,EAAE,CAAC;YAChB,eAAe,EAAE,CAAC;YAClB,OAAO,EAAE,IAAI,GAAG,EAAE;YAClB,IAAI,EAAE,IAAI,GAAG,EAAE;YACf,WAAW,EAAE,EAAE;SAChB,CAAA;IACH,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,KAAe;QACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE;YAC7D,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;SACzD,CAAC,CAAA;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;QAC7F,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAA;QACpE,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,oBAAoB,EAAE,CAAC;YAC3E,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAClE,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAClC,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,oBAAoB;YAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QACpH,IAAI,UAAmB,CAAA;QACvB,IAAI,CAAC;YAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAAC,CAAC;QAChH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAChG,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAA;QACvH,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,KAAK,CAAC,MAAO,CAAC,EAAE,CAAC,CAAA;QAC3F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAA;YAC/D,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QACpD,CAAC;QAED,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,KAAK,MAAM,CAAC,EAAE,IAAI,KAAK,CAAC,MAAM,CAAC,oBAAoB,KAAK,MAAM,CAAC,oBAAoB,CAAA;QACpH,IAAI,QAAQ;YAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAA;QAC7E,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;;YAC/C,MAAM,KAAK,CAAC,IAAI,CAAA;QACrB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAC7C,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;YAC1B,KAAK,CAAC,UAAU,GAAG,SAAS,CAAA;YAC5B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC,CAAA;YAC9F,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAA;QAC9E,CAAC;QACD,KAAK,CAAC,OAAO,GAAG,OAAO,CAAA;QACvB,OAAO,KAAK,CAAA;IACd,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,KAAe,EAAE,OAAoB;QAChE,MAAM,OAAO,GAAgB,EAAE,CAAA;QAC/B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,2BAA2B,EAAE,CAAC;YACvG,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,2BAA2B,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;gBAC7G,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;gBAC9F,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;gBACrB,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;oBACjC,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;gBACvF,CAAC;gBAAC,MAAM,CAAC;oBACP,yEAAyE;oBACzE,OAAO,SAAS,CAAA;gBAClB,CAAC;wBAAS,CAAC;oBACT,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAA;gBACjE,CAAC;YACH,CAAC,CAAC,CAAC,CAAA;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAuB,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjF,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAA;QAC/G,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAA;QAClH,OAAO,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,KAAe;QACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,kBAAkB,EAAE;YAC7D,UAAU,EAAE,kBAAkB;YAC9B,aAAa,EAAE,IAAI;SACpB,CAAC,CAAA;QACF,MAAM,KAAK,GAAI,QAAQ,CAAC,MAA0C,EAAE,KAAiD,CAAA;QACrH,MAAM,UAAU,GAAG,CAAC,EAAW,EAAE,EAAE,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,IAAI,GAAG,CAAC,CAAA;QAC/F,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG;eAC1E,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;QAC/D,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAW,EAAE,SAAS,EAAE,KAAK,CAAC,SAAU,EAAE,CAAA;IACjG,CAAC;IAEO,cAAc,CAAC,KAAe,EAAE,OAA4B;QAClE,OAAO,OAAO,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CAAC;eACjH,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC,CAAA;IAClF,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,KAAe,EAAE,MAAiB;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA;QACrE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;QACrB,KAAK,CAAC,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACjD,MAAM,IAAI,GAAG,CAAC,KAAY,EAAE,EAAE;gBAC5B,YAAY,CAAC,KAAK,CAAC,CAAA;gBACnB,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;oBAC5B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;gBAC/B,CAAC;;oBAAM,MAAM,CAAC,KAAK,EAAE,CAAA;gBACrB,MAAM,CAAC,KAAK,CAAC,CAAA;YACf,CAAC,CAAA;YACD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;YAClH,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA,CAAC,CAAC,CAAA;YACxD,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;QACF,MAAM,CAAC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACvE,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;YACpB,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;gBAAE,OAAM;YACnC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAA;YACxB,KAAK,CAAC,IAAI,GAAG,SAAS,CAAA;YACtB,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;YAC1B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAA;QAC9D,CAAC,CAAA;QACD,MAAM,KAAK,CAAC,IAAI,CAAA;QAChB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,CAAA;QACxC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAA;QAC3C,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAA;IACnD,CAAC;IAEO,OAAO,CACb,KAAe,EACf,MAAc,EACd,MAAgC;QAEhC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAA;QACrF,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,aAAa,CAAA;QAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBACxB,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,MAAM,YAAY,CAAC,CAAC,CAAA;YACtD,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;YAC/B,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;YACjD,KAAK,CAAC,MAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACnF,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,SAAS,CAAC,KAAe,EAAE,MAAiB,EAAE,IAAa;QACjE,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;YAAE,OAAM;QACnC,IAAI,OAAoB,CAAA;QACxB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAmB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAChG,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAA;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,OAAM;QACR,CAAC;QACD,IAAI,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;YAC7C,IAAI,CAAC,OAAO;gBAAE,OAAM;YACpB,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YAC3B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;YAChC,IAAI,OAAO,CAAC,KAAK;gBAAE,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,aAAa,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC,CAAA;;gBAChH,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;YAC1C,OAAM;QACR,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,qBAAqB,EAAE,CAAC;YAC7C,KAAK,CAAC,eAAe,EAAE,CAAA;YACvB,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;YAClB,OAAM;QACR,CAAC;QACD,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;QAC1C,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YAClC,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,gBAAgB;gBAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,gBAAgB,CAAC,CAAA;QAC3H,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,KAAe,EAAE,GAAW;QAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAChC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,eAAe,EAAE,CAAC;YACxF,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,EAAE,CAAC,CAAA;QAC/D,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,KAAe,EAAE,aAAqB,EAAE,KAAa;QACvE,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,4BAA4B,EAAE,EAAE,aAAa,EAAE,CAAC,CAAA;QAC1E,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,2CAA2C,CAAC,CAAA;QAC1F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,iBAAiB,EAAE,EAAE,aAAa,EAAE,CAAC,CAAA;QAC9E,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,2CAA2C,CAAC,CAAA;QAC1F,MAAM,QAAQ,GAAI,MAAM,CAAC,MAA6C,EAAE,QAAQ,CAAA;QAChF,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;QACzF,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,wBAAwB,EAAE;YAClD,QAAQ;YACR,mBAAmB,EAAE,qMAAqM;SAC3N,CAAC,CAAA;QACF,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,2CAA2C,CAAC,CAAA;IAC5F,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,KAAe,EAAE,KAAa,EAAE,OAAe;QAChF,IAAI,KAAK,CAAC,eAAe,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;QAC1B,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAC7C,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;YAC1B,KAAK,CAAC,OAAO,GAAG,OAAO,CAAA;YACvB,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;QAC1B,CAAC;QACD,IAAI,KAAK,CAAC,eAAe,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;QAC1B,CAAC;QACD,KAAK,CAAC,OAAO,GAAG,OAAO,CAAA;IACzB,CAAC;IAEO,SAAS,CAAI,KAAa,EAAE,SAA2B;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAA;QAChE,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;QAC1D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAChC,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;YACzB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI;gBAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACxE,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,cAAc,CAAC,KAAe;QACpC,KAAK,CAAC,eAAe,EAAE,CAAA;QACvB,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IAEO,UAAU,CAAC,KAAe,EAAE,KAAY;QAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;QAC3B,KAAK,CAAC,MAAM,GAAG,SAAS,CAAA;QACxB,KAAK,CAAC,IAAI,GAAG,SAAS,CAAA;QACtB,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;QAC1B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QAChC,MAAM,EAAE,KAAK,EAAE,CAAA;IACjB,CAAC;IAEO,aAAa,CAAC,KAAe,EAAE,KAAY;QACjD,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACvB,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;IACvB,CAAC;CACF;AAED,SAAS,YAAY,CAAC,QAAgB;IACpC,IAAI,GAAQ,CAAA;IACZ,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IACpG,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9F,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,IAAI,CAAA;AACxC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,MAAM,MAAM,GAAG,KAAkC,CAAA;IACjD,OAAO,CAAC,CAAC,MAAM;WACV,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ;WAC7B,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;WAChC,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;WAC/B,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;WAC9B,OAAO,MAAM,CAAC,oBAAoB,KAAK,QAAQ;WAC/C,sBAAsB,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA;AAC1D,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;QAC1B,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,KAAK,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC;eACrD,GAAG,CAAC,QAAQ,KAAK,WAAW;eAC5B,CAAC,GAAG,CAAC,QAAQ;eACb,CAAC,GAAG,CAAC,QAAQ,CAAA;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,KAA0B;IACzC,OAAO,OAAO,KAAK,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;AAC5D,CAAC;AAED,SAAS,cAAc,CAAC,OAAoB;IAC1C,IAAI,OAAO,CAAC,MAAM,KAAK,0BAA0B,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAkG,CAAA;QACzH,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;QACnG,MAAM,KAAK,GAAG,MAAM,EAAE,IAAI,KAAK,OAAO,IAAI,MAAM,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO;YAC3E,CAAC,CAAC,MAAM,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;QAClD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,CAAA;IAC3C,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,yBAAyB,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAsG,CAAA;QAC7H,MAAM,MAAM,GAAG,MAAM,EAAE,gBAAgB,CAAA;QACvC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,IAAI,MAAM,EAAE,IAAI,IAAI,mBAAmB,CAAC,CAAC,EAAE,CAAA;IAC7H,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;AACtG,CAAC","sourcesContent":["import { WebSocket } from \"undici\"\n\nconst DEFAULT_TIMEOUT_MS = 5_000\nconst DEFAULT_MAX_SCREENSHOT_BYTES = 5 * 1024 * 1024\nconst DIAGNOSTIC_LIMIT = 1_000\nconst SNAPSHOT_NODE_LIMIT = 750\nconst SNAPSHOT_TEXT_LIMIT = 64 * 1024\nconst DIAGNOSTIC_TEXT_LIMIT = 512\nconst DISCOVERY_TEXT_LIMIT = 256 * 1024\nconst DISCOVERY_TARGET_LIMIT = 64\nconst DISCOVERY_PROBE_CONCURRENCY = 4\nconst CONTEXT_EXPRESSION = `(() => {\n const root = document.querySelector('[data-tab-visible=\"true\"][data-instance-id]');\n const pane = root?.querySelector('.session-cache-pane[data-session-active=\"true\"][data-session-id]');\n return {\n windowId: window.__CODENOMAD_WINDOW_ID__ ?? null,\n instanceId: root?.getAttribute('data-instance-id') ?? null,\n sessionId: pane?.getAttribute('data-session-id') ?? null,\n };\n})()`\n\nexport interface DeveloperCdpSelection {\n endpoint: string\n runId: string\n windowId: string\n sessionId?: string\n}\n\nexport interface DeveloperCdpIdentity extends DeveloperCdpSelection {\n instanceId?: string\n}\n\nexport interface DeveloperCdpContext {\n windowId: string\n instanceId: string | null\n sessionId: string | null\n}\n\nexport interface DeveloperCdpNode {\n ref?: string\n role: string\n name: string\n description?: string\n value?: string\n states?: string[]\n}\n\nexport interface DeveloperCdpDiagnostic {\n level: \"log\" | \"warning\" | \"error\"\n text: string\n}\n\nexport interface DeveloperCdpInspection {\n target: { id: string; title: string; url: string }\n context: DeveloperCdpContext\n nodes: DeveloperCdpNode[]\n diagnostics: DeveloperCdpDiagnostic[]\n}\n\nexport type DeveloperCdpAction =\n | (DeveloperCdpIdentity & { kind: \"click\"; ref: string })\n | (DeveloperCdpIdentity & { kind: \"type\"; ref: string; text: string })\n\nexport interface DeveloperCdpScreenshot {\n mediaType: \"image/png\"\n data: string\n bytes: number\n}\n\ninterface CdpSocket {\n onopen: ((event: unknown) => void) | null\n onmessage: ((event: { data: unknown }) => void) | null\n onclose: ((event: unknown) => void) | null\n onerror: ((event: unknown) => void) | null\n send(data: string): void\n close(): void\n}\n\ninterface DeveloperCdpDependencies {\n fetch: typeof globalThis.fetch\n connect: (url: string) => CdpSocket\n timeoutMs: number\n maxScreenshotBytes: number\n}\n\ninterface CdpTarget {\n id: string\n title: string\n type: string\n url: string\n webSocketDebuggerUrl: string\n}\n\ninterface CdpResponse {\n id?: number\n method?: string\n params?: Record<string, unknown>\n result?: Record<string, unknown>\n error?: { code?: number; message?: string }\n}\n\ninterface PendingCommand {\n resolve: (value: Record<string, unknown>) => void\n reject: (error: Error) => void\n timer: NodeJS.Timeout\n}\n\ninterface RunState {\n endpoint: string\n windowId: string\n sessionId?: string\n instanceId?: string\n context?: DeveloperCdpContext\n target?: CdpTarget\n socket?: CdpSocket\n open?: Promise<void>\n nextCommandId: number\n navigationEpoch: number\n pending: Map<number, PendingCommand>\n refs: Map<string, { backendNodeId: number; targetId: string; epoch: number }>\n diagnostics: DeveloperCdpDiagnostic[]\n}\n\ninterface AxValue { value?: unknown }\ninterface AxNode {\n ignored?: boolean\n backendDOMNodeId?: number\n role?: AxValue\n name?: AxValue\n description?: AxValue\n value?: AxValue\n properties?: Array<{ name?: string; value?: AxValue }>\n}\n\nexport class DeveloperCdp {\n private readonly dependencies: DeveloperCdpDependencies\n private readonly runs = new Map<string, RunState>()\n private readonly operations = new Map<string, Promise<void>>()\n private nextRefId = 0\n\n constructor(dependencies: Partial<DeveloperCdpDependencies> = {}) {\n this.dependencies = {\n fetch: globalThis.fetch,\n connect: (url) => new WebSocket(url) as unknown as CdpSocket,\n timeoutMs: DEFAULT_TIMEOUT_MS,\n maxScreenshotBytes: DEFAULT_MAX_SCREENSHOT_BYTES,\n ...dependencies,\n }\n }\n\n async inspect(identity: DeveloperCdpIdentity): Promise<DeveloperCdpInspection> {\n return this.exclusive(identity.runId, async () => {\n const state = await this.ensure(identity)\n const epoch = state.navigationEpoch\n const result = await this.command(state, \"Accessibility.getFullAXTree\")\n await this.assertContextCurrent(state, epoch, \"Page changed during inspection; inspect again\")\n\n state.refs.clear()\n const nodes = Array.isArray(result.nodes) ? result.nodes as AxNode[] : []\n const snapshot: DeveloperCdpNode[] = []\n let textSize = 0\n for (const node of nodes) {\n if (node.ignored || !Number.isInteger(node.backendDOMNodeId)) continue\n const role = valueOf(node.role)\n const name = valueOf(node.name)\n if (!role || (!name && [\"generic\", \"none\", \"StaticText\", \"InlineTextBox\"].includes(role))) continue\n const description = valueOf(node.description)\n const value = valueOf(node.value)\n const states = (node.properties ?? [])\n .filter((property) => [\"checked\", \"disabled\", \"expanded\", \"focused\", \"selected\"].includes(property.name ?? \"\"))\n .map((property) => `${property.name}=${String(property.value?.value)}`)\n const size = role.length + name.length + description.length + value.length + states.join(\" \").length\n if (snapshot.length >= SNAPSHOT_NODE_LIMIT || textSize + size > SNAPSHOT_TEXT_LIMIT) break\n textSize += size\n const ref = `ax${++this.nextRefId}`\n state.refs.set(ref, {\n backendNodeId: node.backendDOMNodeId!,\n targetId: state.target!.id,\n epoch,\n })\n snapshot.push({\n ref,\n role,\n name,\n ...(description ? { description } : {}),\n ...(value ? { value } : {}),\n ...(states.length ? { states } : {}),\n })\n }\n return {\n target: { id: state.target!.id, title: state.target!.title, url: state.target!.url },\n context: state.context!,\n nodes: snapshot,\n diagnostics: state.diagnostics.splice(0),\n }\n })\n }\n\n async act(action: DeveloperCdpAction): Promise<void> {\n return this.exclusive(action.runId, async () => {\n const state = await this.ensure(action)\n const node = this.resolveRef(state, action.ref)\n if (action.kind === \"click\") {\n await this.click(state, node.backendNodeId, node.epoch)\n return\n }\n await this.command(state, \"DOM.focus\", { backendNodeId: node.backendNodeId })\n await this.assertContextCurrent(state, node.epoch, \"Page changed during action; inspect again\")\n await this.command(state, \"Input.insertText\", { text: action.text })\n await this.assertContextCurrent(state, node.epoch, \"Page changed during action; inspect again\")\n })\n }\n\n async screenshot(identity: DeveloperCdpIdentity): Promise<DeveloperCdpScreenshot> {\n return this.exclusive(identity.runId, async () => {\n const state = await this.ensure(identity)\n const epoch = state.navigationEpoch\n const result = await this.command(state, \"Page.captureScreenshot\", {\n format: \"png\",\n fromSurface: true,\n captureBeyondViewport: false,\n })\n await this.assertContextCurrent(state, epoch, \"Page changed during screenshot; capture again\")\n if (typeof result.data !== \"string\") throw new Error(\"Chrome returned an invalid screenshot\")\n const bytes = Buffer.from(result.data, \"base64\").byteLength\n if (bytes > this.dependencies.maxScreenshotBytes) {\n throw new Error(`Screenshot exceeds ${this.dependencies.maxScreenshotBytes} byte limit`)\n }\n return { mediaType: \"image/png\", data: result.data, bytes }\n })\n }\n\n close(runId?: string): void {\n for (const [id, state] of this.runs) {\n if (runId && id !== runId) continue\n this.disconnect(state, new Error(\"Developer CDP controller closed\"))\n this.runs.delete(id)\n }\n }\n\n async context(selection: DeveloperCdpSelection): Promise<DeveloperCdpContext> {\n return this.exclusive(selection.runId, async () => (await this.ensure(selection)).context!)\n }\n\n\n private async ensure(identity: DeveloperCdpSelection | DeveloperCdpIdentity): Promise<RunState> {\n if (!identity.runId.trim()) throw new Error(\"runId is required\")\n const endpoint = discoveryUrl(identity.endpoint)\n for (const [runId, previous] of this.runs) {\n if (runId === identity.runId) continue\n this.disconnect(previous, new Error(\"Developer run was replaced\"))\n this.runs.delete(runId)\n }\n let state = this.runs.get(identity.runId)\n if (!state || state.endpoint !== endpoint || state.windowId !== identity.windowId || state.sessionId !== identity.sessionId\n || (\"instanceId\" in identity && state.instanceId !== identity.instanceId)) {\n if (state) this.disconnect(state, new Error(\"CDP endpoint changed\"))\n state = this.newState(endpoint, identity.windowId, identity.sessionId, \"instanceId\" in identity ? identity.instanceId : undefined)\n this.runs.set(identity.runId, state)\n }\n return this.ensureTarget(state)\n }\n\n private newState(endpoint: string, windowId: string, sessionId?: string, instanceId?: string): RunState {\n return {\n endpoint,\n windowId,\n sessionId,\n instanceId,\n nextCommandId: 0,\n navigationEpoch: 0,\n pending: new Map(),\n refs: new Map(),\n diagnostics: [],\n }\n }\n\n private async ensureTarget(state: RunState): Promise<RunState> {\n const response = await this.dependencies.fetch(state.endpoint, {\n signal: AbortSignal.timeout(this.dependencies.timeoutMs),\n })\n if (!response.ok) throw new Error(`Chrome target discovery failed (HTTP ${response.status})`)\n const contentLength = Number(response.headers.get(\"content-length\"))\n if (Number.isFinite(contentLength) && contentLength > DISCOVERY_TEXT_LIMIT) {\n throw new Error(\"Chrome target discovery response is too large\")\n }\n const text = await response.text()\n if (Buffer.byteLength(text) > DISCOVERY_TEXT_LIMIT) throw new Error(\"Chrome target discovery response is too large\")\n let candidates: unknown\n try { candidates = JSON.parse(text) } catch { throw new Error(\"Chrome target discovery returned invalid JSON\") }\n if (!Array.isArray(candidates)) throw new Error(\"Chrome target discovery returned invalid JSON\")\n const targets = candidates.slice(0, DISCOVERY_TARGET_LIMIT).filter(isTarget).filter((target) => target.type === \"page\")\n let target = state.target && targets.find((candidate) => candidate.id === state.target!.id)\n if (!target) {\n this.disconnect(state, new Error(\"Chrome target was replaced\"))\n target = await this.discoverTarget(state, targets)\n }\n\n const replaced = state.target?.id !== target.id || state.target.webSocketDebuggerUrl !== target.webSocketDebuggerUrl\n if (replaced) this.disconnect(state, new Error(\"Chrome target was replaced\"))\n state.target = target\n if (!state.socket) await this.connect(state, target)\n else await state.open\n const context = await this.readContext(state)\n if (!this.matchesContext(state, context)) {\n this.invalidateRefs(state)\n state.instanceId = undefined\n this.disconnect(state, new Error(\"CodeNomad window or active session changed; inspect again\"))\n throw new Error(\"CodeNomad window or active session changed; inspect again\")\n }\n state.context = context\n return state\n }\n\n private async discoverTarget(state: RunState, targets: CdpTarget[]): Promise<CdpTarget> {\n const matches: CdpTarget[] = []\n for (let index = 0; index < targets.length && matches.length < 2; index += DISCOVERY_PROBE_CONCURRENCY) {\n const batch = await Promise.all(targets.slice(index, index + DISCOVERY_PROBE_CONCURRENCY).map(async (target) => {\n const probe = this.newState(state.endpoint, state.windowId, state.sessionId, state.instanceId)\n probe.target = target\n try {\n await this.connect(probe, target)\n return this.matchesContext(state, await this.readContext(probe)) ? target : undefined\n } catch {\n // Targets can disappear while Chromium's target list is being inspected.\n return undefined\n } finally {\n this.disconnect(probe, new Error(\"CDP target probe completed\"))\n }\n }))\n matches.push(...batch.filter((target): target is CdpTarget => Boolean(target)))\n }\n if (matches.length === 0) throw new Error(\"No CodeNomad page matches the selected window and OpenCode session\")\n if (matches.length > 1) throw new Error(\"Multiple CodeNomad pages match the selected window and OpenCode session\")\n return matches[0]\n }\n\n private async readContext(state: RunState): Promise<DeveloperCdpContext> {\n const response = await this.command(state, \"Runtime.evaluate\", {\n expression: CONTEXT_EXPRESSION,\n returnByValue: true,\n })\n const value = (response.result as { value?: unknown } | undefined)?.value as Partial<DeveloperCdpContext> | undefined\n const optionalId = (id: unknown) => id === null || (typeof id === \"string\" && id.length <= 256)\n if (!value || typeof value.windowId !== \"string\" || value.windowId.length > 256\n || !optionalId(value.instanceId) || !optionalId(value.sessionId)) {\n throw new Error(\"CodeNomad page has no valid window context\")\n }\n return { windowId: value.windowId, instanceId: value.instanceId!, sessionId: value.sessionId! }\n }\n\n private matchesContext(state: RunState, context: DeveloperCdpContext): boolean {\n return context.windowId === state.windowId && (state.sessionId === undefined || context.sessionId === state.sessionId)\n && (state.instanceId === undefined || context.instanceId === state.instanceId)\n }\n\n private async connect(state: RunState, target: CdpTarget): Promise<void> {\n const socket = this.dependencies.connect(target.webSocketDebuggerUrl)\n state.socket = socket\n state.open = new Promise<void>((resolve, reject) => {\n const fail = (error: Error) => {\n clearTimeout(timer)\n if (state.socket === socket) {\n this.disconnect(state, error)\n } else socket.close()\n reject(error)\n }\n const timer = setTimeout(() => fail(new Error(\"CDP WebSocket connection timed out\")), this.dependencies.timeoutMs)\n socket.onopen = () => { clearTimeout(timer); resolve() }\n socket.onerror = () => fail(new Error(\"CDP WebSocket connection failed\"))\n })\n socket.onmessage = (event) => this.onMessage(state, socket, event.data)\n socket.onclose = () => {\n if (state.socket !== socket) return\n state.socket = undefined\n state.open = undefined\n this.invalidateRefs(state)\n this.rejectPending(state, new Error(\"CDP WebSocket closed\"))\n }\n await state.open\n await this.command(state, \"Page.enable\")\n await this.command(state, \"Runtime.enable\")\n await this.command(state, \"Accessibility.enable\")\n }\n\n private command(\n state: RunState,\n method: string,\n params?: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n if (!state.socket) return Promise.reject(new Error(\"CDP WebSocket is not connected\"))\n const id = ++state.nextCommandId\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n state.pending.delete(id)\n reject(new Error(`CDP command ${method} timed out`))\n }, this.dependencies.timeoutMs)\n state.pending.set(id, { resolve, reject, timer })\n state.socket!.send(JSON.stringify({ id, method, ...(params ? { params } : {}) }))\n })\n }\n\n private onMessage(state: RunState, socket: CdpSocket, data: unknown): void {\n if (state.socket !== socket) return\n let message: CdpResponse\n try {\n const text = typeof data === \"string\" ? data : Buffer.from(data as ArrayBuffer).toString(\"utf8\")\n message = JSON.parse(text) as CdpResponse\n } catch {\n return\n }\n if (typeof message.id === \"number\") {\n const pending = state.pending.get(message.id)\n if (!pending) return\n clearTimeout(pending.timer)\n state.pending.delete(message.id)\n if (message.error) pending.reject(new Error(message.error.message ?? `CDP error ${message.error.code ?? \"unknown\"}`))\n else pending.resolve(message.result ?? {})\n return\n }\n if (message.method === \"Page.frameNavigated\") {\n state.navigationEpoch++\n state.refs.clear()\n return\n }\n const diagnostic = readDiagnostic(message)\n if (diagnostic) {\n state.diagnostics.push(diagnostic)\n if (state.diagnostics.length > DIAGNOSTIC_LIMIT) state.diagnostics.splice(0, state.diagnostics.length - DIAGNOSTIC_LIMIT)\n }\n }\n\n private resolveRef(state: RunState, ref: string): { backendNodeId: number; epoch: number } {\n const node = state.refs.get(ref)\n if (!node || node.targetId !== state.target?.id || node.epoch !== state.navigationEpoch) {\n throw new Error(`Unknown or stale accessibility ref: ${ref}`)\n }\n return node\n }\n\n private async click(state: RunState, backendNodeId: number, epoch: number): Promise<void> {\n await this.command(state, \"DOM.scrollIntoViewIfNeeded\", { backendNodeId })\n await this.assertContextCurrent(state, epoch, \"Page changed during action; inspect again\")\n const result = await this.command(state, \"DOM.resolveNode\", { backendNodeId })\n await this.assertContextCurrent(state, epoch, \"Page changed during action; inspect again\")\n const objectId = (result.object as { objectId?: unknown } | undefined)?.objectId\n if (typeof objectId !== \"string\") throw new Error(\"Chrome could not resolve the element\")\n await this.command(state, \"Runtime.callFunctionOn\", {\n objectId,\n functionDeclaration: \"function () { const element = this.nodeType === Node.ELEMENT_NODE ? this : this.parentElement; if (!(element instanceof HTMLElement)) throw new Error('Element is unavailable'); element.click(); }\",\n })\n await this.assertContextCurrent(state, epoch, \"Page changed during action; inspect again\")\n }\n\n private async assertContextCurrent(state: RunState, epoch: number, message: string): Promise<void> {\n if (state.navigationEpoch !== epoch || !state.socket) {\n throw new Error(message)\n }\n const context = await this.readContext(state)\n if (!this.matchesContext(state, context)) {\n this.invalidateRefs(state)\n state.context = context\n throw new Error(message)\n }\n if (state.navigationEpoch !== epoch || !state.socket) {\n throw new Error(message)\n }\n state.context = context\n }\n\n private exclusive<T>(runId: string, operation: () => Promise<T>): Promise<T> {\n const previous = this.operations.get(runId) ?? Promise.resolve()\n const queued = previous.catch(() => undefined).then(operation)\n const tail = queued.then(() => undefined, () => undefined)\n this.operations.set(runId, tail)\n return queued.finally(() => {\n if (this.operations.get(runId) === tail) this.operations.delete(runId)\n })\n }\n\n private invalidateRefs(state: RunState): void {\n state.navigationEpoch++\n state.refs.clear()\n }\n\n private disconnect(state: RunState, error: Error): void {\n const socket = state.socket\n state.socket = undefined\n state.open = undefined\n this.invalidateRefs(state)\n this.rejectPending(state, error)\n socket?.close()\n }\n\n private rejectPending(state: RunState, error: Error): void {\n for (const pending of state.pending.values()) {\n clearTimeout(pending.timer)\n pending.reject(error)\n }\n state.pending.clear()\n }\n}\n\nfunction discoveryUrl(endpoint: string): string {\n let url: URL\n try {\n url = new URL(endpoint)\n } catch {\n throw new Error(\"CDP endpoint must be an HTTP or HTTPS URL\")\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"CDP endpoint must be an HTTP or HTTPS URL\")\n }\n if (url.hostname !== \"127.0.0.1\") throw new Error(\"CDP endpoint must use the IPv4 loopback address\")\n if (url.username || url.password) throw new Error(\"CDP endpoint must not contain credentials\")\n return new URL(\"/json/list\", url).href\n}\n\nfunction isTarget(value: unknown): value is CdpTarget {\n const target = value as Partial<CdpTarget> | null\n return !!target\n && typeof target.id === \"string\"\n && typeof target.title === \"string\"\n && typeof target.type === \"string\"\n && typeof target.url === \"string\"\n && typeof target.webSocketDebuggerUrl === \"string\"\n && isLoopbackWebSocketUrl(target.webSocketDebuggerUrl)\n}\n\nfunction isLoopbackWebSocketUrl(value: string): boolean {\n try {\n const url = new URL(value)\n return (url.protocol === \"ws:\" || url.protocol === \"wss:\")\n && url.hostname === \"127.0.0.1\"\n && !url.username\n && !url.password\n } catch {\n return false\n }\n}\n\nfunction valueOf(value: AxValue | undefined): string {\n return typeof value?.value === \"string\" ? value.value : \"\"\n}\n\nfunction readDiagnostic(message: CdpResponse): DeveloperCdpDiagnostic | undefined {\n if (message.method === \"Runtime.consoleAPICalled\") {\n const params = message.params as { type?: unknown; args?: Array<{ value?: unknown; description?: unknown }> } | undefined\n const text = params?.args?.map((arg) => String(arg.value ?? arg.description ?? \"\")).join(\" \") ?? \"\"\n const level = params?.type === \"error\" || params?.type === \"assert\" ? \"error\"\n : params?.type === \"warning\" ? \"warning\" : \"log\"\n return { level, text: boundedText(text) }\n }\n if (message.method === \"Runtime.exceptionThrown\") {\n const params = message.params as { exceptionDetails?: { text?: unknown; exception?: { description?: unknown } } } | undefined\n const detail = params?.exceptionDetails\n return { level: \"error\", text: boundedText(String(detail?.exception?.description ?? detail?.text ?? \"Runtime exception\")) }\n }\n return undefined\n}\n\nfunction boundedText(text: string): string {\n return text.length > DIAGNOSTIC_TEXT_LIMIT ? `${text.slice(0, DIAGNOSTIC_TEXT_LIMIT - 3)}...` : text\n}\n"]}
@@ -91,6 +91,24 @@ const identity = {
91
91
  instanceId: "workspace-1",
92
92
  };
93
93
  describe("DeveloperCdp", () => {
94
+ it("keeps window-scoped tools usable across session/project navigation and empty views", async () => {
95
+ const chrome = new FakeChrome();
96
+ const client = chrome.client();
97
+ const window = { endpoint: identity.endpoint, runId: identity.runId, windowId: identity.windowId };
98
+ try {
99
+ const first = await client.inspect(window);
100
+ chrome.context = { ...chrome.context, sessionId: "another-session", instanceId: "another-project" };
101
+ await client.act({ ...window, kind: "click", ref: first.nodes[0].ref });
102
+ assert.equal((await client.inspect(window)).context.sessionId, "another-session");
103
+ chrome.context = { windowId: "window-1", sessionId: null, instanceId: null };
104
+ assert.equal((await client.inspect(window)).context.sessionId, null);
105
+ chrome.context = { ...chrome.context, windowId: "another-window" };
106
+ await assert.rejects(client.screenshot(window), /window or active session changed/);
107
+ }
108
+ finally {
109
+ client.close();
110
+ }
111
+ });
94
112
  it("matches out-of-order protocol responses and drains runtime diagnostics on inspect", async () => {
95
113
  const chrome = new FakeChrome();
96
114
  const client = chrome.client();
@@ -1 +1 @@
1
- {"version":3,"file":"developer-cdp.test.js","sourceRoot":"","sources":["../src/developer-cdp.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAQ9C,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,CAAC;IAC5B,EAAE;IACF,KAAK,EAAE,QAAQ,EAAE,EAAE;IACnB,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,mBAAmB,EAAE,EAAE;IAC5B,oBAAoB,EAAE,uBAAuB,EAAE,EAAE;CAClD,CAAC,CAAA;AAEF,MAAM,UAAU;IAOd,YAA6B,MAAkB;QAAlB,WAAM,GAAN,MAAM,CAAY;QAN/C,WAAM,GAAsC,IAAI,CAAA;QAChD,cAAS,GAAgD,IAAI,CAAA;QAC7D,YAAO,GAAsC,IAAI,CAAA;QACjD,YAAO,GAAsC,IAAI,CAAA;QACjD,WAAM,GAAG,KAAK,CAAA;QAGZ,cAAc,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACzC,CAAC;IAED,IAAI,CAAC,IAAY;QACf,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC,CAAA;IACxD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;IACpB,CAAC;IAED,OAAO,CAAC,OAAgB,EAAE,SAAkC,EAAE;QAC5D,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;IACxE,CAAC;IAED,IAAI,CAAC,MAAc,EAAE,SAAkC,EAAE;QACvD,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;IAChE,CAAC;CACF;AAED,MAAM,UAAU;IAAhB;QACE,WAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;QAEpB,YAAO,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,CAAA;QACrF,YAAO,GAAiB,EAAE,CAAA;QAC1B,aAAQ,GAAc,EAAE,CAAA;QACxB,aAAQ,GAAG,IAAI,GAAG,EAAoD,CAAA;QACtE,mBAAc,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACtD,YAAO,GAAmC;YACxC,EAAE,gBAAgB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;SAC7E,CAAA;QAED,UAAK,GAAG,KAAK,EAAE,KAA6B,EAAqB,EAAE;YACjE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,iCAAiC,CAAC,CAAA;YAC9D,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACpE,CAAC,CAAA;QAED,YAAO,GAAG,CAAC,IAAY,EAAc,EAAE;YACrC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAA;YACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACzB,OAAO,MAAM,CAAA;QACf,CAAC,CAAA;IA6BH,CAAC;IA3BC,OAAO,CAAC,MAAkB,EAAE,OAAgB;QAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;YACtD,OAAM;QACR,CAAC;QACD,cAAc,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAC5E,CAAC;IAED,MAAM,CAAC,MAAc;QACnB,IAAI,MAAM,KAAK,6BAA6B;YAAE,OAAO;gBACnD,KAAK,EAAE,IAAI,CAAC,OAAO;aACpB,CAAA;QACD,IAAI,MAAM,KAAK,kBAAkB;YAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAA;QAC7E,IAAI,MAAM,KAAK,wBAAwB;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,CAAA;QAC7E,IAAI,MAAM,KAAK,iBAAiB;YAAE,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAA;QAC3E,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,CAAC,YAAqC,EAAE;QAC5C,OAAO,IAAI,YAAY,CAAC;YACtB,KAAK,EAAE,IAAI,CAAC,KAAgC;YAC5C,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS,EAAE,KAAK;YAChB,GAAG,SAAS;SACb,CAAC,CAAA;IACJ,CAAC;CACF;AAED,MAAM,QAAQ,GAAG;IACf,QAAQ,EAAE,uBAAuB;IACjC,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,UAAU,EAAE,aAAa;CAC1B,CAAA;AAED,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,mFAAmF,EAAE,KAAK,IAAI,EAAE;QACjG,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAA;QACrC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;QACrG,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE;YACrC,gBAAgB,EAAE,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,EAAE;SAClE,CAAC,CAAA;QAEF,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,6BAA6B,EAAE,SAAkB,CAAC,CAAA;QACtE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,wBAAwB,EAAE,SAAkB,CAAC,CAAA;QACjE,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,6BAA6B,CAAC;YAAE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;QACvH,MAAM,iBAAiB,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;QACrD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;QAC3D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,wBAAwB,CAAC,EAAE,SAAS,CAAC,CAAA;QACtE,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,6BAA6B,CAAE,CAAA;QAC1E,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAA;QACnG,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAA;QAC1C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,wBAAwB,CAAC;YAAE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;QAClH,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,wBAAwB,CAAE,CAAA;QACxE,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QAC7G,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAA;QAC1C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAC9C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QAClD,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;QACpF,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAA;QAC1F,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAA;QAEvE,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;QACvB,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;QAClE,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;QAC/F,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,CAAA;QAClC,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAA;QAExC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;QAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAE7C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;QACrC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACtC,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAA;IAC1G,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9B,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,yBAAyB,EAAE,CAAA;QAEtF,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAEjD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QAChD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAA;QAC9D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAEjD,MAAM,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,EAAE,CAAC,CAAA;QAE/E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,0BAA0B,CAAC,EAAE,KAAK,CAAC,CAAA;QACrG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,wBAAwB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC1H,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC3B,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE;gBACvB,QAAQ,IAAI,CAAC,CAAA;gBACb,IAAI,QAAQ,GAAG,CAAC;oBAAE,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;gBAC5C,MAAM,MAAM,GAAG;oBACb,MAAM,EAAE,IAAI;oBACZ,SAAS,EAAE,IAAI;oBACf,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,IAAI;oBACb,IAAI,KAAI,CAAC;oBACT,KAAK,KAAI,CAAC;iBACc,CAAA;gBAC1B,cAAc,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC1C,OAAO,MAAM,CAAA;YACf,CAAC;SACF,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,2BAA2B,CAAC,CAAA;QAC3E,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;QAC/D,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;IAC3B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACjD,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAA;QAE7E,MAAM,MAAM,CAAC,OAAO,CAClB,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EACvF,yBAAyB,CAC1B,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACjD,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,KAAK,EAAE,CAAA;QAE9B,MAAM,MAAM,CAAC,OAAO,CAClB,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,EAAE,CAAC,EACzE,yBAAyB,CAC1B,CAAA;QACD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACjD,MAAM,CAAC,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,CAAA;QAE9D,MAAM,MAAM,CAAC,OAAO,CAClB,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,EAAE,CAAC,EACzE,wBAAwB,CACzB,CAAA;QACD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,0BAA0B,CAAC,EAAE,KAAK,CAAC,CAAA;IACvG,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACjD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,CAAA;QACvC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAA;QACrC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;QAEpB,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAA;QACxG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,CAAA;QACnF,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,2BAA2B,CAAC,CAAA;QACpF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACjD,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,EAAE,SAAkB,CAAC,CAAA;QAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,EAAE,CAAC,CAAA;QACxF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC;YAAE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;QAC3G,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAE,CAAA;QACxD,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAA;QACtE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAA;QAE3E,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAA;QAC1D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,0BAA0B,CAAC,EAAE,KAAK,CAAC,CAAA;IACvG,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAEjD,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,EAAE,SAAkB,CAAC,CAAA;QAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAI,EAAE,CAAC,CAAA;QACxF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC;YAAE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;QAC3G,MAAM,CAAC,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,CAAA;QACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAE,CAAA;QACxD,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAA;QAE3E,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAA;QAC1D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,0BAA0B,CAAC,EAAE,KAAK,CAAC,CAAA;IACvG,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC,CAAA;QACvD,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAE9B,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YAC1D,gBAAgB,EAAE,KAAK,GAAG,CAAC;YAC3B,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;YACzB,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,KAAK,EAAE,EAAE;SACnC,CAAC,CAAC,CAAA;QACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC1D,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC9B,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9B,MAAM,CAAC,KAAK,EAAE,CAAA;QACd,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import assert from \"node:assert/strict\"\nimport { describe, it } from \"node:test\"\nimport { DeveloperCdp } from \"./developer-cdp\"\n\ninterface Command {\n id: number\n method: string\n params?: Record<string, unknown>\n}\n\nconst page = (id: string) => ({\n id,\n title: `Page ${id}`,\n type: \"page\",\n url: `http://app.test/${id}`,\n webSocketDebuggerUrl: `ws://127.0.0.1:9222/${id}`,\n})\n\nclass FakeSocket {\n onopen: ((event: unknown) => void) | null = null\n onmessage: ((event: { data: unknown }) => void) | null = null\n onclose: ((event: unknown) => void) | null = null\n onerror: ((event: unknown) => void) | null = null\n closed = false\n\n constructor(private readonly chrome: FakeChrome) {\n queueMicrotask(() => this.onopen?.({}))\n }\n\n send(data: string): void {\n this.chrome.receive(this, JSON.parse(data) as Command)\n }\n\n close(): void {\n this.closed = true\n this.onclose?.({})\n }\n\n respond(command: Command, result: Record<string, unknown> = {}): void {\n this.onmessage?.({ data: JSON.stringify({ id: command.id, result }) })\n }\n\n emit(method: string, params: Record<string, unknown> = {}): void {\n this.onmessage?.({ data: JSON.stringify({ method, params }) })\n }\n}\n\nclass FakeChrome {\n target = page(\"one\")\n targets: Array<ReturnType<typeof page>> | undefined\n context = { windowId: \"window-1\", instanceId: \"workspace-1\", sessionId: \"session-1\" }\n sockets: FakeSocket[] = []\n commands: Command[] = []\n deferred = new Map<string, { socket: FakeSocket; command: Command }>()\n screenshotData = Buffer.from(\"png\").toString(\"base64\")\n axNodes: Array<Record<string, unknown>> = [\n { backendDOMNodeId: 42, role: { value: \"button\" }, name: { value: \"Save\" } },\n ]\n\n fetch = async (input: string | URL | Request): Promise<Response> => {\n assert.equal(String(input), \"http://127.0.0.1:9222/json/list\")\n return new Response(JSON.stringify(this.targets ?? [this.target]))\n }\n\n connect = (_url: string): FakeSocket => {\n const socket = new FakeSocket(this)\n this.sockets.push(socket)\n return socket\n }\n\n receive(socket: FakeSocket, command: Command): void {\n this.commands.push(command)\n if (this.deferred.has(command.method)) {\n this.deferred.set(command.method, { socket, command })\n return\n }\n queueMicrotask(() => socket.respond(command, this.result(command.method)))\n }\n\n result(method: string): Record<string, unknown> {\n if (method === \"Accessibility.getFullAXTree\") return {\n nodes: this.axNodes,\n }\n if (method === \"Runtime.evaluate\") return { result: { value: this.context } }\n if (method === \"Page.captureScreenshot\") return { data: this.screenshotData }\n if (method === \"DOM.resolveNode\") return { object: { objectId: \"node-1\" } }\n return {}\n }\n\n client(overrides: Record<string, unknown> = {}): DeveloperCdp {\n return new DeveloperCdp({\n fetch: this.fetch as typeof globalThis.fetch,\n connect: this.connect,\n timeoutMs: 1_000,\n ...overrides,\n })\n }\n}\n\nconst identity = {\n endpoint: \"http://127.0.0.1:9222\",\n runId: \"run-1\",\n windowId: \"window-1\",\n sessionId: \"session-1\",\n instanceId: \"workspace-1\",\n}\n\ndescribe(\"DeveloperCdp\", () => {\n it(\"matches out-of-order protocol responses and drains runtime diagnostics on inspect\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n await client.inspect(identity)\n const socket = chrome.sockets.at(-1)!\n for (let index = 0; index < 1_001; index++) {\n socket.emit(\"Runtime.consoleAPICalled\", { type: \"warning\", args: [{ value: `message-${index}` }] })\n }\n socket.emit(\"Runtime.exceptionThrown\", {\n exceptionDetails: { exception: { description: \"Error: broken\" } },\n })\n\n chrome.deferred.set(\"Accessibility.getFullAXTree\", undefined as never)\n chrome.deferred.set(\"Page.captureScreenshot\", undefined as never)\n const inspectionPromise = client.inspect(identity)\n while (!chrome.deferred.get(\"Accessibility.getFullAXTree\")) await new Promise<void>((resolve) => setImmediate(resolve))\n const screenshotPromise = client.screenshot(identity)\n await new Promise<void>((resolve) => setImmediate(resolve))\n assert.equal(chrome.deferred.get(\"Page.captureScreenshot\"), undefined)\n const inspectCommand = chrome.deferred.get(\"Accessibility.getFullAXTree\")!\n inspectCommand.socket.respond(inspectCommand.command, chrome.result(\"Accessibility.getFullAXTree\"))\n const inspection = await inspectionPromise\n while (!chrome.deferred.get(\"Page.captureScreenshot\")) await new Promise<void>((resolve) => setImmediate(resolve))\n const screenshotCommand = chrome.deferred.get(\"Page.captureScreenshot\")!\n screenshotCommand.socket.respond(screenshotCommand.command, { data: Buffer.from(\"shot\").toString(\"base64\") })\n const screenshot = await screenshotPromise\n assert.equal(inspection.nodes[0].name, \"Save\")\n assert.equal(inspection.diagnostics.length, 1_000)\n assert.deepEqual(inspection.diagnostics[0], { level: \"warning\", text: \"message-2\" })\n assert.deepEqual(inspection.diagnostics.at(-1), { level: \"error\", text: \"Error: broken\" })\n assert.equal(Buffer.from(screenshot.data, \"base64\").toString(), \"shot\")\n\n chrome.deferred.clear()\n assert.deepEqual((await client.inspect(identity)).diagnostics, [])\n socket.emit(\"Runtime.consoleAPICalled\", { type: \"log\", args: [{ value: \"x\".repeat(10_000) }] })\n assert.equal((await client.inspect(identity)).diagnostics[0].text.length, 512)\n })\n\n it(\"reconnects when the page target is replaced and rejects target-scoped refs\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const first = await client.inspect(identity)\n const oldRef = first.nodes[0].ref!\n const oldSocket = chrome.sockets.at(-1)!\n\n chrome.target = page(\"two\")\n const second = await client.inspect(identity)\n\n assert.equal(second.target.id, \"two\")\n assert.equal(oldSocket.closed, true)\n assert.equal(chrome.sockets.length, 4)\n await assert.rejects(client.act({ ...identity, kind: \"click\", ref: oldRef }), /stale accessibility ref/)\n })\n\n it(\"refreshes target metadata without reconnecting\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n await client.inspect(identity)\n chrome.target = { ...chrome.target, title: \"Renamed\", url: \"http://app.test/current\" }\n\n const inspection = await client.inspect(identity)\n\n assert.equal(inspection.target.title, \"Renamed\")\n assert.equal(inspection.target.url, \"http://app.test/current\")\n assert.equal(chrome.sockets.length, 2)\n })\n\n it(\"activates clicks through the resolved accessibility node\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n\n await client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! })\n\n assert.equal(chrome.commands.some((command) => command.method === \"Input.dispatchMouseEvent\"), false)\n assert.equal(chrome.commands.find((command) => command.method === \"Runtime.callFunctionOn\")?.params?.objectId, \"node-1\")\n })\n\n it(\"retries a failed WebSocket connection\", async () => {\n const chrome = new FakeChrome()\n let attempts = 0\n const client = chrome.client({\n connect: (url: string) => {\n attempts += 1\n if (attempts > 1) return chrome.connect(url)\n const socket = {\n onopen: null,\n onmessage: null,\n onclose: null,\n onerror: null,\n send() {},\n close() {},\n } as unknown as FakeSocket\n queueMicrotask(() => socket.onerror?.({}))\n return socket\n },\n })\n\n await assert.rejects(client.inspect(identity), /No CodeNomad page matches/)\n assert.equal((await client.inspect(identity)).target.id, \"one\")\n assert.equal(attempts, 3)\n })\n\n it(\"invalidates accessibility refs on frame navigation\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n chrome.sockets.at(-1)!.emit(\"Page.frameNavigated\", { frame: { id: \"main\" } })\n\n await assert.rejects(\n client.act({ ...identity, kind: \"type\", ref: inspection.nodes[0].ref!, text: \"hello\" }),\n /stale accessibility ref/,\n )\n })\n\n it(\"invalidates refs when the target socket reconnects\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n chrome.sockets.at(-1)!.close()\n\n await assert.rejects(\n client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! }),\n /stale accessibility ref/,\n )\n assert.equal(chrome.sockets.length, 3)\n })\n\n it(\"rejects actions after the visible OpenCode session changes\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n chrome.context = { ...chrome.context, sessionId: \"session-2\" }\n\n await assert.rejects(\n client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! }),\n /active session changed/,\n )\n assert.equal(chrome.commands.some((command) => command.method === \"Input.dispatchMouseEvent\"), false)\n })\n\n it(\"invalidates refs and pending commands when an open socket errors\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n const oldRef = inspection.nodes[0].ref!\n const socket = chrome.sockets.at(-1)!\n socket.onerror?.({})\n\n await assert.rejects(client.act({ ...identity, kind: \"click\", ref: oldRef }), /stale accessibility ref/)\n assert.equal(socket.closed, true)\n })\n\n it(\"rejects non-loopback WebSocket targets\", async () => {\n const chrome = new FakeChrome()\n chrome.target = { ...chrome.target, webSocketDebuggerUrl: \"ws://example.com/page\" }\n await assert.rejects(chrome.client().inspect(identity), /No CodeNomad page matches/)\n assert.equal(chrome.sockets.length, 0)\n })\n\n it(\"aborts actions when navigation occurs between CDP commands\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n chrome.deferred.set(\"DOM.resolveNode\", undefined as never)\n const action = client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! })\n while (!chrome.deferred.get(\"DOM.resolveNode\")) await new Promise<void>((resolve) => setImmediate(resolve))\n const deferred = chrome.deferred.get(\"DOM.resolveNode\")!\n deferred.socket.emit(\"Page.frameNavigated\", { frame: { id: \"main\" } })\n deferred.socket.respond(deferred.command, chrome.result(\"DOM.resolveNode\"))\n\n await assert.rejects(action, /Page changed during action/)\n assert.equal(chrome.commands.some((command) => command.method === \"Input.dispatchMouseEvent\"), false)\n })\n\n it(\"rejects captures and input when the visible instance changes mid-command\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n\n chrome.deferred.set(\"DOM.resolveNode\", undefined as never)\n const action = client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! })\n while (!chrome.deferred.get(\"DOM.resolveNode\")) await new Promise<void>((resolve) => setImmediate(resolve))\n chrome.context = { ...chrome.context, instanceId: \"workspace-2\" }\n const deferred = chrome.deferred.get(\"DOM.resolveNode\")!\n deferred.socket.respond(deferred.command, chrome.result(\"DOM.resolveNode\"))\n\n await assert.rejects(action, /Page changed during action/)\n assert.equal(chrome.commands.some((command) => command.method === \"Input.dispatchMouseEvent\"), false)\n })\n\n it(\"rejects screenshots over the configured PNG byte limit\", async () => {\n const chrome = new FakeChrome()\n chrome.screenshotData = Buffer.from(\"12345\").toString(\"base64\")\n const client = chrome.client({ maxScreenshotBytes: 4 })\n await client.inspect(identity)\n\n await assert.rejects(client.screenshot(identity), /exceeds 4 byte limit/)\n })\n\n it(\"bounds accessibility snapshots\", async () => {\n const chrome = new FakeChrome()\n chrome.axNodes = Array.from({ length: 800 }, (_, index) => ({\n backendDOMNodeId: index + 1,\n role: { value: \"button\" },\n name: { value: `Button ${index}` },\n }))\n const inspection = await chrome.client().inspect(identity)\n assert.equal(inspection.nodes.length, 750)\n })\n\n it(\"closes active target connections\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n await client.inspect(identity)\n client.close()\n assert.equal(chrome.sockets.at(-1)!.closed, true)\n })\n})\n"]}
1
+ {"version":3,"file":"developer-cdp.test.js","sourceRoot":"","sources":["../src/developer-cdp.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\"\nimport { describe, it } from \"node:test\"\nimport { DeveloperCdp } from \"./developer-cdp\"\n\ninterface Command {\n id: number\n method: string\n params?: Record<string, unknown>\n}\n\nconst page = (id: string) => ({\n id,\n title: `Page ${id}`,\n type: \"page\",\n url: `http://app.test/${id}`,\n webSocketDebuggerUrl: `ws://127.0.0.1:9222/${id}`,\n})\n\nclass FakeSocket {\n onopen: ((event: unknown) => void) | null = null\n onmessage: ((event: { data: unknown }) => void) | null = null\n onclose: ((event: unknown) => void) | null = null\n onerror: ((event: unknown) => void) | null = null\n closed = false\n\n constructor(private readonly chrome: FakeChrome) {\n queueMicrotask(() => this.onopen?.({}))\n }\n\n send(data: string): void {\n this.chrome.receive(this, JSON.parse(data) as Command)\n }\n\n close(): void {\n this.closed = true\n this.onclose?.({})\n }\n\n respond(command: Command, result: Record<string, unknown> = {}): void {\n this.onmessage?.({ data: JSON.stringify({ id: command.id, result }) })\n }\n\n emit(method: string, params: Record<string, unknown> = {}): void {\n this.onmessage?.({ data: JSON.stringify({ method, params }) })\n }\n}\n\nclass FakeChrome {\n target = page(\"one\")\n targets: Array<ReturnType<typeof page>> | undefined\n context = { windowId: \"window-1\", instanceId: \"workspace-1\", sessionId: \"session-1\" }\n sockets: FakeSocket[] = []\n commands: Command[] = []\n deferred = new Map<string, { socket: FakeSocket; command: Command }>()\n screenshotData = Buffer.from(\"png\").toString(\"base64\")\n axNodes: Array<Record<string, unknown>> = [\n { backendDOMNodeId: 42, role: { value: \"button\" }, name: { value: \"Save\" } },\n ]\n\n fetch = async (input: string | URL | Request): Promise<Response> => {\n assert.equal(String(input), \"http://127.0.0.1:9222/json/list\")\n return new Response(JSON.stringify(this.targets ?? [this.target]))\n }\n\n connect = (_url: string): FakeSocket => {\n const socket = new FakeSocket(this)\n this.sockets.push(socket)\n return socket\n }\n\n receive(socket: FakeSocket, command: Command): void {\n this.commands.push(command)\n if (this.deferred.has(command.method)) {\n this.deferred.set(command.method, { socket, command })\n return\n }\n queueMicrotask(() => socket.respond(command, this.result(command.method)))\n }\n\n result(method: string): Record<string, unknown> {\n if (method === \"Accessibility.getFullAXTree\") return {\n nodes: this.axNodes,\n }\n if (method === \"Runtime.evaluate\") return { result: { value: this.context } }\n if (method === \"Page.captureScreenshot\") return { data: this.screenshotData }\n if (method === \"DOM.resolveNode\") return { object: { objectId: \"node-1\" } }\n return {}\n }\n\n client(overrides: Record<string, unknown> = {}): DeveloperCdp {\n return new DeveloperCdp({\n fetch: this.fetch as typeof globalThis.fetch,\n connect: this.connect,\n timeoutMs: 1_000,\n ...overrides,\n })\n }\n}\n\nconst identity = {\n endpoint: \"http://127.0.0.1:9222\",\n runId: \"run-1\",\n windowId: \"window-1\",\n sessionId: \"session-1\",\n instanceId: \"workspace-1\",\n}\n\ndescribe(\"DeveloperCdp\", () => {\n it(\"keeps window-scoped tools usable across session/project navigation and empty views\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const window = { endpoint: identity.endpoint, runId: identity.runId, windowId: identity.windowId }\n try {\n const first = await client.inspect(window)\n chrome.context = { ...chrome.context, sessionId: \"another-session\", instanceId: \"another-project\" }\n await client.act({ ...window, kind: \"click\", ref: first.nodes[0].ref! })\n assert.equal((await client.inspect(window)).context.sessionId, \"another-session\")\n chrome.context = { windowId: \"window-1\", sessionId: null, instanceId: null } as never\n assert.equal((await client.inspect(window)).context.sessionId, null)\n chrome.context = { ...chrome.context, windowId: \"another-window\" }\n await assert.rejects(client.screenshot(window), /window or active session changed/)\n } finally { client.close() }\n })\n\n it(\"matches out-of-order protocol responses and drains runtime diagnostics on inspect\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n await client.inspect(identity)\n const socket = chrome.sockets.at(-1)!\n for (let index = 0; index < 1_001; index++) {\n socket.emit(\"Runtime.consoleAPICalled\", { type: \"warning\", args: [{ value: `message-${index}` }] })\n }\n socket.emit(\"Runtime.exceptionThrown\", {\n exceptionDetails: { exception: { description: \"Error: broken\" } },\n })\n\n chrome.deferred.set(\"Accessibility.getFullAXTree\", undefined as never)\n chrome.deferred.set(\"Page.captureScreenshot\", undefined as never)\n const inspectionPromise = client.inspect(identity)\n while (!chrome.deferred.get(\"Accessibility.getFullAXTree\")) await new Promise<void>((resolve) => setImmediate(resolve))\n const screenshotPromise = client.screenshot(identity)\n await new Promise<void>((resolve) => setImmediate(resolve))\n assert.equal(chrome.deferred.get(\"Page.captureScreenshot\"), undefined)\n const inspectCommand = chrome.deferred.get(\"Accessibility.getFullAXTree\")!\n inspectCommand.socket.respond(inspectCommand.command, chrome.result(\"Accessibility.getFullAXTree\"))\n const inspection = await inspectionPromise\n while (!chrome.deferred.get(\"Page.captureScreenshot\")) await new Promise<void>((resolve) => setImmediate(resolve))\n const screenshotCommand = chrome.deferred.get(\"Page.captureScreenshot\")!\n screenshotCommand.socket.respond(screenshotCommand.command, { data: Buffer.from(\"shot\").toString(\"base64\") })\n const screenshot = await screenshotPromise\n assert.equal(inspection.nodes[0].name, \"Save\")\n assert.equal(inspection.diagnostics.length, 1_000)\n assert.deepEqual(inspection.diagnostics[0], { level: \"warning\", text: \"message-2\" })\n assert.deepEqual(inspection.diagnostics.at(-1), { level: \"error\", text: \"Error: broken\" })\n assert.equal(Buffer.from(screenshot.data, \"base64\").toString(), \"shot\")\n\n chrome.deferred.clear()\n assert.deepEqual((await client.inspect(identity)).diagnostics, [])\n socket.emit(\"Runtime.consoleAPICalled\", { type: \"log\", args: [{ value: \"x\".repeat(10_000) }] })\n assert.equal((await client.inspect(identity)).diagnostics[0].text.length, 512)\n })\n\n it(\"reconnects when the page target is replaced and rejects target-scoped refs\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const first = await client.inspect(identity)\n const oldRef = first.nodes[0].ref!\n const oldSocket = chrome.sockets.at(-1)!\n\n chrome.target = page(\"two\")\n const second = await client.inspect(identity)\n\n assert.equal(second.target.id, \"two\")\n assert.equal(oldSocket.closed, true)\n assert.equal(chrome.sockets.length, 4)\n await assert.rejects(client.act({ ...identity, kind: \"click\", ref: oldRef }), /stale accessibility ref/)\n })\n\n it(\"refreshes target metadata without reconnecting\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n await client.inspect(identity)\n chrome.target = { ...chrome.target, title: \"Renamed\", url: \"http://app.test/current\" }\n\n const inspection = await client.inspect(identity)\n\n assert.equal(inspection.target.title, \"Renamed\")\n assert.equal(inspection.target.url, \"http://app.test/current\")\n assert.equal(chrome.sockets.length, 2)\n })\n\n it(\"activates clicks through the resolved accessibility node\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n\n await client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! })\n\n assert.equal(chrome.commands.some((command) => command.method === \"Input.dispatchMouseEvent\"), false)\n assert.equal(chrome.commands.find((command) => command.method === \"Runtime.callFunctionOn\")?.params?.objectId, \"node-1\")\n })\n\n it(\"retries a failed WebSocket connection\", async () => {\n const chrome = new FakeChrome()\n let attempts = 0\n const client = chrome.client({\n connect: (url: string) => {\n attempts += 1\n if (attempts > 1) return chrome.connect(url)\n const socket = {\n onopen: null,\n onmessage: null,\n onclose: null,\n onerror: null,\n send() {},\n close() {},\n } as unknown as FakeSocket\n queueMicrotask(() => socket.onerror?.({}))\n return socket\n },\n })\n\n await assert.rejects(client.inspect(identity), /No CodeNomad page matches/)\n assert.equal((await client.inspect(identity)).target.id, \"one\")\n assert.equal(attempts, 3)\n })\n\n it(\"invalidates accessibility refs on frame navigation\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n chrome.sockets.at(-1)!.emit(\"Page.frameNavigated\", { frame: { id: \"main\" } })\n\n await assert.rejects(\n client.act({ ...identity, kind: \"type\", ref: inspection.nodes[0].ref!, text: \"hello\" }),\n /stale accessibility ref/,\n )\n })\n\n it(\"invalidates refs when the target socket reconnects\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n chrome.sockets.at(-1)!.close()\n\n await assert.rejects(\n client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! }),\n /stale accessibility ref/,\n )\n assert.equal(chrome.sockets.length, 3)\n })\n\n it(\"rejects actions after the visible OpenCode session changes\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n chrome.context = { ...chrome.context, sessionId: \"session-2\" }\n\n await assert.rejects(\n client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! }),\n /active session changed/,\n )\n assert.equal(chrome.commands.some((command) => command.method === \"Input.dispatchMouseEvent\"), false)\n })\n\n it(\"invalidates refs and pending commands when an open socket errors\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n const oldRef = inspection.nodes[0].ref!\n const socket = chrome.sockets.at(-1)!\n socket.onerror?.({})\n\n await assert.rejects(client.act({ ...identity, kind: \"click\", ref: oldRef }), /stale accessibility ref/)\n assert.equal(socket.closed, true)\n })\n\n it(\"rejects non-loopback WebSocket targets\", async () => {\n const chrome = new FakeChrome()\n chrome.target = { ...chrome.target, webSocketDebuggerUrl: \"ws://example.com/page\" }\n await assert.rejects(chrome.client().inspect(identity), /No CodeNomad page matches/)\n assert.equal(chrome.sockets.length, 0)\n })\n\n it(\"aborts actions when navigation occurs between CDP commands\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n chrome.deferred.set(\"DOM.resolveNode\", undefined as never)\n const action = client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! })\n while (!chrome.deferred.get(\"DOM.resolveNode\")) await new Promise<void>((resolve) => setImmediate(resolve))\n const deferred = chrome.deferred.get(\"DOM.resolveNode\")!\n deferred.socket.emit(\"Page.frameNavigated\", { frame: { id: \"main\" } })\n deferred.socket.respond(deferred.command, chrome.result(\"DOM.resolveNode\"))\n\n await assert.rejects(action, /Page changed during action/)\n assert.equal(chrome.commands.some((command) => command.method === \"Input.dispatchMouseEvent\"), false)\n })\n\n it(\"rejects captures and input when the visible instance changes mid-command\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n const inspection = await client.inspect(identity)\n\n chrome.deferred.set(\"DOM.resolveNode\", undefined as never)\n const action = client.act({ ...identity, kind: \"click\", ref: inspection.nodes[0].ref! })\n while (!chrome.deferred.get(\"DOM.resolveNode\")) await new Promise<void>((resolve) => setImmediate(resolve))\n chrome.context = { ...chrome.context, instanceId: \"workspace-2\" }\n const deferred = chrome.deferred.get(\"DOM.resolveNode\")!\n deferred.socket.respond(deferred.command, chrome.result(\"DOM.resolveNode\"))\n\n await assert.rejects(action, /Page changed during action/)\n assert.equal(chrome.commands.some((command) => command.method === \"Input.dispatchMouseEvent\"), false)\n })\n\n it(\"rejects screenshots over the configured PNG byte limit\", async () => {\n const chrome = new FakeChrome()\n chrome.screenshotData = Buffer.from(\"12345\").toString(\"base64\")\n const client = chrome.client({ maxScreenshotBytes: 4 })\n await client.inspect(identity)\n\n await assert.rejects(client.screenshot(identity), /exceeds 4 byte limit/)\n })\n\n it(\"bounds accessibility snapshots\", async () => {\n const chrome = new FakeChrome()\n chrome.axNodes = Array.from({ length: 800 }, (_, index) => ({\n backendDOMNodeId: index + 1,\n role: { value: \"button\" },\n name: { value: `Button ${index}` },\n }))\n const inspection = await chrome.client().inspect(identity)\n assert.equal(inspection.nodes.length, 750)\n })\n\n it(\"closes active target connections\", async () => {\n const chrome = new FakeChrome()\n const client = chrome.client()\n await client.inspect(identity)\n client.close()\n assert.equal(chrome.sockets.at(-1)!.closed, true)\n })\n})\n"]}
@@ -1,5 +1,6 @@
1
1
  import { timingSafeEqual } from "node:crypto";
2
2
  import { AUTOMATION_BRIDGE_PATH, parseBrowserAction, parseDeveloperAction } from "../../opencode/automation-plugin";
3
+ import { DeveloperInspectionTargets } from "../../automation/developer-inspection-targets";
3
4
  export function isAutomationPluginRequest(request, deps) {
4
5
  if (request.method !== "POST" || request.url.split("?")[0] !== AUTOMATION_BRIDGE_PATH)
5
6
  return false;
@@ -13,6 +14,7 @@ export function isAutomationPluginRequest(request, deps) {
13
14
  return actual.length === expected.length && timingSafeEqual(actual, expected);
14
15
  }
15
16
  export function registerAutomationPluginRoute(app, deps) {
17
+ const inspectedTargets = new DeveloperInspectionTargets();
16
18
  app.post(AUTOMATION_BRIDGE_PATH, { bodyLimit: 32 * 1024 }, async (request, reply) => {
17
19
  if (!isAutomationPluginRequest(request, deps))
18
20
  return reply.code(401).send({ error: "Unauthorized automation bridge" });
@@ -77,37 +79,48 @@ export function registerAutomationPluginRoute(app, deps) {
77
79
  endpoint: status.cdpUrl,
78
80
  runId: status.runId,
79
81
  windowId: status.windowId,
80
- sessionId: body.sessionID,
81
82
  };
82
- let context;
83
+ let command;
84
+ if (body.mode !== "developer-probe") {
85
+ try {
86
+ command = parseDeveloperAction(body.command);
87
+ }
88
+ catch (error) {
89
+ return reply.code(400).send({ error: error instanceof Error ? error.message : String(error) });
90
+ }
91
+ }
92
+ let identity;
83
93
  try {
84
- context = await deps.developerCdp.context(selection);
94
+ if (body.mode === "developer-probe" || command?.action === "inspect") {
95
+ await deps.developerCdp.context(selection);
96
+ }
97
+ else {
98
+ identity = inspectedTargets.get(body.sessionID, selection);
99
+ await deps.developerCdp.context(identity);
100
+ }
85
101
  }
86
102
  catch (error) {
103
+ if (body.mode !== "developer-probe")
104
+ inspectedTargets.forget(body.sessionID);
87
105
  return reply.code(404).send({ error: error instanceof Error ? error.message : String(error) });
88
106
  }
89
- if (!await deps.workspaceManager.ownsLocation(context.instanceId, location)) {
90
- return reply.code(404).send({ error: "The visible CodeNomad workspace does not own this OpenCode session" });
91
- }
92
- const identity = { ...selection, instanceId: context.instanceId };
107
+ identity ??= selection;
93
108
  if (body.mode === "developer-probe") {
94
109
  return reply.send({ result: { available: true, nativeIdentity: status.nativeIdentity, runId: status.runId } });
95
110
  }
96
- let command;
97
- try {
98
- command = parseDeveloperAction(body.command);
99
- }
100
- catch (error) {
101
- return reply.code(400).send({ error: error instanceof Error ? error.message : String(error) });
102
- }
111
+ if (!command)
112
+ return reply.code(400).send({ error: "Missing developer command" });
103
113
  try {
104
114
  if (command.action === "restart") {
115
+ inspectedTargets.forget(body.sessionID);
105
116
  const result = await deps.nativeParent.request("developer.restart", {});
106
117
  deps.developerCdp.close(status.runId);
107
118
  return reply.send({ result });
108
119
  }
109
120
  if (command.action === "inspect") {
110
- return reply.send({ result: await deps.developerCdp.inspect(identity) });
121
+ const result = await deps.developerCdp.inspect(identity);
122
+ inspectedTargets.remember(body.sessionID, identity);
123
+ return reply.send({ result });
111
124
  }
112
125
  if (command.action === "screenshot") {
113
126
  const image = await deps.developerCdp.screenshot(identity);
@@ -1 +1 @@
1
- {"version":3,"file":"automation-plugin.js","sourceRoot":"","sources":["../../../src/server/routes/automation-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { timingSafeEqual } from \"node:crypto\"\nimport type { FastifyInstance, FastifyRequest } from \"fastify\"\nimport type { AuthManager } from \"../../auth/manager\"\nimport type { DeveloperCdp } from \"../../developer-cdp\"\nimport type { DeveloperCdpIdentity, DeveloperCdpSelection } from \"../../developer-cdp\"\nimport type { NativeParent } from \"../../native-parent\"\nimport { AUTOMATION_BRIDGE_PATH, parseBrowserAction, parseDeveloperAction } from \"../../opencode/automation-plugin\"\nimport type { WorkspaceManager } from \"../../workspaces/manager\"\n\ninterface AutomationPluginRouteDeps {\n authManager: AuthManager\n bridgeToken: string\n nativeParent: NativeParent\n workspaceManager: WorkspaceManager\n developerCdp: DeveloperCdp\n}\n\ninterface DeveloperNativeStatus {\n status: {\n state: string\n runId?: string\n nativeIdentity?: string\n cdpUrl?: string\n windowId?: string\n }\n logs?: unknown[]\n}\n\nexport function isAutomationPluginRequest(\n request: FastifyRequest,\n deps: Pick<AutomationPluginRouteDeps, \"authManager\" | \"bridgeToken\">,\n): boolean {\n if (request.method !== \"POST\" || request.url.split(\"?\")[0] !== AUTOMATION_BRIDGE_PATH) return false\n if (!deps.authManager.isLoopbackRequest(request)) return false\n const supplied = request.headers[\"x-codenomad-automation-token\"]\n if (typeof supplied !== \"string\") return false\n const actual = Buffer.from(supplied)\n const expected = Buffer.from(deps.bridgeToken)\n return actual.length === expected.length && timingSafeEqual(actual, expected)\n}\n\nexport function registerAutomationPluginRoute(app: FastifyInstance, deps: AutomationPluginRouteDeps): void {\n app.post(AUTOMATION_BRIDGE_PATH, { bodyLimit: 32 * 1024 }, async (request, reply) => {\n if (!isAutomationPluginRequest(request, deps)) return reply.code(401).send({ error: \"Unauthorized automation bridge\" })\n const body = request.body as { mode?: unknown; sessionID?: unknown; command?: unknown } | undefined\n if (!body || ![\"developer-probe\", \"developer-execute\", \"browser-claim\", \"browser-probe\", \"browser-execute\"].includes(String(body.mode))\n || typeof body.sessionID !== \"string\" || body.sessionID.length > 256) {\n return reply.code(400).send({ error: \"Invalid automation bridge request\" })\n }\n\n let location\n try {\n location = (await (await deps.workspaceManager.getSharedServiceClient()).session.get({ sessionID: body.sessionID })).location\n } catch {\n return reply.code(404).send({ error: \"Session not found\" })\n }\n const owned = (await Promise.all(deps.workspaceManager.list().map((workspace) =>\n deps.workspaceManager.ownsLocation(workspace.id, location).catch(() => false),\n ))).some(Boolean)\n if (!owned) return reply.code(404).send({ error: \"Session is not owned by this CodeNomad instance\" })\n\n if (body.mode === \"browser-claim\") return reply.send({ result: { available: true } })\n if (body.mode === \"browser-probe\") {\n try {\n const result = await deps.nativeParent.request<{ available: boolean }>(\"browser.probe\", { sessionID: body.sessionID })\n return result.available ? reply.send({ result }) : reply.code(404).send({ error: \"No visible browser target\" })\n } catch (error) {\n return reply.code(404).send({ error: error instanceof Error ? error.message : String(error) })\n }\n }\n if (body.mode === \"browser-execute\") {\n let command\n try {\n command = parseBrowserAction(body.command)\n } catch (error) {\n return reply.code(400).send({ error: error instanceof Error ? error.message : String(error) })\n }\n try {\n const result = await deps.nativeParent.request(\"browser.execute\", { sessionID: body.sessionID, command })\n return reply.send({ result })\n } catch (error) {\n return reply.code(409).send({ error: error instanceof Error ? error.message : String(error) })\n }\n }\n\n let native: DeveloperNativeStatus\n try {\n native = await deps.nativeParent.request<DeveloperNativeStatus>(\"developer.status\", {})\n } catch (error) {\n return reply.code(404).send({ error: error instanceof Error ? error.message : String(error) })\n }\n const status = native.status\n const available = status?.state === \"ready\" && typeof status.runId === \"string\"\n && typeof status.nativeIdentity === \"string\" && typeof status.cdpUrl === \"string\" && typeof status.windowId === \"string\"\n if (!available) {\n if (typeof status?.runId === \"string\") deps.developerCdp.close(status.runId)\n return reply.code(404).send({ error: \"Native automation has no active CodeNomad session\" })\n }\n\n const selection: DeveloperCdpSelection = {\n endpoint: status.cdpUrl!,\n runId: status.runId!,\n windowId: status.windowId!,\n sessionId: body.sessionID,\n }\n let context\n try {\n context = await deps.developerCdp.context(selection)\n } catch (error) {\n return reply.code(404).send({ error: error instanceof Error ? error.message : String(error) })\n }\n if (!await deps.workspaceManager.ownsLocation(context.instanceId, location)) {\n return reply.code(404).send({ error: \"The visible CodeNomad workspace does not own this OpenCode session\" })\n }\n const identity: DeveloperCdpIdentity = { ...selection, instanceId: context.instanceId }\n if (body.mode === \"developer-probe\") {\n return reply.send({ result: { available: true, nativeIdentity: status.nativeIdentity, runId: status.runId } })\n }\n\n let command\n try {\n command = parseDeveloperAction(body.command)\n } catch (error) {\n return reply.code(400).send({ error: error instanceof Error ? error.message : String(error) })\n }\n try {\n if (command.action === \"restart\") {\n const result = await deps.nativeParent.request<DeveloperNativeStatus[\"status\"]>(\"developer.restart\", {})\n deps.developerCdp.close(status.runId)\n return reply.send({ result })\n }\n if (command.action === \"inspect\") {\n return reply.send({ result: await deps.developerCdp.inspect(identity) })\n }\n if (command.action === \"screenshot\") {\n const image = await deps.developerCdp.screenshot(identity)\n return reply.send({ result: { image: { data: image.data, mime: image.mediaType } } })\n }\n await deps.developerCdp.act(command.action === \"type\"\n ? { ...identity, kind: \"type\", ref: command.ref, text: command.text }\n : { ...identity, kind: \"click\", ref: command.ref })\n return reply.send({ result: { ok: true } })\n } catch (error) {\n return reply.code(409).send({ error: error instanceof Error ? error.message : String(error) })\n }\n })\n}\n"]}
1
+ {"version":3,"file":"automation-plugin.js","sourceRoot":"","sources":["../../../src/server/routes/automation-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { timingSafeEqual } from \"node:crypto\"\nimport type { FastifyInstance, FastifyRequest } from \"fastify\"\nimport type { AuthManager } from \"../../auth/manager\"\nimport type { DeveloperCdp } from \"../../developer-cdp\"\nimport type { DeveloperCdpIdentity, DeveloperCdpSelection } from \"../../developer-cdp\"\nimport type { NativeParent } from \"../../native-parent\"\nimport { AUTOMATION_BRIDGE_PATH, parseBrowserAction, parseDeveloperAction } from \"../../opencode/automation-plugin\"\nimport type { WorkspaceManager } from \"../../workspaces/manager\"\nimport { DeveloperInspectionTargets } from \"../../automation/developer-inspection-targets\"\n\ninterface AutomationPluginRouteDeps {\n authManager: AuthManager\n bridgeToken: string\n nativeParent: NativeParent\n workspaceManager: WorkspaceManager\n developerCdp: DeveloperCdp\n}\n\ninterface DeveloperNativeStatus {\n status: {\n state: string\n runId?: string\n nativeIdentity?: string\n cdpUrl?: string\n windowId?: string\n }\n logs?: unknown[]\n}\n\nexport function isAutomationPluginRequest(\n request: FastifyRequest,\n deps: Pick<AutomationPluginRouteDeps, \"authManager\" | \"bridgeToken\">,\n): boolean {\n if (request.method !== \"POST\" || request.url.split(\"?\")[0] !== AUTOMATION_BRIDGE_PATH) return false\n if (!deps.authManager.isLoopbackRequest(request)) return false\n const supplied = request.headers[\"x-codenomad-automation-token\"]\n if (typeof supplied !== \"string\") return false\n const actual = Buffer.from(supplied)\n const expected = Buffer.from(deps.bridgeToken)\n return actual.length === expected.length && timingSafeEqual(actual, expected)\n}\n\nexport function registerAutomationPluginRoute(app: FastifyInstance, deps: AutomationPluginRouteDeps): void {\n const inspectedTargets = new DeveloperInspectionTargets()\n app.post(AUTOMATION_BRIDGE_PATH, { bodyLimit: 32 * 1024 }, async (request, reply) => {\n if (!isAutomationPluginRequest(request, deps)) return reply.code(401).send({ error: \"Unauthorized automation bridge\" })\n const body = request.body as { mode?: unknown; sessionID?: unknown; command?: unknown } | undefined\n if (!body || ![\"developer-probe\", \"developer-execute\", \"browser-claim\", \"browser-probe\", \"browser-execute\"].includes(String(body.mode))\n || typeof body.sessionID !== \"string\" || body.sessionID.length > 256) {\n return reply.code(400).send({ error: \"Invalid automation bridge request\" })\n }\n\n let location\n try {\n location = (await (await deps.workspaceManager.getSharedServiceClient()).session.get({ sessionID: body.sessionID })).location\n } catch {\n return reply.code(404).send({ error: \"Session not found\" })\n }\n const owned = (await Promise.all(deps.workspaceManager.list().map((workspace) =>\n deps.workspaceManager.ownsLocation(workspace.id, location).catch(() => false),\n ))).some(Boolean)\n if (!owned) return reply.code(404).send({ error: \"Session is not owned by this CodeNomad instance\" })\n\n if (body.mode === \"browser-claim\") return reply.send({ result: { available: true } })\n if (body.mode === \"browser-probe\") {\n try {\n const result = await deps.nativeParent.request<{ available: boolean }>(\"browser.probe\", { sessionID: body.sessionID })\n return result.available ? reply.send({ result }) : reply.code(404).send({ error: \"No visible browser target\" })\n } catch (error) {\n return reply.code(404).send({ error: error instanceof Error ? error.message : String(error) })\n }\n }\n if (body.mode === \"browser-execute\") {\n let command\n try {\n command = parseBrowserAction(body.command)\n } catch (error) {\n return reply.code(400).send({ error: error instanceof Error ? error.message : String(error) })\n }\n try {\n const result = await deps.nativeParent.request(\"browser.execute\", { sessionID: body.sessionID, command })\n return reply.send({ result })\n } catch (error) {\n return reply.code(409).send({ error: error instanceof Error ? error.message : String(error) })\n }\n }\n\n let native: DeveloperNativeStatus\n try {\n native = await deps.nativeParent.request<DeveloperNativeStatus>(\"developer.status\", {})\n } catch (error) {\n return reply.code(404).send({ error: error instanceof Error ? error.message : String(error) })\n }\n const status = native.status\n const available = status?.state === \"ready\" && typeof status.runId === \"string\"\n && typeof status.nativeIdentity === \"string\" && typeof status.cdpUrl === \"string\" && typeof status.windowId === \"string\"\n if (!available) {\n if (typeof status?.runId === \"string\") deps.developerCdp.close(status.runId)\n return reply.code(404).send({ error: \"Native automation has no active CodeNomad session\" })\n }\n\n const selection: DeveloperCdpSelection = {\n endpoint: status.cdpUrl!,\n runId: status.runId!,\n windowId: status.windowId!,\n }\n let command\n if (body.mode !== \"developer-probe\") {\n try {\n command = parseDeveloperAction(body.command)\n } catch (error) {\n return reply.code(400).send({ error: error instanceof Error ? error.message : String(error) })\n }\n }\n let identity: DeveloperCdpIdentity | undefined\n try {\n if (body.mode === \"developer-probe\" || command?.action === \"inspect\") {\n await deps.developerCdp.context(selection)\n } else {\n identity = inspectedTargets.get(body.sessionID, selection)\n await deps.developerCdp.context(identity)\n }\n } catch (error) {\n if (body.mode !== \"developer-probe\") inspectedTargets.forget(body.sessionID)\n return reply.code(404).send({ error: error instanceof Error ? error.message : String(error) })\n }\n identity ??= selection\n if (body.mode === \"developer-probe\") {\n return reply.send({ result: { available: true, nativeIdentity: status.nativeIdentity, runId: status.runId } })\n }\n\n if (!command) return reply.code(400).send({ error: \"Missing developer command\" })\n try {\n if (command.action === \"restart\") {\n inspectedTargets.forget(body.sessionID)\n const result = await deps.nativeParent.request<DeveloperNativeStatus[\"status\"]>(\"developer.restart\", {})\n deps.developerCdp.close(status.runId)\n return reply.send({ result })\n }\n if (command.action === \"inspect\") {\n const result = await deps.developerCdp.inspect(identity)\n inspectedTargets.remember(body.sessionID, identity)\n return reply.send({ result })\n }\n if (command.action === \"screenshot\") {\n const image = await deps.developerCdp.screenshot(identity)\n return reply.send({ result: { image: { data: image.data, mime: image.mediaType } } })\n }\n await deps.developerCdp.act(command.action === \"type\"\n ? { ...identity, kind: \"type\", ref: command.ref, text: command.text }\n : { ...identity, kind: \"click\", ref: command.ref })\n return reply.send({ result: { ok: true } })\n } catch (error) {\n return reply.code(409).send({ error: error instanceof Error ? error.message : String(error) })\n }\n })\n}\n"]}