@opencraw/studio 0.0.14 → 0.0.16

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/index.esm.js CHANGED
@@ -503,10 +503,16 @@ const recipeListingSchema = z.object({
503
503
  /** The Steps tab's view of this file's `steps`, from `@opencraw/studio`'s `scope-outline` slice. `input` recipes only; `undefined` for an `output` or `unknown` file, which has no steps to show. */
504
504
  outline: outlineViewSchema.optional()
505
505
  });
506
- /** What `open-workspace` answers with: every recipe file directly inside the folder. */
506
+ /** The hooks Studio was started with (`opencraw studio --hooks <file>`, issue #150): where they came from and what they are called, for the warning bar and the hook-name suggestions. */
507
+ const loadedHooksSchema = z.object({
508
+ source: z.string(),
509
+ names: z.array(z.string())
510
+ });
511
+ /** What `open-workspace` answers with: every recipe file directly inside the folder, and the hooks Studio runs them with, if any. */
507
512
  const workspaceViewSchema = z.object({
508
513
  folder: z.string(),
509
- recipes: z.array(recipeListingSchema)
514
+ recipes: z.array(recipeListingSchema),
515
+ hooks: loadedHooksSchema.optional()
510
516
  });
511
517
 
512
518
  /** `import-document`'s answer: where the copy landed, and the `file:` URL a recipe's `start.url` points at it with. */
