teamshare-bridge 0.26.6 → 0.26.7

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 (37) hide show
  1. package/dist/bridge/daemon-support.d.ts +9 -0
  2. package/dist/bridge/daemon-support.js +12 -0
  3. package/dist/bridge/daemon-support.js.map +1 -1
  4. package/dist/bridge/daemon.js +37 -0
  5. package/dist/bridge/daemon.js.map +1 -1
  6. package/dist/bridge/local-server.d.ts +12 -0
  7. package/dist/bridge/local-server.js +36 -0
  8. package/dist/bridge/local-server.js.map +1 -1
  9. package/dist/lib/browser/batch.d.ts +67 -2
  10. package/dist/lib/browser/batch.js +109 -4
  11. package/dist/lib/browser/batch.js.map +1 -1
  12. package/dist/lib/browser/download.d.ts +19 -0
  13. package/dist/lib/browser/download.js +251 -0
  14. package/dist/lib/browser/download.js.map +1 -0
  15. package/dist/lib/browser/render-image.d.ts +30 -0
  16. package/dist/lib/browser/render-image.js +285 -0
  17. package/dist/lib/browser/render-image.js.map +1 -0
  18. package/dist/lib/browser/session.d.ts +79 -1
  19. package/dist/lib/browser/session.js +174 -3
  20. package/dist/lib/browser/session.js.map +1 -1
  21. package/dist/lib/browser/stage-file.d.ts +17 -0
  22. package/dist/lib/browser/stage-file.js +23 -0
  23. package/dist/lib/browser/stage-file.js.map +1 -1
  24. package/dist/lib/browser/xlsx-template.d.ts +59 -0
  25. package/dist/lib/browser/xlsx-template.js +380 -0
  26. package/dist/lib/browser/xlsx-template.js.map +1 -0
  27. package/dist/lib/harness/opencode-control.d.ts +14 -0
  28. package/dist/lib/harness/opencode-control.js +63 -0
  29. package/dist/lib/harness/opencode-control.js.map +1 -0
  30. package/dist/lib/harness/session-store.d.ts +33 -0
  31. package/dist/lib/harness/session-store.js +38 -0
  32. package/dist/lib/harness/session-store.js.map +1 -1
  33. package/dist/lib/harness/spawn.js +56 -18
  34. package/dist/lib/harness/spawn.js.map +1 -1
  35. package/dist/lib/orchestrator/handlers/browser.js +181 -1
  36. package/dist/lib/orchestrator/handlers/browser.js.map +1 -1
  37. package/package.json +1 -1
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.QA_DOWNLOAD_MAX_BYTES = exports.QA_DOWNLOAD_TIMEOUT_MS = void 0;
37
+ exports.downloadTemplateFile = downloadTemplateFile;
38
+ /**
39
+ * Download a template file into the run's staging directory (2026-10, QA).
40
+ *
41
+ * WHY THIS EXISTS: a QA flow that must fill and re-upload a spreadsheet
42
+ * template cannot work from a URL alone — the agent has to READ the template
43
+ * (headers, validation), FILL it, and ATTACH the result. The bytes have to
44
+ * land inside the run's staging directory, because that is the only place
45
+ * `attachFile` may read from.
46
+ *
47
+ * Two trigger styles, because sites offer the template two ways:
48
+ * - `url`: a direct link. A throwaway tab (same profile, so the login holds)
49
+ * navigates to it while the driven page stays exactly where it is.
50
+ * - no `url`: the agent already triggered the download on the driven page
51
+ * (clicked the "Download template" button in a previous action). The call
52
+ * then only waits for a new file to settle in the staging directory.
53
+ *
54
+ * Completion is polled, not assumed: a file counts only when it exists, is
55
+ * not a partial-download stub (`.crdownload`/`.part`/`.tmp`), and its size
56
+ * is stable across two polls.
57
+ */
58
+ const node_fs_1 = require("node:fs");
59
+ const node_path_1 = require("node:path");
60
+ const stage_file_1 = require("./stage-file");
61
+ exports.QA_DOWNLOAD_TIMEOUT_MS = 45_000;
62
+ exports.QA_DOWNLOAD_MAX_BYTES = 25 * 1024 * 1024;
63
+ const PARTIAL_SUFFIXES = ['.crdownload', '.part', '.tmp', '.download'];
64
+ function isPartial(name) {
65
+ const lower = name.toLowerCase();
66
+ return PARTIAL_SUFFIXES.some((s) => lower.endsWith(s));
67
+ }
68
+ function snapshot(dir) {
69
+ const out = new Map();
70
+ let entries = [];
71
+ try {
72
+ entries = (0, node_fs_1.readdirSync)(dir);
73
+ }
74
+ catch {
75
+ return out;
76
+ }
77
+ for (const name of entries) {
78
+ if (isPartial(name))
79
+ continue;
80
+ try {
81
+ out.set(name, (0, node_fs_1.statSync)((0, node_path_1.join)(dir, name)).mtimeMs);
82
+ }
83
+ catch {
84
+ /* raced a delete — ignore */
85
+ }
86
+ }
87
+ return out;
88
+ }
89
+ function sizeOf(path) {
90
+ try {
91
+ return (0, node_fs_1.statSync)(path).size;
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ }
97
+ /** Wait for a file created at/after `sinceMs` to finish writing. */
98
+ async function waitForNewFile(dir, sinceMs, timeoutMs) {
99
+ const start = Date.now();
100
+ let candidate = null;
101
+ let lastSize = -1;
102
+ for (;;) {
103
+ let entries = [];
104
+ try {
105
+ entries = (0, node_fs_1.readdirSync)(dir);
106
+ }
107
+ catch {
108
+ entries = [];
109
+ }
110
+ let newest = null;
111
+ let newestMtime = sinceMs;
112
+ for (const name of entries) {
113
+ if (isPartial(name))
114
+ continue;
115
+ try {
116
+ const st = (0, node_fs_1.statSync)((0, node_path_1.join)(dir, name));
117
+ if (st.mtimeMs >= sinceMs - 1000 && st.mtimeMs >= newestMtime) {
118
+ newestMtime = st.mtimeMs;
119
+ newest = name;
120
+ }
121
+ }
122
+ catch {
123
+ /* raced — ignore */
124
+ }
125
+ }
126
+ if (newest) {
127
+ const size = sizeOf((0, node_path_1.join)(dir, newest));
128
+ if (size !== null &&
129
+ size > 0 &&
130
+ size === lastSize &&
131
+ newest === candidate) {
132
+ if (size > exports.QA_DOWNLOAD_MAX_BYTES)
133
+ return null;
134
+ return { name: newest, bytes: size };
135
+ }
136
+ candidate = newest;
137
+ lastSize = size ?? -1;
138
+ }
139
+ else {
140
+ candidate = null;
141
+ lastSize = -1;
142
+ }
143
+ if (Date.now() - start > timeoutMs)
144
+ return null;
145
+ await new Promise((r) => setTimeout(r, 300));
146
+ }
147
+ }
148
+ async function httpJson(url, init) {
149
+ try {
150
+ const res = await fetch(url, {
151
+ ...(init ?? {}),
152
+ signal: AbortSignal.timeout(15_000),
153
+ });
154
+ if (!res.ok)
155
+ return null;
156
+ return (await res.json());
157
+ }
158
+ catch {
159
+ return null;
160
+ }
161
+ }
162
+ /** Open a tab at `url` (same profile, so site login holds). Returns the tab id. */
163
+ async function openUrlTab(port, url) {
164
+ const created = await httpJson(`http://127.0.0.1:${port}/json/new?${new URLSearchParams({ url }).toString()}`, { method: 'PUT' });
165
+ const id = typeof created?.id === 'string' ? created.id : undefined;
166
+ if (!id)
167
+ throw new Error('could not open a download tab');
168
+ return id;
169
+ }
170
+ async function closeTab(port, id) {
171
+ try {
172
+ await httpJson(`http://127.0.0.1:${port}/json/close/${id}`);
173
+ }
174
+ catch {
175
+ /* best-effort */
176
+ }
177
+ }
178
+ /**
179
+ * Download `url` (or wait for an already-triggered download) into the run's
180
+ * staging directory. Returns the staged absolute path.
181
+ */
182
+ async function downloadTemplateFile(opts) {
183
+ const runId = String(opts.runId ?? '').trim();
184
+ if (!runId) {
185
+ return { ok: false, error: 'runId is required to download a file' };
186
+ }
187
+ const dir = (0, stage_file_1.runStagingDir)(runId);
188
+ try {
189
+ const { mkdirSync } = await Promise.resolve().then(() => __importStar(require('node:fs')));
190
+ mkdirSync(dir, { recursive: true });
191
+ }
192
+ catch {
193
+ return { ok: false, error: 'could not create the run staging directory' };
194
+ }
195
+ const timeoutMs = Math.min(Math.max(typeof opts.timeoutMs === 'number'
196
+ ? opts.timeoutMs
197
+ : exports.QA_DOWNLOAD_TIMEOUT_MS, 5000), 120_000);
198
+ const sinceMs = Date.now();
199
+ // Arm BEFORE triggering: anything already in the dir must not match.
200
+ void snapshot(dir);
201
+ if (opts.url) {
202
+ let parsed;
203
+ try {
204
+ parsed = new URL(opts.url);
205
+ }
206
+ catch {
207
+ return { ok: false, error: 'url is not a valid URL' };
208
+ }
209
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
210
+ return { ok: false, error: 'only http(s) download URLs are supported' };
211
+ }
212
+ let tabId = null;
213
+ try {
214
+ tabId = await openUrlTab(opts.port, parsed.toString());
215
+ }
216
+ catch (err) {
217
+ return {
218
+ ok: false,
219
+ error: err instanceof Error ? err.message : String(err),
220
+ };
221
+ }
222
+ // The tab stays open while the download lands (closing it first can
223
+ // cancel an in-flight download); it closes once the file has settled.
224
+ const found = await waitForNewFile(dir, sinceMs, timeoutMs);
225
+ await closeTab(opts.port, tabId);
226
+ if (!found) {
227
+ return {
228
+ ok: false,
229
+ error: 'no file arrived in the staging directory — the link may open a preview instead of downloading',
230
+ };
231
+ }
232
+ const path = (0, node_path_1.join)(dir, found.name);
233
+ if (!(0, node_fs_1.existsSync)(path)) {
234
+ return { ok: false, error: 'the downloaded file disappeared' };
235
+ }
236
+ return { ok: true, path, fileName: found.name, bytes: found.bytes };
237
+ }
238
+ const found = await waitForNewFile(dir, sinceMs, timeoutMs);
239
+ if (!found) {
240
+ return {
241
+ ok: false,
242
+ error: 'no new file arrived — trigger the download on the page first (click the download button), then call again',
243
+ };
244
+ }
245
+ const path = (0, node_path_1.join)(dir, found.name);
246
+ if (!(0, node_fs_1.existsSync)(path)) {
247
+ return { ok: false, error: 'the downloaded file disappeared' };
248
+ }
249
+ return { ok: true, path, fileName: found.name, bytes: found.bytes };
250
+ }
251
+ //# sourceMappingURL=download.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.js","sourceRoot":"","sources":["../../../src/lib/browser/download.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export declare const QA_RENDER_MAX_HTML_BYTES: number;
2
+ export declare const QA_RENDER_MIN_WIDTH = 320;
3
+ export declare const QA_RENDER_MAX_WIDTH = 2400;
4
+ export declare const QA_RENDER_TIMEOUT_MS = 10000;
5
+ export interface RenderImageResult {
6
+ ok: boolean;
7
+ buffer?: Buffer;
8
+ width?: number;
9
+ height?: number;
10
+ error?: string;
11
+ }
12
+ /** Lock the agent's HTML into a document that cannot call out or run script. */
13
+ export declare function wrapRenderDocument(html: string, title: string): string;
14
+ /**
15
+ * Render agent HTML to a PNG buffer. `drivenTargetId` restores focus to the
16
+ * page under test afterwards (pass undefined when unknown).
17
+ */
18
+ export declare function renderHtmlToImage(port: number, html: string, opts?: {
19
+ width?: number;
20
+ drivenTargetId?: string;
21
+ title?: string;
22
+ }): Promise<RenderImageResult>;
23
+ /**
24
+ * Render agent HTML to a PDF buffer (forms that demand a document upload).
25
+ * Same tab machinery as the PNG path.
26
+ */
27
+ export declare function renderHtmlToPdf(port: number, html: string, opts?: {
28
+ drivenTargetId?: string;
29
+ title?: string;
30
+ }): Promise<RenderImageResult>;
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.QA_RENDER_TIMEOUT_MS = exports.QA_RENDER_MAX_WIDTH = exports.QA_RENDER_MIN_WIDTH = exports.QA_RENDER_MAX_HTML_BYTES = void 0;
7
+ exports.wrapRenderDocument = wrapRenderDocument;
8
+ exports.renderHtmlToImage = renderHtmlToImage;
9
+ exports.renderHtmlToPdf = renderHtmlToPdf;
10
+ /**
11
+ * Render HTML to an image/PDF through the debug Chrome (2026-10, QA files).
12
+ *
13
+ * WHY THIS EXISTS: a QA run that reaches a form with `<input type="file">`
14
+ * has no file to attach. The agent cannot write to the user's disk and no
15
+ * MCP tool produces bytes — so the BRIDGE renders the bytes itself, in the
16
+ * browser it already drives, and stages them for `attachFile`.
17
+ *
18
+ * HOW: a throwaway tab on the same debug port (same profile, same cookies —
19
+ * irrelevant here since the document is local), `Page.setDocumentContent`
20
+ * with a CSP-locked wrapper, `Page.captureScreenshot` (PNG) or
21
+ * `Page.printToPDF` (PDF), then the tab is closed and focus is handed back
22
+ * to the driven tab. The render never touches the page the agent is testing.
23
+ *
24
+ * GUARDS: the document cannot run script or make requests
25
+ * (`default-src 'none'; script-src 'none'`), HTML is size-capped by the
26
+ * caller, and the tab is ALWAYS closed in a `finally`.
27
+ */
28
+ const ws_1 = __importDefault(require("ws"));
29
+ exports.QA_RENDER_MAX_HTML_BYTES = 200 * 1024;
30
+ exports.QA_RENDER_MIN_WIDTH = 320;
31
+ exports.QA_RENDER_MAX_WIDTH = 2400;
32
+ exports.QA_RENDER_TIMEOUT_MS = 10_000;
33
+ /** Lock the agent's HTML into a document that cannot call out or run script. */
34
+ function wrapRenderDocument(html, title) {
35
+ const safeTitle = title.replace(/[<>&"]/g, '');
36
+ return (`<!doctype html><html><head><meta charset="utf-8">` +
37
+ `<title>${safeTitle}</title>` +
38
+ `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'none'; style-src 'unsafe-inline'; img-src data:; font-src data:;">` +
39
+ `<style>body{margin:0;padding:32px;font-family:system-ui,sans-serif;}</style>` +
40
+ `</head><body>${html}</body></html>`);
41
+ }
42
+ async function httpJson(url, init) {
43
+ try {
44
+ const res = await fetch(url, {
45
+ ...(init ?? {}),
46
+ signal: AbortSignal.timeout(exports.QA_RENDER_TIMEOUT_MS),
47
+ });
48
+ if (!res.ok)
49
+ return null;
50
+ return (await res.json());
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ function send(ws, id, method, params) {
57
+ ws.send(JSON.stringify({ id, method, params }));
58
+ }
59
+ function call(ws, nextId, method, params, timeoutMs = exports.QA_RENDER_TIMEOUT_MS) {
60
+ return new Promise((resolve, reject) => {
61
+ const id = nextId();
62
+ const timer = setTimeout(() => reject(new Error(`CDP timeout: ${method}`)), timeoutMs);
63
+ const onMessage = (raw) => {
64
+ let msg;
65
+ try {
66
+ msg = JSON.parse(raw.toString());
67
+ }
68
+ catch {
69
+ return;
70
+ }
71
+ if (msg?.id !== id)
72
+ return;
73
+ clearTimeout(timer);
74
+ ws.off('message', onMessage);
75
+ if (msg.error)
76
+ reject(new Error(msg.error.message ?? method));
77
+ else
78
+ resolve(msg.result);
79
+ };
80
+ ws.on('message', onMessage);
81
+ try {
82
+ send(ws, id, method, params);
83
+ }
84
+ catch (err) {
85
+ clearTimeout(timer);
86
+ ws.off('message', onMessage);
87
+ reject(err instanceof Error ? err : new Error(String(err)));
88
+ }
89
+ });
90
+ }
91
+ function connect(wsUrl, timeoutMs = exports.QA_RENDER_TIMEOUT_MS) {
92
+ return new Promise((resolve, reject) => {
93
+ const ws = new ws_1.default(wsUrl);
94
+ const timer = setTimeout(() => {
95
+ try {
96
+ ws.close();
97
+ }
98
+ catch {
99
+ /* already dead */
100
+ }
101
+ reject(new Error('render tab connection timed out'));
102
+ }, timeoutMs);
103
+ ws.on('open', () => {
104
+ clearTimeout(timer);
105
+ resolve(ws);
106
+ });
107
+ ws.on('error', (err) => {
108
+ clearTimeout(timer);
109
+ reject(err instanceof Error ? err : new Error(String(err)));
110
+ });
111
+ });
112
+ }
113
+ /**
114
+ * Open a throwaway tab, render the callback against its CDP session, then
115
+ * close the tab and hand focus back. `drivenTargetId` is best-effort: when
116
+ * the caller does not know it, the render tab simply closes.
117
+ */
118
+ async function withRenderTab(port, drivenTargetId, fn) {
119
+ const created = await httpJson(`http://127.0.0.1:${port}/json/new?about:blank`, { method: 'PUT' });
120
+ const target = (created ?? null);
121
+ if (!target?.webSocketDebuggerUrl) {
122
+ throw new Error('could not open a render tab on the debug browser');
123
+ }
124
+ const ws = await connect(target.webSocketDebuggerUrl);
125
+ let next = 1;
126
+ const nextId = () => next++;
127
+ try {
128
+ return await fn(ws, nextId);
129
+ }
130
+ finally {
131
+ try {
132
+ ws.close();
133
+ }
134
+ catch {
135
+ /* already dead */
136
+ }
137
+ try {
138
+ await httpJson(`http://127.0.0.1:${port}/json/close/${target.id}`);
139
+ }
140
+ catch {
141
+ /* best-effort */
142
+ }
143
+ if (drivenTargetId) {
144
+ try {
145
+ await httpJson(`http://127.0.0.1:${port}/json/activate/${drivenTargetId}`);
146
+ }
147
+ catch {
148
+ /* best-effort: focus restore must never fail the render */
149
+ }
150
+ }
151
+ }
152
+ }
153
+ async function waitSettled(ws, nextId, timeoutMs = exports.QA_RENDER_TIMEOUT_MS) {
154
+ const start = Date.now();
155
+ for (;;) {
156
+ let state = '';
157
+ try {
158
+ const res = await call(ws, nextId, 'Runtime.evaluate', {
159
+ expression: 'document.readyState',
160
+ returnByValue: true,
161
+ });
162
+ state = String(res?.result?.value ?? '');
163
+ }
164
+ catch {
165
+ /* a failed poll is not a failed render */
166
+ }
167
+ if (state === 'complete')
168
+ break;
169
+ if (Date.now() - start > timeoutMs)
170
+ break;
171
+ await new Promise((r) => setTimeout(r, 150));
172
+ }
173
+ try {
174
+ await call(ws, nextId, 'Runtime.evaluate', {
175
+ expression: 'document.fonts ? document.fonts.ready.then(() => 1) : 1',
176
+ awaitPromise: true,
177
+ returnByValue: true,
178
+ }, 4000);
179
+ }
180
+ catch {
181
+ /* fonts are best-effort */
182
+ }
183
+ await new Promise((r) => setTimeout(r, 150));
184
+ }
185
+ function clampWidth(width) {
186
+ const n = typeof width === 'number' ? Math.round(width) : 1200;
187
+ return Math.min(exports.QA_RENDER_MAX_WIDTH, Math.max(exports.QA_RENDER_MIN_WIDTH, Number.isFinite(n) ? n : 1200));
188
+ }
189
+ /**
190
+ * Render agent HTML to a PNG buffer. `drivenTargetId` restores focus to the
191
+ * page under test afterwards (pass undefined when unknown).
192
+ */
193
+ async function renderHtmlToImage(port, html, opts) {
194
+ if (!html || !html.trim()) {
195
+ return { ok: false, error: 'html is required to render an image' };
196
+ }
197
+ if (Buffer.byteLength(html, 'utf8') > exports.QA_RENDER_MAX_HTML_BYTES) {
198
+ return {
199
+ ok: false,
200
+ error: `html is too large (max ${exports.QA_RENDER_MAX_HTML_BYTES / 1024} KB)`,
201
+ };
202
+ }
203
+ const width = clampWidth(opts?.width);
204
+ try {
205
+ const out = await withRenderTab(port, opts?.drivenTargetId, async (ws, nextId) => {
206
+ await call(ws, nextId, 'Page.enable', {});
207
+ const tree = await call(ws, nextId, 'Page.getFrameTree', {});
208
+ const frameId = tree?.frameTree?.frame?.id;
209
+ if (!frameId)
210
+ throw new Error('render tab has no frame');
211
+ await call(ws, nextId, 'Emulation.setDeviceMetricsOverride', {
212
+ width,
213
+ height: 900,
214
+ deviceScaleFactor: 1,
215
+ mobile: false,
216
+ });
217
+ await call(ws, nextId, 'Page.setDocumentContent', {
218
+ frameId,
219
+ html: wrapRenderDocument(html, opts?.title ?? 'test upload'),
220
+ });
221
+ await waitSettled(ws, nextId);
222
+ const shot = await call(ws, nextId, 'Page.captureScreenshot', {
223
+ format: 'png',
224
+ captureBeyondViewport: true,
225
+ });
226
+ if (!shot?.data)
227
+ throw new Error('the render produced no image');
228
+ return { data: String(shot.data) };
229
+ });
230
+ return {
231
+ ok: true,
232
+ buffer: Buffer.from(out.data, 'base64'),
233
+ width,
234
+ };
235
+ }
236
+ catch (err) {
237
+ return {
238
+ ok: false,
239
+ error: err instanceof Error ? err.message : String(err),
240
+ };
241
+ }
242
+ }
243
+ /**
244
+ * Render agent HTML to a PDF buffer (forms that demand a document upload).
245
+ * Same tab machinery as the PNG path.
246
+ */
247
+ async function renderHtmlToPdf(port, html, opts) {
248
+ if (!html || !html.trim()) {
249
+ return { ok: false, error: 'html is required to render a PDF' };
250
+ }
251
+ if (Buffer.byteLength(html, 'utf8') > exports.QA_RENDER_MAX_HTML_BYTES) {
252
+ return {
253
+ ok: false,
254
+ error: `html is too large (max ${exports.QA_RENDER_MAX_HTML_BYTES / 1024} KB)`,
255
+ };
256
+ }
257
+ try {
258
+ const out = await withRenderTab(port, opts?.drivenTargetId, async (ws, nextId) => {
259
+ await call(ws, nextId, 'Page.enable', {});
260
+ const tree = await call(ws, nextId, 'Page.getFrameTree', {});
261
+ const frameId = tree?.frameTree?.frame?.id;
262
+ if (!frameId)
263
+ throw new Error('render tab has no frame');
264
+ await call(ws, nextId, 'Page.setDocumentContent', {
265
+ frameId,
266
+ html: wrapRenderDocument(html, opts?.title ?? 'test upload'),
267
+ });
268
+ await waitSettled(ws, nextId);
269
+ const pdf = await call(ws, nextId, 'Page.printToPDF', {
270
+ printBackground: true,
271
+ });
272
+ if (!pdf?.data)
273
+ throw new Error('the render produced no PDF');
274
+ return { data: String(pdf.data) };
275
+ });
276
+ return { ok: true, buffer: Buffer.from(out.data, 'base64') };
277
+ }
278
+ catch (err) {
279
+ return {
280
+ ok: false,
281
+ error: err instanceof Error ? err.message : String(err),
282
+ };
283
+ }
284
+ }
285
+ //# sourceMappingURL=render-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-image.js","sourceRoot":"","sources":["../../../src/lib/browser/render-image.ts"],"names":[],"mappings":"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"}