@opencraw/studio 0.0.18 → 0.0.20

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 (116) hide show
  1. package/README.md +3 -3
  2. package/dist/browser-provisioning/ensure-browser-launch.use-case.d.ts +12 -0
  3. package/dist/browser-provisioning/index.d.ts +2 -0
  4. package/dist/browser-provisioning/install-chromium.use-case.d.ts +2 -0
  5. package/dist/browser-provisioning/missing-browser.policy.d.ts +3 -0
  6. package/dist/document-view/deck-view.mapper.d.ts +70 -0
  7. package/dist/document-view/index.d.ts +13 -0
  8. package/dist/document-view/pdf-view.mapper.d.ts +47 -0
  9. package/dist/document-view/region-preview.use-case.d.ts +30 -0
  10. package/dist/document-view/table-preview.use-case.d.ts +152 -0
  11. package/dist/document-view/tree-view.mapper.d.ts +47 -0
  12. package/dist/document-view/workbook-view.mapper.d.ts +51 -0
  13. package/dist/explain-why/index.d.ts +5 -0
  14. package/dist/explain-why/item-hint.algorithm.d.ts +13 -0
  15. package/dist/explain-why/why-sentence.mapper.d.ts +48 -0
  16. package/dist/explain-why/why.use-case.d.ts +26 -0
  17. package/dist/flow-recording/action-to-step.mapper.d.ts +16 -0
  18. package/dist/flow-recording/index.d.ts +13 -0
  19. package/dist/flow-recording/next-link.policy.d.ts +27 -0
  20. package/dist/flow-recording/recorded-action.contract.d.ts +114 -0
  21. package/dist/flow-recording/recorder-script.client.d.ts +48 -0
  22. package/dist/flow-recording/recorder-session.use-case.d.ts +67 -0
  23. package/dist/flow-recording/secret-field.policy.d.ts +33 -0
  24. package/dist/flow-recording/wait-insertion.policy.d.ts +26 -0
  25. package/dist/index.d.ts +14 -1
  26. package/dist/main.d.ts +18 -0
  27. package/dist/page-inspector/dom-tree.mapper.d.ts +32 -0
  28. package/dist/page-inspector/index.d.ts +7 -0
  29. package/dist/page-inspector/page-data.algorithm.d.ts +39 -0
  30. package/dist/page-inspector/responses-seen.use-case.d.ts +36 -0
  31. package/dist/page-snapshot/fetch-start-page.use-case.d.ts +20 -0
  32. package/dist/page-snapshot/hidden-marks.algorithm.d.ts +23 -0
  33. package/dist/page-snapshot/index.d.ts +13 -0
  34. package/dist/page-snapshot/invalidate-stale-snapshot.use-case.d.ts +12 -0
  35. package/dist/page-snapshot/pdf-bytes.use-case.d.ts +16 -0
  36. package/dist/page-snapshot/reread-csv.use-case.d.ts +22 -0
  37. package/dist/page-snapshot/rewrite-document.mapper.d.ts +27 -0
  38. package/dist/page-snapshot/snapshot.store.d.ts +14 -0
  39. package/dist/page-snapshot/start-point.policy.d.ts +12 -0
  40. package/dist/page-snapshot/take-snapshot.use-case.d.ts +60 -0
  41. package/dist/recipe-workspace/import-document.use-case.d.ts +22 -0
  42. package/dist/recipe-workspace/index.d.ts +5 -0
  43. package/dist/recipe-workspace/open-workspace.use-case.d.ts +15 -0
  44. package/dist/recipe-workspace/save-recipe.use-case.d.ts +21 -0
  45. package/dist/sample-run/index.d.ts +8 -0
  46. package/dist/sample-run/last-run.store.d.ts +17 -0
  47. package/dist/sample-run/load-recipe-pair.use-case.d.ts +18 -0
  48. package/dist/sample-run/run-sample.use-case.d.ts +40 -0
  49. package/dist/sample-run/sample-run-record.contract.d.ts +48 -0
  50. package/dist/scope-outline/card-sentence.mapper.d.ts +18 -0
  51. package/dist/scope-outline/index.d.ts +8 -0
  52. package/dist/scope-outline/outline-to-recipe.mapper.d.ts +17 -0
  53. package/dist/scope-outline/outline.model.d.ts +57 -0
  54. package/dist/scope-outline/recipe-to-outline.mapper.d.ts +14 -0
  55. package/dist/scope-outline/scope-at-path.algorithm.d.ts +19 -0
  56. package/dist/selector-inference/class-token.policy.d.ts +35 -0
  57. package/dist/selector-inference/dom-path.model.d.ts +73 -0
  58. package/dist/selector-inference/index.d.ts +12 -0
  59. package/dist/selector-inference/list-inference.algorithm.d.ts +43 -0
  60. package/dist/selector-inference/selector-candidates.algorithm.d.ts +22 -0
  61. package/dist/selector-inference/selector-ranking.policy.d.ts +27 -0
  62. package/dist/selector-inference/shadow-dom.error.d.ts +11 -0
  63. package/dist/selector-inference/take-kind.policy.d.ts +12 -0
  64. package/dist/studio-api/command.contract.d.ts +531 -0
  65. package/dist/studio-api/deck-preview-view.contract.d.ts +28 -0
  66. package/dist/studio-api/deck-view.contract.d.ts +127 -0
  67. package/dist/studio-api/document-tree-view.contract.d.ts +26 -0
  68. package/dist/studio-api/event.contract.d.ts +155 -0
  69. package/dist/studio-api/grid-preview-view.contract.d.ts +26 -0
  70. package/dist/studio-api/grid-view.contract.d.ts +75 -0
  71. package/dist/studio-api/import-document-view.contract.d.ts +8 -0
  72. package/dist/studio-api/index.d.ts +43 -0
  73. package/dist/studio-api/infer-selector-view.contract.d.ts +68 -0
  74. package/dist/studio-api/inspect-view.contract.d.ts +62 -0
  75. package/dist/studio-api/outline-view.contract.d.ts +37 -0
  76. package/dist/studio-api/pdf-view.contract.d.ts +66 -0
  77. package/dist/studio-api/region-preview-view.contract.d.ts +53 -0
  78. package/dist/studio-api/responses-seen-view.contract.d.ts +20 -0
  79. package/dist/studio-api/sample-run-view.contract.d.ts +28 -0
  80. package/dist/studio-api/snapshot-view.contract.d.ts +30 -0
  81. package/dist/studio-api/start-page-view.contract.d.ts +7 -0
  82. package/dist/studio-api/table-preview-view.contract.d.ts +65 -0
  83. package/dist/studio-api/verify-selector-view.contract.d.ts +18 -0
  84. package/dist/studio-api/why-view.contract.d.ts +16 -0
  85. package/dist/studio-api/workspace-view.contract.d.ts +67 -0
  86. package/dist/studio-server/access-token.policy.d.ts +26 -0
  87. package/dist/studio-server/deck-preview.handler.d.ts +17 -0
  88. package/dist/studio-server/deck-view.handler.d.ts +15 -0
  89. package/dist/studio-server/document-tree.handler.d.ts +14 -0
  90. package/dist/studio-server/explain-why.handler.d.ts +14 -0
  91. package/dist/studio-server/fetch-start-page.handler.d.ts +14 -0
  92. package/dist/studio-server/grid-preview.handler.d.ts +17 -0
  93. package/dist/studio-server/grid-view.handler.d.ts +20 -0
  94. package/dist/studio-server/import-document.handler.d.ts +14 -0
  95. package/dist/studio-server/index.d.ts +3 -0
  96. package/dist/studio-server/infer-selector.handler.d.ts +18 -0
  97. package/dist/studio-server/inspect-page.handler.d.ts +18 -0
  98. package/dist/studio-server/open-workspace.handler.d.ts +20 -0
  99. package/dist/studio-server/pdf-bytes.handler.d.ts +17 -0
  100. package/dist/studio-server/pdf-view.handler.d.ts +14 -0
  101. package/dist/studio-server/recording.handler.d.ts +36 -0
  102. package/dist/studio-server/region-preview.handler.d.ts +17 -0
  103. package/dist/studio-server/responses-seen.handler.d.ts +16 -0
  104. package/dist/studio-server/run-sample.handler.d.ts +28 -0
  105. package/dist/studio-server/save-outline.handler.d.ts +18 -0
  106. package/dist/studio-server/save-recipe.handler.d.ts +15 -0
  107. package/dist/studio-server/static-file.handler.d.ts +14 -0
  108. package/dist/studio-server/studio-http.use-case.d.ts +40 -0
  109. package/dist/studio-server/table-preview.handler.d.ts +16 -0
  110. package/dist/studio-server/take-snapshot.handler.d.ts +16 -0
  111. package/dist/studio-server/verify-selector.handler.d.ts +18 -0
  112. package/dist/studio-server/websocket.client.d.ts +22 -0
  113. package/dist/studio-server/workspace.store.d.ts +36 -0
  114. package/dist/trusted-plugins/index.d.ts +2 -0
  115. package/dist/trusted-plugins/trusted-plugins.contract.d.ts +14 -0
  116. package/package.json +4 -4