@@ -1112,22 +1118,24 @@ function escapeAttribute(value) {
1112
1118
  * @param input - The input recipe; only `mode` and the first `start` point are used.
1113
1119
  * @param stepPath - The step to snapshot after, e.g. `"start"` or `"steps.2"` (`scope-outline`'s path format).
1114
1120
  * @param browser - Browser launch settings for web mode.
1121
+ * @param hooks - The hooks a login bootstrap may call (the ones Studio was started with, issue #150).
1115
1122
  * @returns The rewritten snapshot.
1116
1123
  * @throws Error when the recipe has no start point, or `stepPath` is not `"start"`.
1117
1124
  */
1118
- async function takeSnapshot(input, stepPath, browser) {
1125
+ async function takeSnapshot(input, stepPath, browser, hooks) {
1119
1126
  if (stepPath !== 'start') throw new Error(`takeSnapshot: "${stepPath}" is not supported yet — only "start" (the first start point, before any step runs) is; see this function's doc comment`);
1120
1127
  const point = input.start[0];
1121
1128
  if (point === undefined) throw new Error(`recipe "${input.id}" has no start point`);
1122
- const storageState = await loginState(input, browser);
1129
+ const storageState = await loginState(input, browser, hooks);
1123
1130
  return input.mode === 'web' ? snapshotWeb(point.url, storageState, browser) : snapshotApi(point.url, storageState);
1124
1131
  }
1125
1132
  /** What the recipe's own login leaves behind, so the snapshot shows the page as the crawl sees it (issue #185); nothing when it declares no login. */
1126
- async function loginState(input, browser) {
1133
+ async function loginState(input, browser, hooks) {
1127
1134
  if (input.session === undefined) return undefined;
1128
1135
  let client;
1129
1136
  try {
1130
1137
  return await sessionStateOf(input, {
1138
+ hooks,
1131
1139
  browser: async () => {
1132
1140
  client = await ensureBrowserLaunch(browser, () => BrowserClient.launch(browser));
1133
1141
  return client;
@@ -1996,10 +2004,11 @@ function idOf(content) {
1996
2004
  * @param budget - The sample budget; unset runs the recipe to completion (still capped by its own `limits`).
1997
2005
  * @param callbacks - Where trace lines and records go as the run proceeds.
1998
2006
  * @param browser - Browser launch settings for a web-mode recipe (an executable path override, headless…); the server-wide setting `studio-http.use-case.ts`'s `StudioServerOptions.browser` carries in, e.g. `OPENCRAW_CHROMIUM` in a sandbox with no full Playwright install.
2007
+ * @param plugins - Hooks, access plugins and captcha solvers the person started Studio with (`--hooks`, issue #150); none when it was started without.
1999
2008
  * @returns A handle: `stop` closes the crawler cleanly, `result` resolves when the run ends.
2000
2009
  * @throws RecipeValidationError, RecipeBindingError, Error when the recipe or its output cannot be loaded or bound.
2001
2010
  */
2002
- async function runSample(folder, recipeId, budget, callbacks, browser) {
2011
+ async function runSample(folder, recipeId, budget, callbacks, browser, plugins) {
2003
2012
  const {
2004
2013
  input,
2005
2014
  output
@@ -2014,6 +2023,9 @@ async function runSample(folder, recipeId, budget, callbacks, browser) {
2014
2023
  debug: true,
2015
2024
  sample: budget,
2016
2025
  browser,
2026
+ hooks: plugins?.hooks,
2027
+ accessPlugins: plugins?.accessPlugins,
2028
+ captchaSolvers: plugins?.captchaSolvers,
2017
2029
  onEvent: event => {
2018
2030
  const line = traceLine(event);
2019
2031
  if (line !== undefined) callbacks.onTraceLine(line);
@@ -2039,7 +2051,7 @@ async function runSample(folder, recipeId, budget, callbacks, browser) {
2039
2051
  }
2040
2052
  }
2041
2053
  });
2042
- const result = runToResult(crawler, set, recipeId, records, rejectedRecords, steps);
2054
+ const result = runToResult(crawler, set, recipeId, records, rejectedRecords, steps, plugins);
2043
2055
  return {
2044
2056
  stop: () => crawler.close(),
2045
2057
  result
@@ -2089,7 +2101,7 @@ function trackStep(steps, event) {
2089
2101
  * rejection: nothing awaits `result` but a `.then`, and an unhandled rejection
2090
2102
  * would take the whole Studio server down (issue #148).
2091
2103
  */
2092
- async function runToResult(crawler, set, recipeId, records, rejectedRecords, steps) {
2104
+ async function runToResult(crawler, set, recipeId, records, rejectedRecords, steps, plugins) {
2093
2105
  try {
2094
2106
  const report = await crawler.run(set);
2095
2107
  const recipe = report.recipes[0];
@@ -2113,7 +2125,7 @@ async function runToResult(crawler, set, recipeId, records, rejectedRecords, ste
2113
2125
  rejected: 0,
2114
2126
  duplicates: 0,
2115
2127
  durationMs: 0,
2116
- error: failureMessage(error),
2128
+ error: failureMessage(error, plugins),
2117
2129
  records,
2118
2130
  rejectedRecords,
2119
2131
  // eslint-disable-next-line unicorn/prefer-iterator-to-array -- `.toArray()` needs a `lib` newer than this repo's `es2022` (tsconfig.base.json)
@@ -2123,9 +2135,13 @@ async function runToResult(crawler, set, recipeId, records, rejectedRecords, ste
2123
2135
  await crawler.close();
2124
2136
  }
2125
2137
  }
2126
- /** What a run that could not start reports. A hook is the author's own code, which Studio never loads (issue #150): say so, instead of leaving "unknown hook" to read as a typo. */
2127
- function failureMessage(error) {
2128
- if (error instanceof UnknownHookError) return `${stripVTControlCharacters(error.message)}. Studio does not load hooks, so a recipe that uses one cannot be sample-run here; run it with the cli or the mcp server, or temporarily replace the hook step to preview the rest.`;
2138
+ /** What a run that could not start reports. A hook is the author's own code, which Studio only runs when it was started with `--hooks` (issue #150): say which case this is, instead of leaving "unknown hook" to read as a typo. */
2139
+ function failureMessage(error, plugins) {
2140
+ if (error instanceof UnknownHookError) {
2141
+ const message = stripVTControlCharacters(error.message);
2142
+ if (plugins !== undefined) return `${message}. It is not one of the hooks in ${plugins.source}: ${Object.keys(plugins.hooks).join(', ') || 'none exported'}.`;
2143
+ return `${message}. Studio was started without hooks: restart it with \`opencraw studio --hooks <file>\` (a module you trust; it runs as your code), or temporarily replace the hook step to preview the rest.`;
2144
+ }
2129
2145
  if (error instanceof Error) return stripVTControlCharacters(error.message);
2130
2146
  return stripVTControlCharacters(String(error));
2131
2147
  }
@@ -3854,7 +3870,13 @@ async function handleOpenWorkspace(state, command) {
3854
3870
  if (switched) broadcast(state, {
3855
3871
  type: 'workspace-changed'
3856
3872
  });
3857
- return view;
3873
+ return state.plugins === undefined ? view : {
3874
+ ...view,
3875
+ hooks: {
3876
+ source: state.plugins.source,
3877
+ names: Object.keys(state.plugins.hooks).sort((a, b) => a.localeCompare(b))
3878
+ }
3879
+ };
3858
3880
  }
3859
3881
 
3860
3882
  /**
@@ -4704,7 +4726,7 @@ async function handleRunSample(state, command) {
4704
4726
  scope: rejected.scope
4705
4727
  });
4706
4728
  }
4707
- }, state.browser);
4729
+ }, state.browser, state.plugins);
4708
4730
  state.activeRun = handle;
4709
4731
  void handle.result.then(result => {
4710
4732
  if (state.activeRun === handle) state.activeRun = undefined;
@@ -4866,7 +4888,7 @@ async function handleTakeSnapshot(state, command) {
4866
4888
  const {
4867
4889
  input
4868
4890
  } = await loadRecipePair(state.folder, command.recipeId);
4869
- const snapshot = await takeSnapshot(input, command.path, state.browser);
4891
+ const snapshot = await takeSnapshot(input, command.path, state.browser, state.plugins?.hooks);
4870
4892
  putSnapshot(state.snapshots, command.recipeId, command.path, snapshot);
4871
4893
  return snapshotView(snapshot);
4872
4894
  }
@@ -5045,6 +5067,7 @@ async function startStudioServer(options = {}) {
5045
5067
  const state = createStudioState();
5046
5068
  if (options.initialFolder !== undefined) state.folder = options.initialFolder;
5047
5069
  state.browser = options.browser;
5070
+ state.plugins = options.plugins;
5048
5071
  if (options.recorderProfileDir !== undefined) state.recorderProfileDir = options.recorderProfileDir;
5049
5072
  const server = createServer((request, response) => {
5050
5073
  void handleRequest(request, response, token, state, uiRoot);
@@ -5288,14 +5311,17 @@ function messageOf(error) {
5288
5311
  * interrupted (Ctrl+C).
5289
5312
  *
5290
5313
  * @param argv - Arguments after the program name: an optional recipe folder, `.` when omitted.
5314
+ * @param options - What the caller loaded beforehand: the trusted plugins, if any.
5291
5315
  */
5292
- async function main(argv) {
5316
+ async function main(argv, options = {}) {
5293
5317
  const folder = resolve(argv[0] ?? '.');
5294
5318
  const server = await startStudioServer({
5295
- initialFolder: folder
5319
+ initialFolder: folder,
5320
+ plugins: options.plugins
5296
5321
  });
5297
5322
  process.stdout.write(`OpenCraw Studio: ${server.url}\n`);
5298
5323
  process.stdout.write(`Workspace: ${folder}\n`);
5324
+ if (options.plugins !== undefined) process.stdout.write(`Hooks: ${options.plugins.source} (runs as your code)\n`);
5299
5325
  const shutdown = () => {
5300
5326
  void server.close();
5301
5327
  };
@@ -5303,5 +5329,5 @@ async function main(argv) {
5303
5329
  process.on('SIGTERM', shutdown);
5304
5330
  }
5305
5331
 
5306
- export { deckChartSeriesViewSchema, deckChartViewSchema, deckDocumentViewSchema, deckPreviewCommandSchema, deckPreviewOptionsSchema, deckShapeViewSchema, deckSlideViewSchema, deckTablePreviewMatchSchema, deckTablePreviewViewSchema, deckViewCommandSchema, documentTreeCommandSchema, documentTreeNodeViewSchema, documentTreeViewSchema, domTreeNodeViewSchema, explainWhyCommandSchema, fetchStartPage, fetchStartPageCommandSchema, fieldPickSchema, fieldTraceSchema, gridCellViewSchema, gridMergeViewSchema, gridPreviewCommandSchema, gridPreviewOptionsSchema, gridSheetViewSchema, gridTablePreviewMatchSchema, gridTablePreviewViewSchema, gridViewCommandSchema, importDocument, importDocumentCommandSchema, importDocumentViewSchema, inferSelectorCommandSchema, inferSelectorViewSchema, inspectPageCommandSchema, inspectViewSchema, loadRecipePair, main, missingWhyTargetSchema, observedResponseSchema, openWorkspace, openWorkspaceCommandSchema, outlineBracketSchema, outlineCardSchema, outlineNodeSchema, outlineViewSchema, pageDataFindingSchema, pdfCellViewSchema, pdfDocumentViewSchema, pdfPageViewSchema, pdfRowViewSchema, pdfViewCommandSchema, recipeIssueSchema, recipeListingSchema, recordEventSchema, recordRejectedEventSchema, recordingCardEventSchema, recordingNoteEventSchema, recordingStoppedEventSchema, regionPreviewCommandSchema, regionPreviewMatchSchema, regionPreviewViewSchema, rejectedWhyTargetSchema, responsesSeenCommandSchema, responsesSeenViewSchema, runFinishedEventSchema, runSample, runSampleCommandSchema, sampleBudgetSchema, sampleRunRecordSchema, sampleRunViewSchema, saveOutlineCommandSchema, saveRecipe, saveRecipeCommandSchema, sentencePartSchema, snapshotViewSchema, startPageViewSchema, startRecordingCommandSchema, startStudioServer, stopRecordingCommandSchema, stopRunCommandSchema, stoppedBySchema, studioCommandSchema, studioEventSchema, tablePreviewBandSchema, tablePreviewCommandSchema, tablePreviewMatchSchema, tablePreviewOptionsSchema, tablePreviewTableSchema, tablePreviewViewSchema, takeSnapshotCommandSchema, traceLineEventSchema, verifySelectorCommandSchema, verifySelectorViewSchema, whyTargetSchema, whyViewSchema, workbookDocumentViewSchema, workspaceChangedEventSchema, workspaceViewSchema };
5332
+ export { deckChartSeriesViewSchema, deckChartViewSchema, deckDocumentViewSchema, deckPreviewCommandSchema, deckPreviewOptionsSchema, deckShapeViewSchema, deckSlideViewSchema, deckTablePreviewMatchSchema, deckTablePreviewViewSchema, deckViewCommandSchema, documentTreeCommandSchema, documentTreeNodeViewSchema, documentTreeViewSchema, domTreeNodeViewSchema, explainWhyCommandSchema, fetchStartPage, fetchStartPageCommandSchema, fieldPickSchema, fieldTraceSchema, gridCellViewSchema, gridMergeViewSchema, gridPreviewCommandSchema, gridPreviewOptionsSchema, gridSheetViewSchema, gridTablePreviewMatchSchema, gridTablePreviewViewSchema, gridViewCommandSchema, importDocument, importDocumentCommandSchema, importDocumentViewSchema, inferSelectorCommandSchema, inferSelectorViewSchema, inspectPageCommandSchema, inspectViewSchema, loadRecipePair, loadedHooksSchema, main, missingWhyTargetSchema, observedResponseSchema, openWorkspace, openWorkspaceCommandSchema, outlineBracketSchema, outlineCardSchema, outlineNodeSchema, outlineViewSchema, pageDataFindingSchema, pdfCellViewSchema, pdfDocumentViewSchema, pdfPageViewSchema, pdfRowViewSchema, pdfViewCommandSchema, recipeIssueSchema, recipeListingSchema, recordEventSchema, recordRejectedEventSchema, recordingCardEventSchema, recordingNoteEventSchema, recordingStoppedEventSchema, regionPreviewCommandSchema, regionPreviewMatchSchema, regionPreviewViewSchema, rejectedWhyTargetSchema, responsesSeenCommandSchema, responsesSeenViewSchema, runFinishedEventSchema, runSample, runSampleCommandSchema, sampleBudgetSchema, sampleRunRecordSchema, sampleRunViewSchema, saveOutlineCommandSchema, saveRecipe, saveRecipeCommandSchema, sentencePartSchema, snapshotViewSchema, startPageViewSchema, startRecordingCommandSchema, startStudioServer, stopRecordingCommandSchema, stopRunCommandSchema, stoppedBySchema, studioCommandSchema, studioEventSchema, tablePreviewBandSchema, tablePreviewCommandSchema, tablePreviewMatchSchema, tablePreviewOptionsSchema, tablePreviewTableSchema, tablePreviewViewSchema, takeSnapshotCommandSchema, traceLineEventSchema, verifySelectorCommandSchema, verifySelectorViewSchema, whyTargetSchema, whyViewSchema, workbookDocumentViewSchema, workspaceChangedEventSchema, workspaceViewSchema };
5307
5333
  //# sourceMappingURL=index.esm.js.map
@@ -1,4 +1,6 @@
1
1
  export { main } from './main.js';
2
+ export type { StudioMainOptions } from './main.js';
3
+ export type { TrustedPlugins } from './trusted-plugins/index.js';
2
4
  export { startStudioServer } from './studio-server/index.js';
3
5
  export type { StudioServer, StudioServerOptions } from './studio-server/index.js';
4
6
  export { openWorkspace, saveRecipe, importDocument } from './recipe-workspace/index.js';
@@ -7,6 +9,6 @@ export { runSample, loadRecipePair } from './sample-run/index.js';
7
9
  export type { RecipePair, SampleRunCallbacks, SampleRunHandle, SampleRunRecord, SampleRunRejected, SampleRunResult, SampleStepSummary, SampleStoppedBy } from './sample-run/index.js';
8
10
  export { fetchStartPage } from './page-snapshot/index.js';
9
11
  export type { WhyFacts, WhyStepFact } from './explain-why/index.js';
10
- export { sampleBudgetSchema, openWorkspaceCommandSchema, importDocumentCommandSchema, runSampleCommandSchema, stopRunCommandSchema, saveRecipeCommandSchema, fetchStartPageCommandSchema, saveOutlineCommandSchema, takeSnapshotCommandSchema, verifySelectorCommandSchema, inferSelectorCommandSchema, missingWhyTargetSchema, rejectedWhyTargetSchema, whyTargetSchema, explainWhyCommandSchema, studioCommandSchema, importDocumentViewSchema, stoppedBySchema, fieldTraceSchema, traceLineEventSchema, recordEventSchema, recordRejectedEventSchema, runFinishedEventSchema, workspaceChangedEventSchema, studioEventSchema, recipeIssueSchema, recipeListingSchema, workspaceViewSchema, sampleRunRecordSchema, sampleRunViewSchema, startPageViewSchema, snapshotViewSchema, verifySelectorViewSchema, fieldPickSchema, inferSelectorViewSchema, sentencePartSchema, outlineCardSchema, outlineBracketSchema, outlineNodeSchema, outlineViewSchema, whyViewSchema, inspectPageCommandSchema, responsesSeenCommandSchema, documentTreeCommandSchema, pdfViewCommandSchema, tablePreviewOptionsSchema, tablePreviewCommandSchema, regionPreviewCommandSchema, regionPreviewMatchSchema, regionPreviewViewSchema, gridViewCommandSchema, gridPreviewOptionsSchema, gridPreviewCommandSchema, deckViewCommandSchema, deckPreviewOptionsSchema, deckPreviewCommandSchema, domTreeNodeViewSchema, pageDataFindingSchema, inspectViewSchema, observedResponseSchema, responsesSeenViewSchema, documentTreeNodeViewSchema, documentTreeViewSchema, pdfCellViewSchema, pdfRowViewSchema, pdfPageViewSchema, pdfDocumentViewSchema, tablePreviewTableSchema, tablePreviewBandSchema, tablePreviewMatchSchema, tablePreviewViewSchema, gridCellViewSchema, gridMergeViewSchema, gridSheetViewSchema, workbookDocumentViewSchema, gridTablePreviewMatchSchema, gridTablePreviewViewSchema, deckShapeViewSchema, deckChartSeriesViewSchema, deckChartViewSchema, deckSlideViewSchema, deckDocumentViewSchema, deckTablePreviewMatchSchema, deckTablePreviewViewSchema, startRecordingCommandSchema, stopRecordingCommandSchema, recordingCardEventSchema, recordingNoteEventSchema, recordingStoppedEventSchema, } from './studio-api/index.js';
11
- export type { SampleBudget, OpenWorkspaceCommand, ImportDocumentCommand, RunSampleCommand, StopRunCommand, SaveRecipeCommand, FetchStartPageCommand, SaveOutlineCommand, TakeSnapshotCommand, VerifySelectorCommand, InferSelectorCommand, MissingWhyTarget, RejectedWhyTarget, WhyTarget, ExplainWhyCommand, InspectPageCommand, ResponsesSeenCommand, DocumentTreeCommand, PdfViewCommand, TablePreviewOptions, TablePreviewCommand, RegionPreviewCommand, GridViewCommand, GridPreviewOptions, GridPreviewCommand, DeckViewCommand, DeckPreviewOptions, DeckPreviewCommand, StudioCommand, ImportDocumentView, RegionPreviewMatchView, RegionPreviewView, StoppedBy, FieldTraceView, TraceLineEvent, RecordEvent, RecordRejectedEvent, RunFinishedEvent, WorkspaceChangedEvent, StudioEvent, RecipeIssue, RecipeListing, WorkspaceView, SampleRunView, StartPageView, SnapshotView, VerifySelectorView, FieldPick, InferSelectorView, SentencePart, OutlineCard, OutlineBracket, OutlineNode, OutlineView, WhyView, DomTreeNodeView, PageDataKind, PageDataFindingView, InspectView, ObservedResponseView, ResponsesSeenView, DocumentTreeNodeView, DocumentTreeView, PdfCellView, PdfRowView, PdfPageView, PdfDocumentView, TablePreviewTableView, TablePreviewBandView, TablePreviewMatchView, TablePreviewView, GridCellView, GridMergeView, GridSheetView, WorkbookDocumentView, GridTablePreviewMatchView, GridTablePreviewView, DeckShapeView, DeckChartSeriesView, DeckChartView, DeckSlideView, DeckDocumentView, DeckTablePreviewMatchView, DeckTablePreviewView, StartRecordingCommand, StopRecordingCommand, RecordingCardEvent, RecordingNoteEvent, RecordingStoppedEvent, } from './studio-api/index.js';
12
+ export { sampleBudgetSchema, openWorkspaceCommandSchema, importDocumentCommandSchema, runSampleCommandSchema, stopRunCommandSchema, saveRecipeCommandSchema, fetchStartPageCommandSchema, saveOutlineCommandSchema, takeSnapshotCommandSchema, verifySelectorCommandSchema, inferSelectorCommandSchema, missingWhyTargetSchema, rejectedWhyTargetSchema, whyTargetSchema, explainWhyCommandSchema, studioCommandSchema, importDocumentViewSchema, stoppedBySchema, fieldTraceSchema, traceLineEventSchema, recordEventSchema, recordRejectedEventSchema, runFinishedEventSchema, workspaceChangedEventSchema, studioEventSchema, loadedHooksSchema, recipeIssueSchema, recipeListingSchema, workspaceViewSchema, sampleRunRecordSchema, sampleRunViewSchema, startPageViewSchema, snapshotViewSchema, verifySelectorViewSchema, fieldPickSchema, inferSelectorViewSchema, sentencePartSchema, outlineCardSchema, outlineBracketSchema, outlineNodeSchema, outlineViewSchema, whyViewSchema, inspectPageCommandSchema, responsesSeenCommandSchema, documentTreeCommandSchema, pdfViewCommandSchema, tablePreviewOptionsSchema, tablePreviewCommandSchema, regionPreviewCommandSchema, regionPreviewMatchSchema, regionPreviewViewSchema, gridViewCommandSchema, gridPreviewOptionsSchema, gridPreviewCommandSchema, deckViewCommandSchema, deckPreviewOptionsSchema, deckPreviewCommandSchema, domTreeNodeViewSchema, pageDataFindingSchema, inspectViewSchema, observedResponseSchema, responsesSeenViewSchema, documentTreeNodeViewSchema, documentTreeViewSchema, pdfCellViewSchema, pdfRowViewSchema, pdfPageViewSchema, pdfDocumentViewSchema, tablePreviewTableSchema, tablePreviewBandSchema, tablePreviewMatchSchema, tablePreviewViewSchema, gridCellViewSchema, gridMergeViewSchema, gridSheetViewSchema, workbookDocumentViewSchema, gridTablePreviewMatchSchema, gridTablePreviewViewSchema, deckShapeViewSchema, deckChartSeriesViewSchema, deckChartViewSchema, deckSlideViewSchema, deckDocumentViewSchema, deckTablePreviewMatchSchema, deckTablePreviewViewSchema, startRecordingCommandSchema, stopRecordingCommandSchema, recordingCardEventSchema, recordingNoteEventSchema, recordingStoppedEventSchema, } from './studio-api/index.js';
13
+ export type { SampleBudget, OpenWorkspaceCommand, ImportDocumentCommand, RunSampleCommand, StopRunCommand, SaveRecipeCommand, FetchStartPageCommand, SaveOutlineCommand, TakeSnapshotCommand, VerifySelectorCommand, InferSelectorCommand, MissingWhyTarget, RejectedWhyTarget, WhyTarget, ExplainWhyCommand, InspectPageCommand, ResponsesSeenCommand, DocumentTreeCommand, PdfViewCommand, TablePreviewOptions, TablePreviewCommand, RegionPreviewCommand, GridViewCommand, GridPreviewOptions, GridPreviewCommand, DeckViewCommand, DeckPreviewOptions, DeckPreviewCommand, StudioCommand, ImportDocumentView, RegionPreviewMatchView, RegionPreviewView, StoppedBy, FieldTraceView, TraceLineEvent, RecordEvent, RecordRejectedEvent, RunFinishedEvent, WorkspaceChangedEvent, StudioEvent, LoadedHooks, RecipeIssue, RecipeListing, WorkspaceView, SampleRunView, StartPageView, SnapshotView, VerifySelectorView, FieldPick, InferSelectorView, SentencePart, OutlineCard, OutlineBracket, OutlineNode, OutlineView, WhyView, DomTreeNodeView, PageDataKind, PageDataFindingView, InspectView, ObservedResponseView, ResponsesSeenView, DocumentTreeNodeView, DocumentTreeView, PdfCellView, PdfRowView, PdfPageView, PdfDocumentView, TablePreviewTableView, TablePreviewBandView, TablePreviewMatchView, TablePreviewView, GridCellView, GridMergeView, GridSheetView, WorkbookDocumentView, GridTablePreviewMatchView, GridTablePreviewView, DeckShapeView, DeckChartSeriesView, DeckChartView, DeckSlideView, DeckDocumentView, DeckTablePreviewMatchView, DeckTablePreviewView, StartRecordingCommand, StopRecordingCommand, RecordingCardEvent, RecordingNoteEvent, RecordingStoppedEvent, } from './studio-api/index.js';
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1,3 +1,9 @@
1
+ import type { TrustedPlugins } from './trusted-plugins/index.js';
2
+ /** What the caller of `main` decided beyond the command-line arguments. */
3
+ export interface StudioMainOptions {
4
+ /** Hooks and plugins loaded from a file the person named at launch (`opencraw studio --hooks <file>`, issue #150). `main` never loads code itself. */
5
+ plugins?: TrustedPlugins;
6
+ }
1
7
  /**
2
8
  * Runs `opencraw-studio`: starts the server, opens `folder` (if given) as
3
9
  * the workspace right away, and prints the URL with the token, the way
@@ -6,6 +12,7 @@
6
12
  * interrupted (Ctrl+C).
7
13
  *
8
14
  * @param argv - Arguments after the program name: an optional recipe folder, `.` when omitted.
15
+ * @param options - What the caller loaded beforehand: the trusted plugins, if any.
9
16
  */
10
- export declare function main(argv: readonly string[]): Promise<void>;
17
+ export declare function main(argv: readonly string[], options?: StudioMainOptions): Promise<void>;
11
18
  //# sourceMappingURL=main.d.ts.map
@@ -1,4 +1,4 @@
1
- import type { BodyKind, BrowserSessionConfig, HttpBody, InputRecipe } from '@opencraw/core';
1
+ import type { BodyKind, BrowserSessionConfig, HookMap, HttpBody, InputRecipe } from '@opencraw/core';
2
2
  export interface SnapshotResult {
3
3
  /** The rewritten document, ready for the content pane's sandboxed iframe. */
4
4
  html: string;
@@ -52,8 +52,9 @@ export interface SnapshotResult {
52
52
  * @param input - The input recipe; only `mode` and the first `start` point are used.
53
53
  * @param stepPath - The step to snapshot after, e.g. `"start"` or `"steps.2"` (`scope-outline`'s path format).
54
54
  * @param browser - Browser launch settings for web mode.
55
+ * @param hooks - The hooks a login bootstrap may call (the ones Studio was started with, issue #150).
55
56
  * @returns The rewritten snapshot.
56
57
  * @throws Error when the recipe has no start point, or `stepPath` is not `"start"`.
57
58
  */
58
- export declare function takeSnapshot(input: InputRecipe, stepPath: string, browser?: BrowserSessionConfig): Promise<SnapshotResult>;
59
+ export declare function takeSnapshot(input: InputRecipe, stepPath: string, browser?: BrowserSessionConfig, hooks?: HookMap): Promise<SnapshotResult>;
59
60
  //# sourceMappingURL=take-snapshot.use-case.d.ts.map
@@ -1,5 +1,6 @@
1
1
  import type { BrowserSessionConfig } from '@opencraw/core';
2
2
  import type { SampleBudget } from '../studio-api/index.js';
3
+ import type { TrustedPlugins } from '../trusted-plugins/index.js';
3
4
  import type { SampleRunRecord, SampleRunRejected, SampleRunResult } from './sample-run-record.contract.js';
4
5
  /** Where trace lines and records go as a sample run proceeds. */
5
6
  export interface SampleRunCallbacks {
@@ -31,8 +32,9 @@ export interface SampleRunHandle {
31
32
  * @param budget - The sample budget; unset runs the recipe to completion (still capped by its own `limits`).
32
33
  * @param callbacks - Where trace lines and records go as the run proceeds.
33
34
  * @param browser - Browser launch settings for a web-mode recipe (an executable path override, headless…); the server-wide setting `studio-http.use-case.ts`'s `StudioServerOptions.browser` carries in, e.g. `OPENCRAW_CHROMIUM` in a sandbox with no full Playwright install.
35
+ * @param plugins - Hooks, access plugins and captcha solvers the person started Studio with (`--hooks`, issue #150); none when it was started without.
34
36
  * @returns A handle: `stop` closes the crawler cleanly, `result` resolves when the run ends.
35
37
  * @throws RecipeValidationError, RecipeBindingError, Error when the recipe or its output cannot be loaded or bound.
36
38
  */
37
- export declare function runSample(folder: string, recipeId: string, budget: SampleBudget | undefined, callbacks: SampleRunCallbacks, browser?: BrowserSessionConfig): Promise<SampleRunHandle>;
39
+ export declare function runSample(folder: string, recipeId: string, budget: SampleBudget | undefined, callbacks: SampleRunCallbacks, browser?: BrowserSessionConfig, plugins?: TrustedPlugins): Promise<SampleRunHandle>;
38
40
  //# sourceMappingURL=run-sample.use-case.d.ts.map
@@ -8,8 +8,8 @@ export { fieldPickSchema, inferSelectorViewSchema } from './infer-selector-view.
8
8
  export type { FieldPick, InferSelectorView } from './infer-selector-view.contract.js';
9
9
  export { stoppedBySchema, fieldTraceSchema, traceLineEventSchema, recordEventSchema, recordRejectedEventSchema, runFinishedEventSchema, workspaceChangedEventSchema, recordingCardEventSchema, recordingNoteEventSchema, recordingStoppedEventSchema, studioEventSchema } from './event.contract.js';
10
10
  export type { StoppedBy, FieldTraceView, TraceLineEvent, RecordEvent, RecordRejectedEvent, RunFinishedEvent, WorkspaceChangedEvent, RecordingCardEvent, RecordingNoteEvent, RecordingStoppedEvent, StudioEvent } from './event.contract.js';
11
- export { recipeIssueSchema, recipeListingSchema, workspaceViewSchema } from './workspace-view.contract.js';
12
- export type { RecipeIssue, RecipeListing, WorkspaceView } from './workspace-view.contract.js';
11
+ export { loadedHooksSchema, recipeIssueSchema, recipeListingSchema, workspaceViewSchema } from './workspace-view.contract.js';
12
+ export type { LoadedHooks, RecipeIssue, RecipeListing, WorkspaceView } from './workspace-view.contract.js';
13
13
  export { importDocumentViewSchema } from './import-document-view.contract.js';
14
14
  export type { ImportDocumentView } from './import-document-view.contract.js';
15
15
  export { sampleRunRecordSchema, sampleRunViewSchema } from './sample-run-view.contract.js';
@@ -28,7 +28,12 @@ export declare const recipeListingSchema: z.ZodObject<{
28
28
  text: z.ZodString;
29
29
  outline: z.ZodOptional<z.ZodType<import("./outline-view.contract").OutlineView, unknown, z.core.$ZodTypeInternals<import("./outline-view.contract").OutlineView, unknown>>>;
30
30
  }, z.core.$strip>;
31
- /** What `open-workspace` answers with: every recipe file directly inside the folder. */
31
+ /** The hooks Studio was started with (`opencraw studio --hooks <file>`, issue #150): where they came from and what they are called, for the warning bar and the hook-name suggestions. */
32
+ export declare const loadedHooksSchema: z.ZodObject<{
33
+ source: z.ZodString;
34
+ names: z.ZodArray<z.ZodString>;
35
+ }, z.core.$strip>;
36
+ /** What `open-workspace` answers with: every recipe file directly inside the folder, and the hooks Studio runs them with, if any. */
32
37
  export declare const workspaceViewSchema: z.ZodObject<{
33
38
  folder: z.ZodString;
34
39
  recipes: z.ZodArray<z.ZodObject<{
@@ -50,8 +55,13 @@ export declare const workspaceViewSchema: z.ZodObject<{
50
55
  text: z.ZodString;
51
56
  outline: z.ZodOptional<z.ZodType<import("./outline-view.contract").OutlineView, unknown, z.core.$ZodTypeInternals<import("./outline-view.contract").OutlineView, unknown>>>;
52
57
  }, z.core.$strip>>;
58
+ hooks: z.ZodOptional<z.ZodObject<{
59
+ source: z.ZodString;
60
+ names: z.ZodArray<z.ZodString>;
61
+ }, z.core.$strip>>;
53
62
  }, z.core.$strip>;
54
63
  export type RecipeIssue = z.infer<typeof recipeIssueSchema>;
55
64
  export type RecipeListing = z.infer<typeof recipeListingSchema>;
65
+ export type LoadedHooks = z.infer<typeof loadedHooksSchema>;
56
66
  export type WorkspaceView = z.infer<typeof workspaceViewSchema>;
57
67
  //# sourceMappingURL=workspace-view.contract.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import type { BrowserSessionConfig } from '@opencraw/core';
2
+ import type { TrustedPlugins } from '../trusted-plugins/index.js';
2
3
  export interface StudioServerOptions {
3
4
  /** Where the built UI lives; default: `dist/ui` next to the running server code. */
4
5
  uiRoot?: string;
@@ -14,6 +15,8 @@ export interface StudioServerOptions {
14
15
  initialFolder?: string;
15
16
  /** Browser launch settings every web-mode command shares (`take-snapshot`, `verify-selector`, `run-sample`, `start-recording`); an executable path override (e.g. `OPENCRAW_CHROMIUM`, read by the caller — the server itself has no opinion on env vars) for a sandbox with no full Playwright install. Default: Playwright's own bundled browser. `start-recording` always forces `headless: false` regardless of what this sets. */
16
17
  browser?: BrowserSessionConfig;
18
+ /** Hooks, access plugins and captcha solvers to run recipes with, loaded by the caller from a file the person named at launch (`opencraw studio --hooks`, issue #150). The server never loads code itself and no request can set this. Default: none. */
19
+ plugins?: TrustedPlugins;
17
20
  /** Where the studio's own recorder profile lives (issue #95); default: a fixed directory under the OS temp folder, never a crawl's own profile directory, never the person's default browser. */
18
21
  recorderProfileDir?: string;
19
22
  }
@@ -3,6 +3,7 @@ import type { RecorderSessionHandle } from '../flow-recording/index.js';
3
3
  import type { SnapshotCache } from '../page-snapshot/index.js';
4
4
  import type { LastRunCache, SampleRunHandle } from '../sample-run/index.js';
5
5
  import type { StudioEvent } from '../studio-api/index.js';
6
+ import type { TrustedPlugins } from '../trusted-plugins/index.js';
6
7
  import type { WsConnection } from './websocket.client.js';
7
8
  /** The server's mutable state: the opened folder, the run in progress (if any), the recording in progress (if any, issue #95), the connected event sockets, the per-recipe snapshot cache `take-snapshot`/`verify-selector`/`infer-selector` share, each recipe's last finished sample run (`explain-why`, issue #92), the browser launch settings every web-mode command (`take-snapshot`, `verify-selector`, `run-sample`, `start-recording`) shares, and where the studio's own recorder profile lives. */
8
9
  export interface StudioState {
@@ -16,6 +17,8 @@ export interface StudioState {
16
17
  lastRuns: LastRunCache;
17
18
  /** Set once at server start (`StudioServerOptions.browser`); every web-mode command reads it from here rather than each accepting its own. */
18
19
  browser?: BrowserSessionConfig;
20
+ /** Set once at server start (`StudioServerOptions.plugins`): the hooks and plugins the person started Studio with (issue #150). Never set by a request. */
21
+ plugins?: TrustedPlugins;
19
22
  /** Set once at server start (`StudioServerOptions.recorderProfileDir`), else `defaultRecorderProfileDir()`. */
20
23
  recorderProfileDir: string;
21
24
  }
@@ -0,0 +1,2 @@
1
+ export type { TrustedPlugins } from './trusted-plugins.contract.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,14 @@
1
+ import type { AccessPlugin, CaptchaSolver, HookMap } from '@opencraw/core';
2
+ /**
3
+ * Code the person who started Studio chose to run (`opencraw studio --hooks <file>`, issue #150): the
4
+ * hooks, access plugins and captcha solvers a recipe names. It is loaded once at launch, never at a
5
+ * recipe's or a browser request's say-so, so it has the trust of the command line it came from.
6
+ */
7
+ export interface TrustedPlugins {
8
+ /** The file it was loaded from, shown to the person in the UI and in errors. */
9
+ source: string;
10
+ hooks: HookMap;
11
+ accessPlugins?: AccessPlugin[];
12
+ captchaSolvers?: CaptchaSolver[];
13
+ }
14
+ //# sourceMappingURL=trusted-plugins.contract.d.ts.map