@opencraw/driver 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.esm.js CHANGED
@@ -6,13 +6,20 @@ import { dirname, join } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
7
 
8
8
  // src/server/serve-driver.use-case.ts
9
- import { once } from "node:events";
9
+ import { once as once2 } from "node:events";
10
10
 
11
11
  // src/protocol/driver-message.contract.ts
12
12
  import { calloutRequestSchema, calloutResponseSchema } from "@opencraw/core";
13
13
  import { z } from "zod";
14
- var PROTOCOL_VERSION = "1.0.0";
14
+ var PROTOCOL_VERSION = "1.2.0";
15
15
  var recipeObject = z.record(z.string(), z.unknown());
16
+ var coreObject = z.record(z.string(), z.unknown());
17
+ var accessFields = {
18
+ accessConfig: z.string().optional(),
19
+ access: z.string().optional(),
20
+ /** Access plugins the client serves: a profile `{ "kind": "plugin", "name": … }` naming one leases through a `callout` to the client. */
21
+ accessPlugins: z.array(z.string()).optional()
22
+ };
16
23
  var recipeSource = {
17
24
  paths: z.array(z.string()).min(1).optional(),
18
25
  recipes: z.array(recipeObject).min(1).optional()
@@ -48,17 +55,86 @@ var runParamsSchema = z.strictObject({
48
55
  parallel: z.number().int().min(1).max(16).optional(),
49
56
  browser: z.strictObject({ headless: z.boolean().optional(), executablePath: z.string().optional(), ignoreHTTPSErrors: z.boolean().optional() }).optional(),
50
57
  /** The hooks the client answers itself: each becomes a `callout` request to the client when a recipe calls it. */
51
- hooks: z.array(z.string()).optional()
58
+ hooks: z.array(z.string()).optional(),
59
+ /** Captcha solvers the client serves, by name: a challenge goes to the client as a `captcha` callout. */
60
+ captchaSolvers: z.array(z.string()).optional(),
61
+ ...accessFields
52
62
  });
53
63
  var runResultSchema = z.strictObject({ runId: z.string() });
64
+ var windowsSchema = z.union([z.number().int().min(1).max(64), z.record(z.string(), z.unknown())]);
65
+ var workParamsSchema = z.strictObject({
66
+ ...recipeSource,
67
+ only: z.array(z.string()).optional(),
68
+ out: z.string().optional(),
69
+ append: z.boolean().optional(),
70
+ browser: z.strictObject({ headless: z.boolean().optional(), executablePath: z.string().optional(), ignoreHTTPSErrors: z.boolean().optional() }).optional(),
71
+ hooks: z.array(z.string()).optional(),
72
+ captchaSolvers: z.array(z.string()).optional(),
73
+ ...accessFields,
74
+ windows: windowsSchema.optional()
75
+ });
76
+ var varValue = z.union([z.string(), z.number(), z.boolean()]);
77
+ var workItemSchema = z.strictObject({
78
+ id: z.string().min(1),
79
+ vars: z.record(z.string(), varValue),
80
+ recipe: z.string().optional()
81
+ });
54
82
  var cancelParamsSchema = z.strictObject({ runId: z.string() });
55
83
  var cancelResultSchema = z.strictObject({ cancelled: z.boolean() });
84
+ var probeParamsSchema = z.strictObject({
85
+ url: z.string().min(1),
86
+ /** Render the page in Chromium first (for pages built by scripts). */
87
+ browser: z.boolean().optional(),
88
+ browserPath: z.string().optional(),
89
+ insecureTls: z.boolean().optional(),
90
+ userAgent: z.string().optional(),
91
+ ...accessFields
92
+ });
93
+ var diffParamsSchema = z.strictObject({
94
+ /** The earlier run's JSON Lines file. */
95
+ previous: z.string().min(1),
96
+ current: z.string().min(1),
97
+ /** The fields that identify a record; default: each line's `_key`. */
98
+ key: z.array(z.string()).optional(),
99
+ /** Fields left out of the comparison. */
100
+ ignore: z.array(z.string()).optional(),
101
+ /** Changes returned at most (default 200); the counts cover all of them. */
102
+ limit: z.number().int().min(0).optional()
103
+ });
104
+ var diffResultSchema = z.strictObject({
105
+ added: z.number(),
106
+ removed: z.number(),
107
+ changed: z.number(),
108
+ unchanged: z.number(),
109
+ /** Set when the current run lost most of the previous run's records. */
110
+ shrunk: z.strictObject({ previous: z.number(), current: z.number() }).optional(),
111
+ /** The report a person reads, one line per change. */
112
+ summary: z.array(z.string()),
113
+ /** The changes, up to `limit`: each `added`, `removed` or `changed` (with each field's before and after). */
114
+ changes: z.array(coreObject),
115
+ /** More changes than `limit` were found. */
116
+ truncated: z.boolean()
117
+ });
118
+ var exportParamsSchema = z.strictObject({
119
+ /** A run's JSON Lines file. */
120
+ records: z.string().min(1),
121
+ /** The output recipe that gives the columns. */
122
+ output: z.string().min(1),
123
+ /** The file to write; its extension names the format, as for `run`. */
124
+ out: z.string().min(1)
125
+ });
126
+ var exportResultSchema = z.strictObject({ written: z.number(), location: z.string() });
56
127
  var shutdownResultSchema = z.strictObject({});
128
+ var workNextParamsSchema = z.strictObject({ runId: z.string() });
129
+ var workNextResultSchema = z.strictObject({ item: workItemSchema.nullable() });
130
+ var workRecordSchema = z.strictObject({ key: z.string().nullable(), data: z.record(z.string(), z.unknown()) });
131
+ var workDoneParamsSchema = z.strictObject({ runId: z.string(), item: workItemSchema, report: coreObject, records: z.array(workRecordSchema) });
132
+ var workFailedParamsSchema = z.strictObject({ runId: z.string(), item: workItemSchema, report: coreObject, outcome: z.enum(["failure", "neutral"]) });
57
133
  var eventParamsSchema = z.strictObject({ runId: z.string(), event: z.record(z.string(), z.unknown()) });
58
134
  var recordParamsSchema = z.strictObject({ runId: z.string(), recipeId: z.string(), key: z.string().nullable(), data: z.record(z.string(), z.unknown()) });
59
135
  var finishedParamsSchema = z.strictObject({
60
136
  runId: z.string(),
61
- /** The crawl report (`CrawlReport`), absent when the run could not start. */
137
+ /** The crawl report (`CrawlReport`), or for `work` the work report (`WorkReport`); absent when the run could not start. */
62
138
  report: z.record(z.string(), z.unknown()).optional(),
63
139
  /** Why the run could not start, or stopped as a whole. */
64
140
  error: z.string().optional()
@@ -68,19 +144,127 @@ var calloutParamsSchema = z.strictObject({ runId: z.string(), request: calloutRe
68
144
  // src/protocol/driver-json-schema.mapper.ts
69
145
  import { z as z2 } from "zod";
70
146
 
147
+ // src/record-files/diff-record-files.use-case.ts
148
+ import { diffReport } from "@opencraw/cli";
149
+ import { diffRecords, readRecordsFile } from "@opencraw/core";
150
+ var CHANGE_LIMIT = 200;
151
+ async function diffRecordFiles(params) {
152
+ const [previous, current] = await Promise.all([readRecordsFile(params.previous), readRecordsFile(params.current)]);
153
+ const diff = diffRecords(previous, current, { key: params.key, ignore: params.ignore });
154
+ const limit = params.limit ?? CHANGE_LIMIT;
155
+ return {
156
+ added: diff.added,
157
+ removed: diff.removed,
158
+ changed: diff.changed,
159
+ unchanged: diff.unchanged,
160
+ ...diff.shrunk !== void 0 && { shrunk: diff.shrunk },
161
+ summary: diffReport(diff),
162
+ changes: diff.changes.slice(0, limit).map((change) => ({ ...change })),
163
+ truncated: diff.changes.length > limit
164
+ };
165
+ }
166
+
167
+ // src/record-files/export-record-files.use-case.ts
168
+ import { readFile } from "node:fs/promises";
169
+ import { fileSink, outputRecordOf, parseOutputRecipe, readRecordsFile as readRecordsFile2 } from "@opencraw/core";
170
+ async function exportRecordFiles(params) {
171
+ const output = parseOutputRecipe(JSON.parse(await readFile(params.output, "utf8")), params.output);
172
+ const stored = await readRecordsFile2(params.records);
173
+ const sink = fileSink(params.out, { browser: { executablePath: process.env.OPENCRAW_CHROMIUM } });
174
+ await sink.open(output);
175
+ for (const line of stored) await sink.write(outputRecordOf(line));
176
+ const summary = await sink.close();
177
+ return { written: summary.written, location: summary.location ?? params.out };
178
+ }
179
+
71
180
  // src/session/run-session.use-case.ts
72
- import { createCrawler, fileSink, RecipeSet } from "@opencraw/core";
181
+ import { createCrawler, fileSink as fileSink2, RecipeSet } from "@opencraw/core";
73
182
 
74
183
  // src/callout-bridge/client-hooks.client.ts
75
- import { calloutHook, calloutResponseSchema as calloutResponseSchema2 } from "@opencraw/core";
76
- function clientTransport(hookName, runId, ask) {
184
+ import { accessPluginVia, calloutHook, calloutResponseSchema as calloutResponseSchema2, captchaSolverVia } from "@opencraw/core";
185
+ function clientTransport(label, runId, ask) {
77
186
  return {
78
- label: `client hook ${hookName}`,
187
+ label,
79
188
  call: async (request) => calloutResponseSchema2.parse(await ask("callout", { runId, request }))
80
189
  };
81
190
  }
82
191
  function clientHooks(names, runId, ask) {
83
- return Object.fromEntries(names.map((name) => [name, calloutHook(name, clientTransport(name, runId, ask))]));
192
+ return Object.fromEntries(names.map((name) => [name, calloutHook(name, clientTransport(`client hook ${name}`, runId, ask))]));
193
+ }
194
+ function clientCaptchaSolvers(names, runId, ask) {
195
+ return names.map((name) => captchaSolverVia(name, clientTransport(`client captcha solver ${name}`, runId, ask)));
196
+ }
197
+ function clientAccessPlugins(names, runId, ask) {
198
+ return names.map((name) => accessPluginVia(name, clientTransport(`client access plugin ${name}`, runId, ask)));
199
+ }
200
+
201
+ // src/site-access/resolve-site-access.use-case.ts
202
+ import { resolveAccess } from "@opencraw/cli";
203
+ async function resolveSiteAccess(params, runId, ask, env = process.env) {
204
+ const file = params.accessConfig ?? env.OPENCRAW_ACCESS;
205
+ if (file === void 0 && params.access !== void 0) throw new Error(`access profile "${params.access}" needs an access config: give "accessConfig", or set OPENCRAW_ACCESS where the driver runs`);
206
+ const access = await resolveAccess({ insecureTls: false, access: file, accessProfile: params.access });
207
+ return { access, accessPlugins: clientAccessPlugins(params.accessPlugins ?? [], runId, ask) };
208
+ }
209
+
210
+ // src/work-bridge/client-work-source.client.ts
211
+ import { once } from "node:events";
212
+ function clientWorkSource(runId, ask, notify) {
213
+ const kept = [];
214
+ let ended = false;
215
+ const askClient = async () => {
216
+ const { item } = workNextResultSchema.parse(await ask("work.next", { runId }));
217
+ if (item === null) {
218
+ ended = true;
219
+ return void 0;
220
+ }
221
+ return item;
222
+ };
223
+ const keepLate = async (answer) => {
224
+ try {
225
+ const item = await answer;
226
+ if (item !== void 0) kept.push(item);
227
+ } catch {
228
+ }
229
+ };
230
+ return {
231
+ next: async (options) => {
232
+ const waiting = kept.shift();
233
+ if (waiting !== void 0) return waiting;
234
+ if (ended) return;
235
+ const answer = askClient();
236
+ const signal = options?.signal;
237
+ if (signal === void 0) return await answer;
238
+ signal.throwIfAborted();
239
+ const settled = new AbortController();
240
+ const answered = (async () => {
241
+ const item = await answer;
242
+ return { item };
243
+ })();
244
+ const retired = (async () => {
245
+ try {
246
+ await once(signal, "abort", { signal: settled.signal });
247
+ return "retired";
248
+ } catch {
249
+ return "answered";
250
+ }
251
+ })();
252
+ try {
253
+ const first = await Promise.race([answered, retired]);
254
+ if (first !== "retired" && first !== "answered") return first.item;
255
+ void keepLate(answer);
256
+ throw signal.reason instanceof Error ? signal.reason : new Error(String(signal.reason));
257
+ } finally {
258
+ settled.abort();
259
+ }
260
+ },
261
+ done: (item, report, records) => {
262
+ notify("work.done", { runId, item, report, records: records.map((record) => ({ key: record.key, data: record.data })) });
263
+ },
264
+ failed: (item, report, outcome) => {
265
+ notify("work.failed", { runId, item, report, outcome });
266
+ }
267
+ };
84
268
  }
85
269
 
86
270
  // src/session/recipe-loading.use-case.ts
@@ -124,36 +308,53 @@ function streamingSink() {
124
308
  function runSessions(notify, ask) {
125
309
  const running = /* @__PURE__ */ new Map();
126
310
  let next = 1;
127
- const crawl = async (runId, crawler, set) => {
128
- try {
129
- const report = await crawler.run(set);
130
- notify("finished", { runId, report });
131
- } catch (error) {
132
- notify("finished", { runId, error: error instanceof Error ? error.message : String(error) });
133
- } finally {
134
- running.delete(runId);
135
- await crawler.close();
136
- }
311
+ const crawlerFor = async (runId, params) => {
312
+ const { access, accessPlugins } = await resolveSiteAccess(params, runId, ask);
313
+ return createCrawler({
314
+ sink: params.out === void 0 ? streamingSink() : fileSink2(params.out, { append: params.append, browser: { executablePath: params.browser?.executablePath } }),
315
+ hooks: clientHooks(params.hooks ?? [], runId, ask),
316
+ captchaSolvers: clientCaptchaSolvers(params.captchaSolvers ?? [], runId, ask),
317
+ access,
318
+ accessPlugins,
319
+ profilesDir: process.env.OPENCRAW_PROFILES,
320
+ parallel: params.parallel,
321
+ resume: params.resume,
322
+ debug: params.dryRun,
323
+ browser: { headless: params.browser?.headless ?? true, executablePath: params.browser?.executablePath, ignoreHTTPSErrors: params.browser?.ignoreHTTPSErrors },
324
+ onEvent: (event) => {
325
+ notify("event", { runId, event });
326
+ if (event.type === "record:emit" && params.out === void 0) notify("record", { runId, recipeId: event.recipeId, key: event.key, data: event.data });
327
+ }
328
+ });
329
+ };
330
+ const track = (runId, crawler, crawling) => {
331
+ running.set(runId, crawler);
332
+ void (async () => {
333
+ try {
334
+ notify("finished", { runId, report: await crawling() });
335
+ } catch (error) {
336
+ notify("finished", { runId, error: error instanceof Error ? error.message : String(error) });
337
+ } finally {
338
+ running.delete(runId);
339
+ await crawler.close();
340
+ }
341
+ })();
137
342
  };
138
343
  return {
139
344
  start: async (params) => {
140
345
  const loaded = await loadRecipes(params);
141
346
  const set = params.dryRun === true ? new RecipeSet(loaded.output, loaded.inputs.map((input) => ({ ...input, limits: { ...input.limits, maxRecords: 1 } }))) : loaded;
142
347
  const runId = `run-${next++}`;
143
- const crawler = createCrawler({
144
- sink: params.out === void 0 ? streamingSink() : fileSink(params.out, { append: params.append, browser: { executablePath: params.browser?.executablePath } }),
145
- hooks: clientHooks(params.hooks ?? [], runId, ask),
146
- parallel: params.parallel,
147
- resume: params.resume,
148
- debug: params.dryRun,
149
- browser: { headless: params.browser?.headless ?? true, executablePath: params.browser?.executablePath, ignoreHTTPSErrors: params.browser?.ignoreHTTPSErrors },
150
- onEvent: (event) => {
151
- notify("event", { runId, event });
152
- if (event.type === "record:emit" && params.out === void 0) notify("record", { runId, recipeId: event.recipeId, key: event.key, data: event.data });
153
- }
154
- });
155
- running.set(runId, crawler);
156
- void crawl(runId, crawler, set);
348
+ const crawler = await crawlerFor(runId, params);
349
+ track(runId, crawler, async () => await crawler.run(set));
350
+ return runId;
351
+ },
352
+ startWork: async (params) => {
353
+ const set = await loadRecipes(params);
354
+ const runId = `run-${next++}`;
355
+ const crawler = await crawlerFor(runId, params);
356
+ const windows = params.windows;
357
+ track(runId, crawler, async () => await crawler.work(set, clientWorkSource(runId, ask, notify), { windows }));
157
358
  return runId;
158
359
  },
159
360
  cancel: async (runId) => {
@@ -173,6 +374,21 @@ function runSessions(notify, ask) {
173
374
  };
174
375
  }
175
376
 
377
+ // src/site-probe/probe-site.use-case.ts
378
+ import { probeUrl } from "@opencraw/cli";
379
+ async function probeSite(params, probeId, ask) {
380
+ const { access, accessPlugins } = await resolveSiteAccess(params, probeId, ask);
381
+ const result = await probeUrl(params.url, {
382
+ browser: params.browser ?? false,
383
+ browserPath: params.browserPath ?? process.env.OPENCRAW_CHROMIUM,
384
+ insecureTls: params.insecureTls ?? false,
385
+ userAgent: params.userAgent,
386
+ accessConfig: access,
387
+ accessPlugins
388
+ });
389
+ return { ...result };
390
+ }
391
+
176
392
  // src/transport/line-channel.client.ts
177
393
  import { createInterface } from "node:readline";
178
394
 
@@ -279,7 +495,7 @@ function openLineChannel(input, output, handle) {
279
495
  }
280
496
 
281
497
  // src/server/serve-driver.use-case.ts
282
- var METHODS = ["initialize", "validate", "run", "cancel", "shutdown"];
498
+ var METHODS = ["initialize", "validate", "run", "work", "cancel", "probe", "diff", "export", "shutdown"];
283
499
  var major = (version) => version.split(".", 1)[0];
284
500
  function parsed(schema, params) {
285
501
  const result = schema.safeParse(params ?? {});
@@ -289,6 +505,7 @@ function parsed(schema, params) {
289
505
  async function serveDriver(input, output, identity) {
290
506
  let initialized = false;
291
507
  const stopping = new AbortController();
508
+ let probes = 0;
292
509
  const channel = openLineChannel(input, output, async (method, params) => {
293
510
  if (method === "initialize") {
294
511
  const hello = parsed(initializeParamsSchema, params);
@@ -301,7 +518,11 @@ async function serveDriver(input, output, identity) {
301
518
  if (!initialized) throw new RpcFailure(RPC_ERRORS.server, "call initialize first");
302
519
  if (method === "validate") return await validateRecipes(parsed(validateParamsSchema, params));
303
520
  if (method === "run") return { runId: await sessions.start(parsed(runParamsSchema, params)) };
521
+ if (method === "work") return { runId: await sessions.startWork(parsed(workParamsSchema, params)) };
304
522
  if (method === "cancel") return { cancelled: await sessions.cancel(parsed(cancelParamsSchema, params).runId) };
523
+ if (method === "probe") return await probeSite(parsed(probeParamsSchema, params), `probe-${++probes}`, channel.request);
524
+ if (method === "diff") return await diffRecordFiles(parsed(diffParamsSchema, params));
525
+ if (method === "export") return await exportRecordFiles(parsed(exportParamsSchema, params));
305
526
  await sessions.closeAll();
306
527
  setImmediate(() => {
307
528
  stopping.abort();
@@ -309,7 +530,7 @@ async function serveDriver(input, output, identity) {
309
530
  return {};
310
531
  });
311
532
  const sessions = runSessions(channel.notify, channel.request);
312
- await Promise.race([channel.closed, once(stopping.signal, "abort")]);
533
+ await Promise.race([channel.closed, once2(stopping.signal, "abort")]);
313
534
  await channel.drained();
314
535
  await sessions.closeAll();
315
536
  }
@@ -1,12 +1,19 @@
1
- import type { CalloutTransport, HookMap } from '@opencraw/core';
1
+ import type { AccessPlugin, CalloutTransport, CaptchaSolver, HookMap } from '@opencraw/core';
2
2
  /** Sends one request to the client and waits for its answer: the channel's `request`. */
3
3
  export type AskClient = (method: string, params: unknown) => Promise<unknown>;
4
+ /** Sends a notification to the client: the channel's `notify`. */
5
+ export type NotifyClient = (method: string, params: unknown) => void;
4
6
  /**
5
7
  * A transport whose handler is the client: each call is a `callout` request carrying core's own
6
8
  * `CalloutRequest`, and the client answers with a `CalloutResponse`, so `pending` and idempotency keys
7
9
  * work exactly as they do for a command or an HTTP hook.
10
+ *
11
+ * @param label - What the logs call it (`client hook tidy`).
12
+ * @param runId - The run it belongs to, sent with every callout.
13
+ * @param ask - The channel's request.
14
+ * @returns The transport.
8
15
  */
9
- export declare function clientTransport(hookName: string, runId: string, ask: AskClient): CalloutTransport;
16
+ export declare function clientTransport(label: string, runId: string, ask: AskClient): CalloutTransport;
10
17
  /**
11
18
  * The hooks a run's client serves, each answered by the client over the channel.
12
19
  *
@@ -16,4 +23,25 @@ export declare function clientTransport(hookName: string, runId: string, ask: As
16
23
  * @returns A hook map for `createCrawler`.
17
24
  */
18
25
  export declare function clientHooks(names: readonly string[], runId: string, ask: AskClient): HookMap;
26
+ /**
27
+ * The captcha solvers a run's client serves: a challenge goes to the client as a `captcha` callout (its
28
+ * input is core's `CaptchaCalloutInput`), and the answer's `token` or `text` is put on the page.
29
+ *
30
+ * @param names - The solvers the client said it serves.
31
+ * @param runId - The run they belong to.
32
+ * @param ask - The channel's request.
33
+ * @returns Solvers for `createCrawler`.
34
+ */
35
+ export declare function clientCaptchaSolvers(names: readonly string[], runId: string, ask: AskClient): CaptchaSolver[];
36
+ /**
37
+ * The access plugins a client serves: a profile `{ "kind": "plugin", "name": … }` leases through an
38
+ * `access` callout to the client (`phase: "lease"`), and releases through another (`phase: "release"`)
39
+ * when the client's lease asked for it.
40
+ *
41
+ * @param names - The plugins the client said it serves.
42
+ * @param runId - The run, or the probe, they belong to.
43
+ * @param ask - The channel's request.
44
+ * @returns Plugins for `createCrawler` or a probe.
45
+ */
46
+ export declare function clientAccessPlugins(names: readonly string[], runId: string, ask: AskClient): AccessPlugin[];
19
47
  //# sourceMappingURL=client-hooks.client.d.ts.map
@@ -1,3 +1,3 @@
1
- export { clientHooks, clientTransport } from './client-hooks.client.js';
2
- export type { AskClient } from './client-hooks.client.js';
1
+ export { clientAccessPlugins, clientCaptchaSolvers, clientHooks, clientTransport } from './client-hooks.client.js';
2
+ export type { AskClient, NotifyClient } from './client-hooks.client.js';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1,10 +1,14 @@
1
1
  export { serveDriver } from './server/index.js';
2
2
  export type { DriverIdentity } from './server/index.js';
3
- export { PROTOCOL_VERSION, MESSAGES, driverProtocolJsonSchema, initializeParamsSchema, initializeResultSchema, validateParamsSchema, validateResultSchema, runParamsSchema, runResultSchema, cancelParamsSchema, cancelResultSchema, eventParamsSchema, recordParamsSchema, finishedParamsSchema, calloutParamsSchema, calloutResultSchema, } from './protocol/index.js';
4
- export type { InitializeParams, InitializeResult, ValidateParams, ValidateResult, RunParams, RunResult, CancelParams, CancelResult, EventParams, RecordParams, FinishedParams, CalloutParams, } from './protocol/index.js';
3
+ export { PROTOCOL_VERSION, MESSAGES, driverProtocolJsonSchema, initializeParamsSchema, initializeResultSchema, validateParamsSchema, validateResultSchema, runParamsSchema, runResultSchema, cancelParamsSchema, cancelResultSchema, eventParamsSchema, recordParamsSchema, finishedParamsSchema, calloutParamsSchema, calloutResultSchema, probeParamsSchema, probeResultSchema, diffParamsSchema, diffResultSchema, exportParamsSchema, exportResultSchema, workParamsSchema, workItemSchema, workNextParamsSchema, workNextResultSchema, workDoneParamsSchema, workFailedParamsSchema, } from './protocol/index.js';
4
+ export type { InitializeParams, InitializeResult, ValidateParams, ValidateResult, RunParams, RunResult, CancelParams, CancelResult, EventParams, RecordParams, FinishedParams, CalloutParams, ProbeParams, DiffParams, DiffResult, ExportParams, ExportResult, WorkParams, WorkItemMessage, WorkNextResult, WorkDoneParams, WorkFailedParams, } from './protocol/index.js';
5
5
  export { openLineChannel, RPC_ERRORS, RpcFailure } from './transport/index.js';
6
6
  export type { LineChannel, RequestHandler, RpcError, RpcMessage } from './transport/index.js';
7
7
  export { runSessions, validateRecipes, streamingSink } from './session/index.js';
8
- export type { RunSessions, NotifyClient } from './session/index.js';
9
- export { clientHooks } from './callout-bridge/index.js';
8
+ export type { RunSessions } from './session/index.js';
9
+ export { clientHooks, clientCaptchaSolvers, clientAccessPlugins } from './callout-bridge/index.js';
10
+ export type { AskClient, NotifyClient } from './callout-bridge/index.js';
11
+ export { clientWorkSource } from './work-bridge/index.js';
12
+ export { probeSite } from './site-probe/index.js';
13
+ export { diffRecordFiles, exportRecordFiles } from './record-files/index.js';
10
14
  //# sourceMappingURL=index.d.ts.map