@@ -0,0 +1,114 @@
1
+ import { z } from 'zod';
2
+ /** The kinds of user action the in-page recorder script (`recorder-script.client.ts`) reports. */
3
+ export declare const RECORDED_ACTION_KINDS: readonly ['click', 'fill', 'select', 'keypress', 'scroll'];
4
+ export type RecordedActionKind = typeof RECORDED_ACTION_KINDS[number];
5
+ /** Why a report was refused before it became an action: out of this phase's scope (issue #95). */
6
+ export declare const UNSUPPORTED_REASONS: readonly ['iframe', 'shadow-dom'];
7
+ export type UnsupportedReason = typeof UNSUPPORTED_REASONS[number];
8
+ /**
9
+ * The type/name/id of the form field a `fill`/`select` landed on, exactly as
10
+ * the live DOM reports them — `secret-field.policy.ts`'s only input. Never
11
+ * carries the field's value: that travels separately, on the action itself.
12
+ */
13
+ export declare const recordedFieldSchema: z.ZodObject<{
14
+ type: z.ZodOptional<z.ZodString>;
15
+ name: z.ZodOptional<z.ZodString>;
16
+ id: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strip>;
18
+ export type RecordedField = z.infer<typeof recordedFieldSchema>;
19
+ /** What `next-link.policy.ts` needs off a clicked anchor: never the whole element. */
20
+ export declare const recordedLinkSchema: z.ZodObject<{
21
+ rel: z.ZodOptional<z.ZodString>;
22
+ text: z.ZodOptional<z.ZodString>;
23
+ ariaLabel: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strip>;
25
+ export type RecordedLink = z.infer<typeof recordedLinkSchema>;
26
+ /**
27
+ * The wire shape of one action as `recorder-script.client.ts` reports it,
28
+ * over the Playwright binding `recorder-session.use-case.ts` exposes: the
29
+ * `data-oc-node` id of the element involved (`selector-inference`'s own
30
+ * marker attribute, `@opencraw/core`'s `NODE_ID_ATTRIBUTE`), never a
31
+ * selector — the studio, not the page, decides that (studio plan §3.2,
32
+ * issue #95). Never the field's real value when it might be a secret: the
33
+ * script itself does not know which fields are secret (`secret-field.policy.ts`
34
+ * runs server-side, once a `RecordedField` is known), but nothing here
35
+ * *requires* a value to be typed out either way — `recorder-session.use-case.ts`
36
+ * discards it the moment a secret is detected.
37
+ *
38
+ * `html` is the document's own markup, captured by the script itself at the
39
+ * moment of the event (`document.documentElement.outerHTML`), not fetched
40
+ * again afterwards: a click that navigates can leave the page before a
41
+ * later `page.content()` call would resolve, reading the *next* page's
42
+ * markup instead of the one the click actually happened on. Capturing it
43
+ * synchronously, in the same event the node id is stamped in, means the
44
+ * selector is always resolved against the exact document the action
45
+ * happened on — still "verified against the page" (issue #95), just without
46
+ * the race a second round trip would risk.
47
+ */
48
+ export declare const rawActionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
49
+ kind: z.ZodLiteral<"click">;
50
+ nodeId: z.ZodString;
51
+ html: z.ZodString;
52
+ link: z.ZodOptional<z.ZodObject<{
53
+ rel: z.ZodOptional<z.ZodString>;
54
+ text: z.ZodOptional<z.ZodString>;
55
+ ariaLabel: z.ZodOptional<z.ZodString>;
56
+ }, z.core.$strip>>;
57
+ }, z.core.$strip>, z.ZodObject<{
58
+ kind: z.ZodLiteral<"fill">;
59
+ nodeId: z.ZodString;
60
+ html: z.ZodString;
61
+ value: z.ZodString;
62
+ field: z.ZodOptional<z.ZodObject<{
63
+ type: z.ZodOptional<z.ZodString>;
64
+ name: z.ZodOptional<z.ZodString>;
65
+ id: z.ZodOptional<z.ZodString>;
66
+ }, z.core.$strip>>;
67
+ }, z.core.$strip>, z.ZodObject<{
68
+ kind: z.ZodLiteral<"select">;
69
+ nodeId: z.ZodString;
70
+ html: z.ZodString;
71
+ value: z.ZodString;
72
+ field: z.ZodOptional<z.ZodObject<{
73
+ type: z.ZodOptional<z.ZodString>;
74
+ name: z.ZodOptional<z.ZodString>;
75
+ id: z.ZodOptional<z.ZodString>;
76
+ }, z.core.$strip>>;
77
+ }, z.core.$strip>, z.ZodObject<{
78
+ kind: z.ZodLiteral<"keypress">;
79
+ nodeId: z.ZodOptional<z.ZodString>;
80
+ html: z.ZodOptional<z.ZodString>;
81
+ key: z.ZodString;
82
+ }, z.core.$strip>, z.ZodObject<{
83
+ kind: z.ZodLiteral<"scroll">;
84
+ to: z.ZodLiteral<"bottom">;
85
+ }, z.core.$strip>, z.ZodObject<{
86
+ kind: z.ZodLiteral<"unsupported">;
87
+ reason: z.ZodEnum<{
88
+ iframe: "iframe";
89
+ "shadow-dom": "shadow-dom";
90
+ }>;
91
+ }, z.core.$strip>], "kind">;
92
+ export type RawAction = z.infer<typeof rawActionSchema>;
93
+ /**
94
+ * One action once `recorder-session.use-case.ts` has resolved it against the
95
+ * live page: `selector` comes from the phase 2 generator
96
+ * (`selector-inference`'s `candidatesFor`/`rankCandidates`), verified
97
+ * against the page it was recorded on, per issue #95. `value` already holds
98
+ * a `{{env.NAME}}` placeholder, never a real secret, once `secret-field.policy.ts`
99
+ * has flagged the field. `navigated` is set when the action's page changed
100
+ * (a click or a key press that submitted a form/followed a link).
101
+ */
102
+ export interface ResolvedAction {
103
+ kind: RecordedActionKind;
104
+ selector?: string;
105
+ value?: string;
106
+ key?: string;
107
+ field?: RecordedField;
108
+ link?: RecordedLink;
109
+ navigated?: {
110
+ url: string;
111
+ status?: number;
112
+ };
113
+ }
114
+ //# sourceMappingURL=recorded-action.contract.d.ts.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The in-page script `recorder-session.use-case.ts` installs on every page
3
+ * of the studio's own headed browser window (`context.addInitScript`),
4
+ * reporting the person's actions to the binding it also exposes on the
5
+ * context (`context.exposeBinding`) — issue #95's "a script injected into
6
+ * every page ... reports the user's actions: click, type, select, key
7
+ * press, scroll".
8
+ *
9
+ * Kept as a plain string, not a TypeScript function passed to
10
+ * `page.evaluate`/`addInitScript`, for the same reason as
11
+ * `page-snapshot/hidden-marks.algorithm.ts`'s `hiddenMarksScript`: it
12
+ * references `window`/`document` as globals, which `AGENTS.md`'s "things
13
+ * that bit before" and the repo's `isolated-functions` lint rule forbid for
14
+ * an in-page TypeScript function.
15
+ *
16
+ * What it reports, and what it deliberately does not:
17
+ *
18
+ * - **click**: the nearest clickable ancestor (`a`, `button`,
19
+ * `input[type=submit|button]`) of the element clicked, or the element
20
+ * itself; for an `<a>`, also its `rel`, text and `aria-label` —
21
+ * `next-link.policy.ts`'s only input.
22
+ * - **fill**: on `blur` of a text-like input/textarea whose value changed
23
+ * since it was focused (never on every keystroke) — the field's `type`,
24
+ * `name` and `id`, and the value *as typed*; whether that value is a
25
+ * secret, and what replaces it, is `secret-field.policy.ts`'s call,
26
+ * server-side, not this script's.
27
+ * - **select**: on `change` of a `<select>`.
28
+ * - **keypress**: `Enter` only (issue #95's own example, "Press Enter");
29
+ * every other key is noise a recipe step has no shape for.
30
+ * - **scroll**: once per "scroll session" (debounced), when the page has
31
+ * been scrolled within `NEAR_BOTTOM_PX` of its bottom.
32
+ * - **unsupported**: once, the first time an event's target sits inside a
33
+ * shadow root, or this script runs in a frame that is not the top window
34
+ * (an iframe) — issue #95's explicit out-of-scope cases, reported instead
35
+ * of attempted.
36
+ *
37
+ * Every reported element is marked with `attribute` (`data-oc-node` by
38
+ * default, `@opencraw/core`'s `NODE_ID_ATTRIBUTE`) if it does not already
39
+ * carry one, the same attribute `selector-inference`'s `pathToNode` reads —
40
+ * so `recorder-session.use-case.ts` can turn a report straight into a
41
+ * verified selector with the phase 2 generator, never inventing its own.
42
+ *
43
+ * @param bindingName - The name Playwright's `exposeBinding` gave the reporting function (`window[bindingName]`).
44
+ * @param attribute - The marker attribute; defaults to `NODE_ID_ATTRIBUTE`.
45
+ * @returns A self-invoking script, ready for `context.addInitScript({ content: recorderScript(...) })`.
46
+ */
47
+ export declare function recorderScript(bindingName: string, attribute?: string): string;
48
+ //# sourceMappingURL=recorder-script.client.d.ts.map
@@ -0,0 +1,67 @@
1
+ import type { Page } from 'playwright';
2
+ import type { BrowserSessionConfig } from '@opencraw/core';
3
+ import type { OutlineNode } from '../studio-api';
4
+ export interface RecorderNote {
5
+ kind: 'next-link' | 'unsupported' | 'info';
6
+ message: string;
7
+ }
8
+ /** Where recorded actions and notices go as a recording proceeds. */
9
+ export interface RecorderCallbacks {
10
+ onCard: (node: OutlineNode, secret: boolean) => void;
11
+ onNote: (note: RecorderNote) => void;
12
+ }
13
+ export interface RecorderSessionOptions {
14
+ /** The page the headed window opens on. */
15
+ startUrl: string;
16
+ /** Where the studio's own recorder profiles live — see `BrowserProfiles`; never the folder a crawl's own `session.browserProfile` uses. */
17
+ profileDir: string;
18
+ /** Browser launch settings; `headless` is always forced `false` — a recording is, by definition, a window the person watches and drives. */
19
+ browser?: BrowserSessionConfig;
20
+ }
21
+ /**
22
+ * A recording in progress: `stop` closes the window and hands back every
23
+ * step recorded, in order. `page` is the window's own live Playwright page
24
+ * — public the same way `BrowserSession.page` already is, for a caller (a
25
+ * future embedded view, this phase's own e2e test driving the window "as
26
+ * the person would") that needs to reach the live window itself, not just
27
+ * the reported actions.
28
+ */
29
+ export interface RecorderSessionHandle {
30
+ page: Page;
31
+ stop: () => Promise<{
32
+ steps: Record<string, unknown>[];
33
+ }>;
34
+ }
35
+ /**
36
+ * Opens the headed browser window a flow is recorded in (issue #95, studio
37
+ * plan §3.1's last paragraph / phase 6): a Playwright persistent context, in
38
+ * the studio's own profile (`BrowserProfiles`, `headless: false` — the only
39
+ * precedent this codebase already has for a headed launch,
40
+ * `packages/core/src/browser-session/browser-profile.store.ts`), with
41
+ * `recorder-script.client.ts` installed on every page
42
+ * (`context.addInitScript`) and reporting through a context-wide binding
43
+ * (`context.exposeBinding`, so a page opened mid-recording — a link with
44
+ * `target=_blank`, say — is covered too, not only the first page).
45
+ *
46
+ * Each reported action is resolved into a verified selector
47
+ * (`selector-inference`, against the page's own current markup — issue
48
+ * #95's "verified against the page"), turned into a step
49
+ * (`action-to-step.mapper.ts`), and broadcast as an outline card built by
50
+ * `scope-outline`'s own `recipeToOutline` — the same sentence/bracket logic
51
+ * every other phase's cards already go through, never a second card format.
52
+ * A secret field's value is replaced by its `{{env.NAME}}` placeholder
53
+ * before it reaches a step, a card, or this function's return value: the
54
+ * real value is discarded the instant `secret-field.policy.ts` flags the
55
+ * field, never logged, never kept.
56
+ *
57
+ * Recording inside an iframe or shadow DOM is out of this phase's scope
58
+ * (issue #95): `recorder-script.client.ts` detects both and reports them as
59
+ * `unsupported` notes instead of guessing at a selector that would not
60
+ * verify.
61
+ *
62
+ * @param options - The start URL, the profile directory, and browser launch settings.
63
+ * @param callbacks - Where cards and notices go as they happen.
64
+ * @returns A handle: `stop` closes the window and returns every step recorded.
65
+ */
66
+ export declare function openRecorderSession(options: RecorderSessionOptions, callbacks: RecorderCallbacks): Promise<RecorderSessionHandle>;
67
+ //# sourceMappingURL=recorder-session.use-case.d.ts.map
@@ -0,0 +1,33 @@
1
+ import type { RecordedField } from './recorded-action.contract';
2
+ /**
3
+ * Whether a recorded `fill`/`select` field's typed value is a secret: a
4
+ * `type="password"` input, or a field the person explicitly marked (`marked`,
5
+ * a future "mark as secret" UI action — not built by this phase, but the
6
+ * flag is honoured wherever it comes from), or a name/id matching `token`,
7
+ * `secret` or `api[-_]?key` (issue #95's exact wording).
8
+ *
9
+ * @param field - The field's type/name/id, as reported by `recorder-script.client.ts`.
10
+ * @param marked - The person explicitly marked this field as secret; default `false`.
11
+ * @returns Whether the field's value must become `{{env.NAME}}` instead of the real text.
12
+ */
13
+ export declare function isSecretField(field: RecordedField, marked?: boolean): boolean;
14
+ /**
15
+ * The `{{env.NAME}}` variable name a secret field suggests, from its own
16
+ * name/id (falling back to `PASSWORD` for a bare `type="password"` field
17
+ * with neither): `camelCase`/`kebab-case`/`snake_case` all become
18
+ * `SCREAMING_SNAKE_CASE`, punctuation dropped, so `user-pass`, `userPass`
19
+ * and `user_pass` all suggest `USER_PASS`.
20
+ *
21
+ * @param field - The field's type/name/id.
22
+ * @returns A valid env-var-shaped name (letters, digits, underscores, not starting with a digit).
23
+ */
24
+ export declare function secretEnvName(field: RecordedField): string;
25
+ /**
26
+ * The placeholder a secret field's value becomes in the recorded recipe:
27
+ * never the real text, in the recipe JSON or anywhere the studio logs.
28
+ *
29
+ * @param field - The field's type/name/id.
30
+ * @returns `{{env.NAME}}`.
31
+ */
32
+ export declare function secretPlaceholder(field: RecordedField): string;
33
+ //# sourceMappingURL=secret-field.policy.d.ts.map
@@ -0,0 +1,26 @@
1
+ import type { Step } from '@opencraw/core';
2
+ export type WaitStep = Extract<Step, {
3
+ type: 'wait';
4
+ }>;
5
+ /** What happened right after the previous recorded action, before this one. */
6
+ export interface WaitContext {
7
+ /** The previous action's click/key press changed the page. */
8
+ navigated: boolean;
9
+ /** The page fetched something (XHR/`fetch`) since the previous action, without necessarily navigating. */
10
+ xhr: boolean;
11
+ }
12
+ /**
13
+ * Whether a `Wait for <selector>` step belongs between the action that just
14
+ * happened and the next one (issue #95): after a navigation or an XHR, the
15
+ * recorder inserts a wait for the element the person interacts with next, so
16
+ * a replayed recipe does not race the page's own load. Nothing to wait for
17
+ * without a next selector (a page-level key press, a scroll) — and no
18
+ * navigation or fetch either: a recording of a page that never moves should
19
+ * not fill up with waits nobody asked for.
20
+ *
21
+ * @param context - What happened since the previous action.
22
+ * @param nextSelector - The next action's own resolved selector, when it has one.
23
+ * @returns The wait step to insert before the next action's own step, or `undefined`.
24
+ */
25
+ export declare function insertWaitStep(context: WaitContext, nextSelector: string | undefined): WaitStep | undefined;
26
+ //# sourceMappingURL=wait-insertion.policy.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1 +1,14 @@
1
- export * from "./src/index.js";
1
+ export { main } from './main';
2
+ export type { StudioMainOptions } from './main';
3
+ export type { TrustedPlugins } from './trusted-plugins';
4
+ export { startStudioServer } from './studio-server';
5
+ export type { StudioServer, StudioServerOptions } from './studio-server';
6
+ export { openWorkspace, saveRecipe, importDocument } from './recipe-workspace';
7
+ export type { ImportedDocument } from './recipe-workspace';
8
+ export { runSample, loadRecipePair } from './sample-run';
9
+ export type { RecipePair, SampleRunCallbacks, SampleRunHandle, SampleRunRecord, SampleRunRejected, SampleRunResult, SampleStepSummary, SampleStoppedBy } from './sample-run';
10
+ export { fetchStartPage } from './page-snapshot';
11
+ export type { WhyFacts, WhyStepFact } from './explain-why';
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';
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';
14
+ //# sourceMappingURL=index.d.ts.map
package/dist/main.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { TrustedPlugins } from './trusted-plugins';
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
+ }
7
+ /**
8
+ * Runs `opencraw-studio`: starts the server, opens `folder` (if given) as
9
+ * the workspace right away, and prints the URL with the token, the way
10
+ * `docs/research/recipe-studio.md` §2 shows it: `http://127.0.0.1:<port>/?token=…`.
11
+ * The process stays up (the server keeps the event loop alive) until it is
12
+ * interrupted (Ctrl+C).
13
+ *
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.
16
+ */
17
+ export declare function main(argv: readonly string[], options?: StudioMainOptions): Promise<void>;
18
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1,32 @@
1
+ /** One row of the Inspect panel's DOM tree (studio plan §3.3, issue #93): a snapshot element, or a collapsed run of identical siblings. */
2
+ export interface DomTreeNode {
3
+ /** The snapshot's own `data-oc-node` id — what a pick addresses. Present on every real element; absent only on the synthetic wrapper a collapsed run never needs (a run always keeps its first member's id here). */
4
+ nodeId: string;
5
+ tag: string;
6
+ id?: string;
7
+ classes?: string[];
8
+ /** Every other attribute (the internal `data-oc-node`/`data-oc-hidden` marks stripped). */
9
+ attributes: Record<string, string>;
10
+ /** This element's own text, trimmed and cut to `TEXT_LIMIT`, when it has no element children (mixed element+text content shows only the element children — see this file's `buildNode`). */
11
+ text?: string;
12
+ /** From the snapshot's `data-oc-hidden` mark (`hidden-marks.algorithm.ts`, phase 2). */
13
+ hidden: boolean;
14
+ children: DomTreeNode[];
15
+ /** Set when this row stands for a run of `repeatCount` structurally identical consecutive siblings (same tag, attributes and subtree — ids aside): the issue's `×20`. `repeatNodeIds` carries every collapsed sibling's own id, so a pick still knows every node the row represents. */
16
+ repeatCount?: number;
17
+ repeatNodeIds?: string[];
18
+ }
19
+ /**
20
+ * Builds the Inspect panel's DOM tree from a captured snapshot (studio plan
21
+ * §3.3, issue #93): the same rewritten, marked-up document the content pane's
22
+ * iframe shows (`page-snapshot`'s `take-snapshot.use-case.ts`), so a tree
23
+ * row's `nodeId` addresses exactly the element the iframe would highlight —
24
+ * no separate capture, per issue #93's scope note to reuse phase 2's
25
+ * snapshot rather than recapture.
26
+ *
27
+ * @param snapshotHtml - The cached, rewritten snapshot (`SnapshotResult.html`).
28
+ * @returns The tree's root (the document's `<html>` element).
29
+ * @throws Error when the document has no `<html>` element (should not happen: `rewriteDocument` always produces one).
30
+ */
31
+ export declare function domTree(snapshotHtml: string): DomTreeNode;
32
+ //# sourceMappingURL=dom-tree.mapper.d.ts.map
@@ -0,0 +1,7 @@
1
+ export { domTree } from './dom-tree.mapper';
2
+ export type { DomTreeNode } from './dom-tree.mapper';
3
+ export { pageData } from './page-data.algorithm';
4
+ export type { PageDataFinding, PageDataKind } from './page-data.algorithm';
5
+ export { responsesSeen } from './responses-seen.use-case';
6
+ export type { ObservedResponse } from './responses-seen.use-case';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,39 @@
1
+ export type PageDataKind = 'ld-json' | 'json-script' | 'inline-state' | 'meta' | 'link';
2
+ /** One pickable value in "data in the page" (studio plan §3.3, issue #93): a `<script type="application/ld+json">`/`"application/json">` block, an inline state assignment, a `<meta>`, or a `<link rel>`. */
3
+ export interface PageDataFinding {
4
+ kind: PageDataKind;
5
+ /** What the UI shows for this row: the JSON-LD `@type`, the global name assigned (`__NEXT_DATA__`), or `meta:`/`link:` and its name/rel. */
6
+ label: string;
7
+ /** A selector verified against the real page (never the sanitised snapshot: `ld-json`/`json-script`/`inline-state` live inside a `<script>`, which the snapshot's `rewriteDocument` strips for the sandboxed iframe — see this file's own doc comment). */
8
+ selector: string;
9
+ selectorKind: 'css';
10
+ /** How many elements this selector reaches on the real page — always 1 by construction (`structuralSelector` is a full ancestor path), kept as a field so the UI's "N matches" confidence reads the same as a tree pick's. */
11
+ matches: number;
12
+ /** The parsed value's top-level keys, each pickable as its own `$.<key>` `jsonpath` card — absent when the value is not a JSON object (an array, a scalar, or text that did not parse). */
13
+ keys?: string[];
14
+ /** `meta`/`link` only: which attribute holds the pickable value (`content`/`href`). */
15
+ attribute?: string;
16
+ }
17
+ /**
18
+ * Finds the data-in-the-page findings the Inspect panel lists apart from the
19
+ * DOM tree (studio plan §3.3, issue #93): JSON-LD and `application/json`
20
+ * script blocks, inline state assignments, `<meta>` name/property values and
21
+ * `<link rel>`s — reusing `@opencraw/probe`'s `describeJson` for a found
22
+ * value's shape (its own `find-data.algorithm.ts`/`html-findings.mapper.ts`
23
+ * scan a page's raw text for *reporting*, with no element to point a pick at;
24
+ * this function's own job — locating each finding's element so a pick can
25
+ * reach it — is new).
26
+ *
27
+ * Takes the **raw** captured document, not the display snapshot
28
+ * (`page-snapshot`'s `SnapshotResult.html`): `rewriteDocument` strips every
29
+ * `<script>` for the sandboxed iframe, which would make JSON-LD, inline
30
+ * state and other script-tag data invisible here. `<meta>`/`<link>` survive
31
+ * rewriting untouched, so using the raw document for every kind (rather than
32
+ * mixing two documents) keeps this function simple and its selectors
33
+ * verified against what the engine will actually crawl.
34
+ *
35
+ * @param rawHtml - The document as fetched/rendered, before `rewriteDocument` strips scripts.
36
+ * @returns The findings, in document order.
37
+ */
38
+ export declare function pageData(rawHtml: string): PageDataFinding[];
39
+ //# sourceMappingURL=page-data.algorithm.d.ts.map
@@ -0,0 +1,36 @@
1
+ import type { BrowserSessionConfig, InputRecipe } from '@opencraw/core';
2
+ /** One JSON response the page fetched while it rendered (studio plan §3.3, issue #93): what "responses seen" lists, and what picking one switches the recipe to api mode on. */
3
+ export interface ObservedResponse {
4
+ url: string;
5
+ status: number;
6
+ /** The response body's size in bytes (its UTF-8 text length). */
7
+ size: number;
8
+ /** The top-level shape (`describeJson`'s own `type`: `"object"`, `"array (12) of object"`…), or `"text"` when the body did not parse as JSON despite its content type. */
9
+ shape: string;
10
+ }
11
+ /**
12
+ * Records the JSON responses seen while an input recipe's start page
13
+ * rendered (studio plan §3.3, issue #93): the same technique `packages/cli`'s
14
+ * `probe --browser` uses (`observeBrowserJson`) — render the page, listen for
15
+ * `response` events whose content type is JSON, give it a few seconds to
16
+ * settle. Kept as its own capture, independent of `page-snapshot`'s
17
+ * `take-snapshot.use-case.ts`: that capture reads `page.content()` right
18
+ * after `goto` resolves, with no observation window, and changing its shape
19
+ * to also collect responses was a larger, riskier change to already-shipped,
20
+ * tested code than this phase's budget allowed (see this phase's final
21
+ * report) — so this opens its own short-lived browser session instead of
22
+ * piggy-backing on the cached snapshot.
23
+ *
24
+ * Only `"start"` is supported, mirroring `take-snapshot.use-case.ts`'s own
25
+ * reach; api-mode recipes have no page load to observe, so they always
26
+ * answer with an empty list rather than an error (there is nothing wrong
27
+ * with asking, the answer is just "none").
28
+ *
29
+ * @param input - The input recipe; only `mode` and the first `start` point are used.
30
+ * @param stepPath - The step to observe after, e.g. `"start"`.
31
+ * @param browser - Browser launch settings, shared with `take-snapshot`/`verify-selector`/`run-sample`.
32
+ * @returns The distinct JSON responses observed, at most `RESPONSE_LIMIT`.
33
+ * @throws Error when the recipe has no start point, or `stepPath` is not `"start"`.
34
+ */
35
+ export declare function responsesSeen(input: InputRecipe, stepPath: string, browser?: BrowserSessionConfig): Promise<ObservedResponse[]>;
36
+ //# sourceMappingURL=responses-seen.use-case.d.ts.map
@@ -0,0 +1,20 @@
1
+ import type { BrowserSessionConfig, InputRecipe } from '@opencraw/core';
2
+ /**
3
+ * Fetches an input recipe's start page as the engine would see it: a fresh
4
+ * Playwright page in web mode, core's HTTP client in api mode. Returns plain
5
+ * text: the page's HTML, or a readable rendering of a non-HTML api response.
6
+ * No rewriting, no script stripping, no node ids yet: that is phase 2's
7
+ * `page-snapshot` proper (studio plan, #91). Provisional for phase 0 in two
8
+ * ways, both worth knowing before relying on it: it opens a bare page
9
+ * without running the recipe's own steps first, so a start point behind a
10
+ * `session.bootstrap` login shows what an anonymous visitor sees; and it
11
+ * launches a fresh browser or HTTP context per call, one page then closes
12
+ * it, rather than reusing whatever the last sample run had open.
13
+ *
14
+ * @param input - The input recipe; only `mode` and the first `start` point are used.
15
+ * @param browser - Browser launch settings for web mode (an executable path override, headless…).
16
+ * @returns The page's content as plain text.
17
+ * @throws Error when the recipe has no start point.
18
+ */
19
+ export declare function fetchStartPage(input: InputRecipe, browser?: BrowserSessionConfig): Promise<string>;
20
+ //# sourceMappingURL=fetch-start-page.use-case.d.ts.map
@@ -0,0 +1,23 @@
1
+ /** The attribute `hiddenMarksScript` stamps on an element hidden on the live page. */
2
+ export declare const HIDDEN_ATTRIBUTE = "data-oc-hidden";
3
+ /**
4
+ * The in-page script `take-snapshot.use-case.ts` runs with `page.evaluate`
5
+ * *before* `page.content()`, so a `display: none`/`visibility: hidden`/
6
+ * zero-size element carries `data-oc-hidden="1"` into the captured markup
7
+ * (studio plan §3.1, issue #91) — the only way to know an element was
8
+ * hidden on the live page, since a static parse of the HTML afterwards has
9
+ * no computed style to ask.
10
+ *
11
+ * Kept as a plain string, not a TypeScript function passed to
12
+ * `page.evaluate`, because it references `window`/`document` as globals: `AGENTS.md`'s
13
+ * "things that bit before" calls out that in-page functions must not do
14
+ * that (the repo's `isolated-functions` lint rule), and every existing
15
+ * `page.evaluate` call with real DOM logic in this codebase (see
16
+ * `packages/core/src/captcha/resolve-captcha.use-case.ts`) already uses
17
+ * this same string-template shape.
18
+ *
19
+ * @param attribute - The attribute to stamp; defaults to `HIDDEN_ATTRIBUTE` (parameterised for tests and for a future caller that wants a different name).
20
+ * @returns A self-invoking script, ready for `page.evaluate(hiddenMarksScript())`.
21
+ */
22
+ export declare function hiddenMarksScript(attribute?: string): string;
23
+ //# sourceMappingURL=hidden-marks.algorithm.d.ts.map
@@ -0,0 +1,13 @@
1
+ export { fetchStartPage } from './fetch-start-page.use-case';
2
+ export { takeSnapshot } from './take-snapshot.use-case';
3
+ export type { SnapshotResult } from './take-snapshot.use-case';
4
+ export { rewriteDocument } from './rewrite-document.mapper';
5
+ export type { RewrittenDocument } from './rewrite-document.mapper';
6
+ export { hiddenMarksScript, HIDDEN_ATTRIBUTE } from './hidden-marks.algorithm';
7
+ export { createSnapshotCache, cachedSnapshot, putSnapshot, invalidateRecipe } from './snapshot.store';
8
+ export type { SnapshotCache } from './snapshot.store';
9
+ export { pdfBytes } from './pdf-bytes.use-case';
10
+ export { rereadCsv } from './reread-csv.use-case';
11
+ export type { CsvOverride } from './reread-csv.use-case';
12
+ export { invalidateStaleSnapshot } from './invalidate-stale-snapshot.use-case';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ import type { SnapshotCache } from './snapshot.store';
2
+ /**
3
+ * Drops a recipe's cached snapshots when the edit about to be saved changes
4
+ * its start point (issue #159). Call it before the file is written: it reads
5
+ * the recipe as it is on disk now to compare.
6
+ *
7
+ * @param cache - The workspace's snapshot cache.
8
+ * @param file - The recipe file being saved.
9
+ * @param next - The recipe being saved.
10
+ */
11
+ export declare function invalidateStaleSnapshot(cache: SnapshotCache, file: string, next: unknown): Promise<void>;
12
+ //# sourceMappingURL=invalidate-stale-snapshot.use-case.d.ts.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Fetches a PDF's raw bytes for the PDF canvas's `pdf.js` to render in the
3
+ * browser (studio plan §3.4, issue #94's 5b: "the PDF bytes served by the
4
+ * studio"). `take-snapshot` already read this same document with
5
+ * `@opencraw/core`'s `readPdf` for the cells/rows `document-view` maps, but
6
+ * `HttpClient`/`readPdf` parse the bytes and keep only the result — pdf.js
7
+ * needs the file itself, so this re-fetches it from the same URL a cached
8
+ * snapshot's own `SnapshotResult.baseUrl` gives, the way `HttpClient`'s own
9
+ * `file:` branch (`readLocalFile`) and its HTTP fetch do.
10
+ *
11
+ * @param url - The document's URL — a `file:` URL or an `http(s):` URL.
12
+ * @returns The raw bytes.
13
+ * @throws Error when a `file:` URL cannot be read, or the fetch does not succeed.
14
+ */
15
+ export declare function pdfBytes(url: string): Promise<Uint8Array>;
16
+ //# sourceMappingURL=pdf-bytes.use-case.d.ts.map
@@ -0,0 +1,22 @@
1
+ import type { WorkbookDocument } from '@opencraw/core';
2
+ /** `delimiter`/`encoding` on a `grid-view` request overriding what was auto-detected (issue #94's 5c: "the detected delimiter and encoding shown and overridable"); either, both, or neither. */
3
+ export interface CsvOverride {
4
+ delimiter?: string;
5
+ encoding?: string;
6
+ }
7
+ /**
8
+ * Re-reads a CSV document with an overridden delimiter and/or encoding
9
+ * (studio plan §3.4, issue #94's 5c). `take-snapshot` already read this same
10
+ * document once with auto-detection (`http.client.ts`'s own `csvWorkbook`
11
+ * call); it keeps only the parsed result, not the raw bytes, so re-reading
12
+ * the file/URL is the only way to apply a different choice — the same
13
+ * "the studio re-fetches, the reader keeps no bytes around" tradeoff
14
+ * `pdf-bytes.use-case.ts` documents for pdf.js.
15
+ *
16
+ * @param url - The document's URL — a `file:` URL or an `http(s):` URL (`page-snapshot`'s cached `SnapshotResult.baseUrl`).
17
+ * @param override - The delimiter and/or encoding to force; `HttpClient` still detects whichever one is left out.
18
+ * @returns The freshly read workbook.
19
+ * @throws Error when the URL cannot be read, or it no longer reads back as a workbook.
20
+ */
21
+ export declare function rereadCsv(url: string, override: CsvOverride): Promise<WorkbookDocument>;
22
+ //# sourceMappingURL=reread-csv.use-case.d.ts.map
@@ -0,0 +1,27 @@
1
+ export interface RewrittenDocument {
2
+ /** The document, ready for the sandboxed iframe: absolute URLs, a `<base>`, no `<script>`, forms disabled, `<meta http-equiv="refresh">` stripped, every element carrying a `data-oc-node` id. */
3
+ html: string;
4
+ /** How many elements were stamped with a node id — the same count `page-inspector` (phase 4) and the picker's match counts can be checked against. */
5
+ nodeCount: number;
6
+ }
7
+ /**
8
+ * Rewrites captured HTML into what the content pane's sandboxed iframe shows
9
+ * (studio plan §3.1, issue #91): every URL made absolute against `baseUrl`,
10
+ * a `<base>` injected, every `<script>` removed, forms disabled (`onsubmit`
11
+ * stripped, fields made read-only), `<meta http-equiv="refresh">` stripped
12
+ * (it would otherwise navigate the sandboxed frame on its own), and every
13
+ * element given a stable `data-oc-node` id, in document order, for the
14
+ * picker overlay and `selector-inference` to address specific nodes by.
15
+ *
16
+ * Purely a markup transform: it does not know whether an element is hidden
17
+ * on the live page (`display: none`, `visibility: hidden`, zero size) — in
18
+ * web mode that is `hidden-marks.algorithm.ts`'s job, run against the live
19
+ * page *before* this function ever sees the markup, so a `data-oc-hidden`
20
+ * attribute it wrote just survives serialisation untouched here.
21
+ *
22
+ * @param html - The captured document (`page.content()` in web mode, the fetched body in api mode).
23
+ * @param baseUrl - The page's own URL, for resolving relative links and as the `<base>`.
24
+ * @returns The rewritten document and how many elements it stamped.
25
+ */
26
+ export declare function rewriteDocument(html: string, baseUrl: string): RewrittenDocument;
27
+ //# sourceMappingURL=rewrite-document.mapper.d.ts.map
@@ -0,0 +1,14 @@
1
+ import type { SnapshotResult } from './take-snapshot.use-case';
2
+ /** A cache of the last snapshot taken per step path, so switching the selected step in the Steps outline does not always re-run the recipe (studio plan §3.1, issue #91). One per open recipe: key by `${recipeId}:${path}`. */
3
+ export interface SnapshotCache {
4
+ entries: Map<string, SnapshotResult>;
5
+ }
6
+ /** @returns An empty cache, for a freshly opened workspace. */
7
+ export declare function createSnapshotCache(): SnapshotCache;
8
+ /** @returns The cached snapshot for `recipeId`/`path`, or `undefined` when none was taken yet. */
9
+ export declare function cachedSnapshot(cache: SnapshotCache, recipeId: string, path: string): SnapshotResult | undefined;
10
+ /** Records a freshly taken snapshot, replacing whatever was cached for the same recipe and step path. */
11
+ export declare function putSnapshot(cache: SnapshotCache, recipeId: string, path: string, snapshot: SnapshotResult): void;
12
+ /** Drops every cached snapshot of one recipe — called after a save, since the steps up to any path may now capture something different. */
13
+ export declare function invalidateRecipe(cache: SnapshotCache, recipeId: string): void;
14
+ //# sourceMappingURL=snapshot.store.d.ts.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Whether an edit changes the page a recipe's start snapshot shows (issue
3
+ * #159): its start URLs, mode, session, vars, headers… anything but the steps
4
+ * and mapping that run after it. A pick only adds steps, so it keeps the
5
+ * snapshot already taken instead of fetching the page again.
6
+ *
7
+ * @param before - The recipe as last saved (`undefined` when there was none).
8
+ * @param after - The recipe being saved.
9
+ * @returns `true` when the cached start snapshot may now be out of date.
10
+ */
11
+ export declare function startPointChanged(before: unknown, after: unknown): boolean;
12
+ //# sourceMappingURL=start-point.policy.d.ts.map