@unfenced-ai/sdk 0.1.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.
Files changed (59) hide show
  1. package/LICENSE +30 -0
  2. package/README.md +171 -0
  3. package/dist/client.d.ts +385 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +349 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/credentials.d.ts +14 -0
  8. package/dist/credentials.d.ts.map +1 -0
  9. package/dist/credentials.js +17 -0
  10. package/dist/credentials.js.map +1 -0
  11. package/dist/fetch.d.ts +16 -0
  12. package/dist/fetch.d.ts.map +1 -0
  13. package/dist/fetch.js +387 -0
  14. package/dist/fetch.js.map +1 -0
  15. package/dist/http.d.ts +76 -0
  16. package/dist/http.d.ts.map +1 -0
  17. package/dist/http.js +250 -0
  18. package/dist/http.js.map +1 -0
  19. package/dist/index.d.ts +53 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +41 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/library.d.ts +17 -0
  24. package/dist/library.d.ts.map +1 -0
  25. package/dist/library.js +25 -0
  26. package/dist/library.js.map +1 -0
  27. package/dist/memory.d.ts +13 -0
  28. package/dist/memory.d.ts.map +1 -0
  29. package/dist/memory.js +45 -0
  30. package/dist/memory.js.map +1 -0
  31. package/dist/permissions.d.ts +29 -0
  32. package/dist/permissions.d.ts.map +1 -0
  33. package/dist/permissions.js +69 -0
  34. package/dist/permissions.js.map +1 -0
  35. package/dist/protocol.d.ts +296 -0
  36. package/dist/protocol.d.ts.map +1 -0
  37. package/dist/protocol.js +89 -0
  38. package/dist/protocol.js.map +1 -0
  39. package/dist/session.d.ts +97 -0
  40. package/dist/session.d.ts.map +1 -0
  41. package/dist/session.js +88 -0
  42. package/dist/session.js.map +1 -0
  43. package/dist/sessions.d.ts +131 -0
  44. package/dist/sessions.d.ts.map +1 -0
  45. package/dist/sessions.js +197 -0
  46. package/dist/sessions.js.map +1 -0
  47. package/dist/token-usage.d.ts +11 -0
  48. package/dist/token-usage.d.ts.map +1 -0
  49. package/dist/token-usage.js +34 -0
  50. package/dist/token-usage.js.map +1 -0
  51. package/dist/types.d.ts +1409 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/url-identity.d.ts +8 -0
  56. package/dist/url-identity.d.ts.map +1 -0
  57. package/dist/url-identity.js +18 -0
  58. package/dist/url-identity.js.map +1 -0
  59. package/package.json +44 -0
@@ -0,0 +1,296 @@
1
+ /**
2
+ * The wire, declared once.
3
+ *
4
+ * Every client of the unfenced server needs the same handful of shapes — the
5
+ * cleaned document, the fetch metadata, the outcome envelope — and until this
6
+ * file existed each one declared its own. Three copies of `ExtractedDoc` were in
7
+ * the tree at the same time: `packages/extract/src/types.ts` (the producer, 21
8
+ * fields), this package (8 fields plus `[key: string]: unknown`), and
9
+ * `packages/ui/src/api.ts` (15 fields, hand-typed). They disagreed, and the
10
+ * disagreement was invisible: an index signature makes `doc.markdwn` compile and
11
+ * return `undefined`, and a field the dashboard never declared is a field no
12
+ * dashboard view can render.
13
+ *
14
+ * @unfenced-ai/sdk is the right home for it. It has no runtime dependencies and is
15
+ * meant to keep none, so a browser bundle can carry it; every other client
16
+ * already depends on it; and it is one of the two packages that actually
17
+ * publish, so its types are the ones a stranger receives.
18
+ *
19
+ * WHY THIS FILE IS SEPARATE FROM `index.ts`: this module is pure declaration —
20
+ * no imports, no client, no `fetch`. `packages/ui` may therefore
21
+ * `import type` from it and get the types with nothing to erase, honouring the
22
+ * boundary in docs/ARCHITECTURE.md that the dashboard owns no `@unfenced/*`
23
+ * runtime import. Importing `index.ts` would put the `Unfenced` class in the
24
+ * dashboard's module graph for a type it does not need.
25
+ *
26
+ * THIS IS STILL A MIRROR, and mirrors drift — that is the whole reason this file
27
+ * exists. So it is BOUND rather than trusted: `test/wire-contract.test.ts` reads
28
+ * the producer's own declarations off disk and fails when a field is renamed,
29
+ * dropped or added on either side. See that file for why the binding runs
30
+ * against the source rather than against a live server.
31
+ */
32
+ /** Which payload the server renders as `content`. */
33
+ export type OutputFormat = "markdown" | "json" | "text" | "html";
34
+ /** 1 = plain HTTP, 2 = stealth headless browser, 3 = headed browser. */
35
+ export type Tier = 1 | 2 | 3;
36
+ export interface ContentOmission {
37
+ kind: "hidden-text" | "listing-prose" | "pdf-page-cap" | "settle-timeout" | "byte-cap" | "word-cap" | "character-cap" | "navigation-incomplete";
38
+ amount?: number;
39
+ unit?: "words" | "pages" | "bytes" | "characters";
40
+ }
41
+ export interface LinkRef {
42
+ /** Absolute when the page had a base URL to resolve against, else the raw href. */
43
+ url: string;
44
+ /** Anchor text, whitespace-collapsed. */
45
+ text: string;
46
+ }
47
+ export interface ImageRef {
48
+ src: string;
49
+ alt: string;
50
+ title?: string;
51
+ }
52
+ export type StructuredDataKind = "ld+json" | "next-data" | "initial-state" | "embedded-json";
53
+ export interface StructuredDatum {
54
+ kind: StructuredDataKind;
55
+ /** Where it came from, e.g. `script#__NEXT_DATA__` or `window.__INITIAL_STATE__`. */
56
+ source: string;
57
+ data: unknown;
58
+ }
59
+ /** What kind of other address the page declared for itself. */
60
+ export type AlternateKind = "markdown" | "amp" | "feed" | "canonical" | "print" | "language" | "other";
61
+ export interface Alternate {
62
+ kind: AlternateKind;
63
+ /** Absolute, resolved against the document's base. */
64
+ url: string;
65
+ /** The MIME type the document declared, verbatim, or null. */
66
+ type: string | null;
67
+ title: string | null;
68
+ /** Present on language alternates: "de", "en-GB", "x-default". */
69
+ hreflang: string | null;
70
+ }
71
+ /** How the main content was isolated. Useful for judging a bad extraction. */
72
+ export type ExtractionMethod = "readability" | "heuristic" | "whole-body" | "listing" | "thread" | "plain-text"
73
+ /** A PDF's own text layer. Never OCR: a scan has no text layer to read. */
74
+ | "pdf";
75
+ export type PageType = "article" | "listing" | "thread" | "data" | "feed";
76
+ /**
77
+ * How much to trust that what came back is what the URL is about.
78
+ *
79
+ * `low` does not mean the content is useless — it means check before relying on
80
+ * it. The canonical case is a login wall: the extractor cleanly pulls the
81
+ * suggestions sidebar and reports a tidy result about the wrong thing.
82
+ */
83
+ export interface ContentConfidence {
84
+ level: "high" | "low";
85
+ /** Plain-language reasons, safe to show an agent or a human. */
86
+ reasons: string[];
87
+ }
88
+ /**
89
+ * The cleaned document a fetch returns — the whole of it.
90
+ *
91
+ * Produced by `packages/extract/src/index.ts#extractDoc` and passed to the
92
+ * client untouched: core caps `markdown` and `text` when `maxWords` bites
93
+ * (`packages/core/src/fetch.ts#capRendered`) and the job route sends the result
94
+ * verbatim (`packages/server/src/routes/jobs.ts`, `result: job.result`).
95
+ * Nothing in between adds or removes a field, which is what lets the contract
96
+ * test bind this declaration to the producer's.
97
+ *
98
+ * There is deliberately NO index signature. The previous one made every typo a
99
+ * silent `undefined` on the primary return value of the client library, and it
100
+ * let thirteen real fields go undeclared for as long as nobody noticed.
101
+ */
102
+ export interface ExtractedDoc {
103
+ /** The URL the document was extracted for, or null when none was supplied. */
104
+ url: string | null;
105
+ title: string;
106
+ description: string | null;
107
+ author: string | null;
108
+ /** ISO 8601, normalised from whichever of three sources answered. */
109
+ publishedAt: string | null;
110
+ siteName: string | null;
111
+ lang: string | null;
112
+ dir: "ltr" | "rtl" | null;
113
+ /** Main content as markdown. Always populated. */
114
+ markdown: string;
115
+ /** Main content as plain text. Always populated. */
116
+ text: string;
117
+ /** Cleaned main-content HTML (not the full page). */
118
+ contentHtml: string;
119
+ links: LinkRef[];
120
+ images: ImageRef[];
121
+ structuredData: StructuredDatum[];
122
+ /**
123
+ * Other addresses this page says it has: a markdown twin, an AMP document, a
124
+ * feed, a canonical, a translation. Each is the SITE declaring an
125
+ * equivalence, so following one is a lookup rather than a guess.
126
+ */
127
+ alternates: Alternate[];
128
+ extractionMethod: ExtractionMethod;
129
+ pageType: PageType;
130
+ /** Counted on the extracted text in the page's own script, not on the render. */
131
+ wordCount: number;
132
+ /** Content supplied by the page but not included in the delivered answer. */
133
+ omissions?: ContentOmission[];
134
+ /** Whether the extraction looks like the page's real content. */
135
+ confidence?: ContentConfidence;
136
+ /**
137
+ * The markdown converter threw and this document fell back to raw DOM text:
138
+ * no headings, no links, no tables — the prose, in reading order, and
139
+ * nothing else.
140
+ *
141
+ * On the document rather than only inside the confidence it produced,
142
+ * because the confidence is RE-ASSESSED downstream once a browser tier is
143
+ * known. Declared here because a field the SDK does not declare arrives at a
144
+ * typed caller as nothing: the reason a page came back without its structure
145
+ * would reach the extractor's own return and no customer.
146
+ */
147
+ converterFailed?: boolean;
148
+ /** Populated for listing pages so the caller can see what was detected. */
149
+ listing?: {
150
+ itemCount: number;
151
+ /** Other qualifying result sets on the page that were not rendered. */
152
+ otherSetsFound: number;
153
+ };
154
+ /** Populated for threaded discussion, so a flat render is explainable. */
155
+ thread?: {
156
+ itemCount: number;
157
+ maxDepth: number;
158
+ /** How reply depth was established: DOM nesting, an attribute, or neither. */
159
+ depthSource: "nesting" | "attribute" | "flat";
160
+ };
161
+ }
162
+ export interface TokenEstimate {
163
+ /** Tokens the agent would have burned on the raw HTML. */
164
+ rawHtml: number;
165
+ /** Tokens in the emitted content for the requested format. */
166
+ output: number;
167
+ /** Percentage saved, 0-100, rounded to one decimal. */
168
+ savedPct: number;
169
+ }
170
+ export interface EscalationRecord {
171
+ from: Tier;
172
+ to: Tier;
173
+ reason: string;
174
+ }
175
+ /**
176
+ * What the fetch consumed. Present on every arm including the failures: a fetch
177
+ * that ended in a 403 still ran a browser and still moved bytes.
178
+ */
179
+ export interface Meter {
180
+ /** Response bytes read. Exact at tier 1; see `basis` for the browser tiers. */
181
+ bytesIn: number;
182
+ /** Wall-clock in plain HTTP. */
183
+ httpMs: number;
184
+ /** Wall-clock with a browser up. The expensive second. */
185
+ browserMs: number;
186
+ /** True when any byte went through a paid egress. */
187
+ proxied: boolean;
188
+ /**
189
+ * How much of `bytesIn` was actually observed. `partial` means the total is a
190
+ * floor, not a figure — do not compare it to an invoice as if it were one.
191
+ */
192
+ basis: "measured" | "partial" | "none";
193
+ /** How many responses could not report a size. Zero when `basis` is measured. */
194
+ unsizedResponses: number;
195
+ }
196
+ /** What that consumption is worth, priced from the meter. */
197
+ export interface Cost {
198
+ /** Authoritative. */
199
+ micros: number;
200
+ /** ceil(micros / 10_000). Display only — never compared, never summed. */
201
+ cents: number;
202
+ currency: "USD";
203
+ /** A price computed from a floor is a floor, and says so here. */
204
+ basis: "measured" | "partial" | "estimated";
205
+ rateCardVersion: string;
206
+ breakdown: {
207
+ egressMicros: number;
208
+ browserMicros: number;
209
+ httpMicros: number;
210
+ };
211
+ }
212
+ /**
213
+ * The metadata on a DELIVERED fetch.
214
+ *
215
+ * No index signature, for the same reason `ExtractedDoc` has none: with one,
216
+ * `meta.tokenEstimte` compiled and fourteen real fields stayed undeclared — so
217
+ * every caller that wanted the token saving or the cache flag had to cast.
218
+ */
219
+ export interface FetchMeta {
220
+ meter: Meter;
221
+ cost: Cost;
222
+ tier: Tier;
223
+ renderedJs: boolean;
224
+ /**
225
+ * robots.txt forbade this path and we fetched it anyway — only ever set in
226
+ * `report` mode. On the SUCCESS shape deliberately: a log that records only
227
+ * refusals cannot answer "did you know?".
228
+ */
229
+ robotsDisallowed?: boolean;
230
+ /** The rule that decided it, so the record can be checked rather than trusted. */
231
+ robotsRule?: string;
232
+ finalUrl: string;
233
+ fetchedAt: string;
234
+ status: number | null;
235
+ durationMs: number;
236
+ /** ms spent per stage, e.g. `{ tier1: 380, tier2: 4120, extracting: 46 }`. */
237
+ timings: Record<string, number>;
238
+ tokenEstimate: TokenEstimate;
239
+ extractionMethod: string;
240
+ escalations: EscalationRecord[];
241
+ /** Which tier the domain cache suggested we start at. */
242
+ startedAtTier: Tier;
243
+ /** The locale this fetch actually presented, so a caller need not assume. */
244
+ locale?: string;
245
+ /** True when `maxWords` cut the content. `doc.wordCount` is the full count. */
246
+ contentTruncated?: boolean;
247
+ omissions?: ContentOmission[];
248
+ /** How many words the body held before the cap bit. */
249
+ totalWords?: number;
250
+ /** True when this answer came from a recent identical fetch, not the network. */
251
+ cached?: boolean;
252
+ }
253
+ /**
254
+ * The metadata on a FAILED fetch, which is not `Partial<FetchMeta>`.
255
+ *
256
+ * It carries two fields a success never does — `retryAfterMs` and `retryAfter`,
257
+ * the answer to "when may I try again" — and it omits the ones that only exist
258
+ * once a document was produced. Typing it as a partial success said the
259
+ * schedulable fields did not exist, which is why the MCP layer reads them
260
+ * through `meta?.["retryAfter"]` instead of by name.
261
+ *
262
+ * A type alias rather than an interface, deliberately: an interface has no
263
+ * implicit index signature, so it is not assignable to `Record<string, unknown>`
264
+ * — and `packages/mcp/src/tools.ts#failurePayload` takes exactly that.
265
+ */
266
+ export type FetchFailureMeta = {
267
+ meter?: Meter;
268
+ cost?: Cost;
269
+ durationMs: number;
270
+ timings?: Record<string, number>;
271
+ escalations: EscalationRecord[];
272
+ startedAtTier: Tier;
273
+ finalUrl?: string;
274
+ /** How long until we will contact the site again, as a duration. */
275
+ retryAfterMs?: number;
276
+ /**
277
+ * …and as an ISO instant. Both forms, because a duration is measured from a
278
+ * moment the caller cannot see and so cannot be scheduled against.
279
+ */
280
+ retryAfter?: string;
281
+ robotsDisallowed?: boolean;
282
+ robotsRule?: string;
283
+ };
284
+ /**
285
+ * Every field name on `ExtractedDoc`, as data.
286
+ *
287
+ * The contract test needs the declared field set at RUNTIME to diff it against
288
+ * the producer's source, and a TypeScript interface leaves nothing behind to
289
+ * read. `satisfies` stops the list naming a field that does not exist; the
290
+ * `_DocFieldsAreComplete` alias below stops it omitting one. Between them the
291
+ * list cannot drift from the interface it describes without failing `tsc`.
292
+ */
293
+ export declare const WIRE_DOC_FIELDS: readonly ["url", "title", "description", "author", "publishedAt", "siteName", "lang", "dir", "markdown", "text", "contentHtml", "links", "images", "structuredData", "alternates", "extractionMethod", "pageType", "wordCount", "omissions", "confidence", "converterFailed", "listing", "thread"];
294
+ /** The same, for the delivered-fetch metadata. */
295
+ export declare const WIRE_META_FIELDS: readonly ["meter", "cost", "tier", "renderedJs", "robotsDisallowed", "robotsRule", "finalUrl", "fetchedAt", "status", "durationMs", "timings", "tokenEstimate", "extractionMethod", "escalations", "startedAtTier", "locale", "contentTruncated", "omissions", "totalWords", "cached"];
296
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The wire, declared once.
3
+ *
4
+ * Every client of the unfenced server needs the same handful of shapes — the
5
+ * cleaned document, the fetch metadata, the outcome envelope — and until this
6
+ * file existed each one declared its own. Three copies of `ExtractedDoc` were in
7
+ * the tree at the same time: `packages/extract/src/types.ts` (the producer, 21
8
+ * fields), this package (8 fields plus `[key: string]: unknown`), and
9
+ * `packages/ui/src/api.ts` (15 fields, hand-typed). They disagreed, and the
10
+ * disagreement was invisible: an index signature makes `doc.markdwn` compile and
11
+ * return `undefined`, and a field the dashboard never declared is a field no
12
+ * dashboard view can render.
13
+ *
14
+ * @unfenced-ai/sdk is the right home for it. It has no runtime dependencies and is
15
+ * meant to keep none, so a browser bundle can carry it; every other client
16
+ * already depends on it; and it is one of the two packages that actually
17
+ * publish, so its types are the ones a stranger receives.
18
+ *
19
+ * WHY THIS FILE IS SEPARATE FROM `index.ts`: this module is pure declaration —
20
+ * no imports, no client, no `fetch`. `packages/ui` may therefore
21
+ * `import type` from it and get the types with nothing to erase, honouring the
22
+ * boundary in docs/ARCHITECTURE.md that the dashboard owns no `@unfenced/*`
23
+ * runtime import. Importing `index.ts` would put the `Unfenced` class in the
24
+ * dashboard's module graph for a type it does not need.
25
+ *
26
+ * THIS IS STILL A MIRROR, and mirrors drift — that is the whole reason this file
27
+ * exists. So it is BOUND rather than trusted: `test/wire-contract.test.ts` reads
28
+ * the producer's own declarations off disk and fails when a field is renamed,
29
+ * dropped or added on either side. See that file for why the binding runs
30
+ * against the source rather than against a live server.
31
+ */
32
+ /**
33
+ * Every field name on `ExtractedDoc`, as data.
34
+ *
35
+ * The contract test needs the declared field set at RUNTIME to diff it against
36
+ * the producer's source, and a TypeScript interface leaves nothing behind to
37
+ * read. `satisfies` stops the list naming a field that does not exist; the
38
+ * `_DocFieldsAreComplete` alias below stops it omitting one. Between them the
39
+ * list cannot drift from the interface it describes without failing `tsc`.
40
+ */
41
+ export const WIRE_DOC_FIELDS = [
42
+ "url",
43
+ "title",
44
+ "description",
45
+ "author",
46
+ "publishedAt",
47
+ "siteName",
48
+ "lang",
49
+ "dir",
50
+ "markdown",
51
+ "text",
52
+ "contentHtml",
53
+ "links",
54
+ "images",
55
+ "structuredData",
56
+ "alternates",
57
+ "extractionMethod",
58
+ "pageType",
59
+ "wordCount",
60
+ "omissions",
61
+ "confidence",
62
+ "converterFailed",
63
+ "listing",
64
+ "thread",
65
+ ];
66
+ /** The same, for the delivered-fetch metadata. */
67
+ export const WIRE_META_FIELDS = [
68
+ "meter",
69
+ "cost",
70
+ "tier",
71
+ "renderedJs",
72
+ "robotsDisallowed",
73
+ "robotsRule",
74
+ "finalUrl",
75
+ "fetchedAt",
76
+ "status",
77
+ "durationMs",
78
+ "timings",
79
+ "tokenEstimate",
80
+ "extractionMethod",
81
+ "escalations",
82
+ "startedAtTier",
83
+ "locale",
84
+ "contentTruncated",
85
+ "omissions",
86
+ "totalWords",
87
+ "cached",
88
+ ];
89
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AA+RH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK;IACL,OAAO;IACP,aAAa;IACb,QAAQ;IACR,aAAa;IACb,UAAU;IACV,MAAM;IACN,KAAK;IACL,UAAU;IACV,MAAM;IACN,aAAa;IACb,OAAO;IACP,QAAQ;IACR,gBAAgB;IAChB,YAAY;IACZ,kBAAkB;IAClB,UAAU;IACV,WAAW;IACX,WAAW;IACX,YAAY;IACZ,iBAAiB;IACjB,SAAS;IACT,QAAQ;CAC0C,CAAC;AAErD,kDAAkD;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,OAAO;IACP,MAAM;IACN,MAAM;IACN,YAAY;IACZ,kBAAkB;IAClB,YAAY;IACZ,UAAU;IACV,WAAW;IACX,QAAQ;IACR,YAAY;IACZ,SAAS;IACT,eAAe;IACf,kBAAkB;IAClB,aAAa;IACb,eAAe;IACf,QAAQ;IACR,kBAAkB;IAClB,WAAW;IACX,YAAY;IACZ,QAAQ;CACuC,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The `Session` handle — a thin façade over the live-session methods on the
3
+ * `Unfenced` client. Moved out of the single-file entry unchanged; every method
4
+ * still delegates to `this.client`, so its behaviour is exactly the client's.
5
+ */
6
+ import type { Unfenced } from "./client.js";
7
+ import type { ExtractedDoc } from "./protocol.js";
8
+ import type { Action, ActExpectation, ActResult, DownloadInfo, Format, OnAction, PageSnapshot, ProviderSessionReason } from "./types.js";
9
+ /** Options that change how an action is reported, not what the page is asked to do. */
10
+ export interface SessionActOptions {
11
+ acceptDialog?: boolean;
12
+ dialogText?: string;
13
+ brief?: boolean;
14
+ see?: boolean;
15
+ expect?: ActExpectation;
16
+ }
17
+ /**
18
+ * A handle to one live browser session.
19
+ *
20
+ * Keep it around across steps: observe to see what is on the page, act to
21
+ * change it, extract to read it clean, screenshot to watch it. Refs come from
22
+ * the latest snapshot and go stale on navigation — observe again after acting.
23
+ */
24
+ export declare class Session {
25
+ private readonly client;
26
+ readonly id: string;
27
+ /** The snapshot from when the session opened. */
28
+ readonly initial: PageSnapshot;
29
+ constructor(client: Unfenced, id: string,
30
+ /** The snapshot from when the session opened. */
31
+ initial: PageSnapshot);
32
+ observe(opts?: {
33
+ match?: string;
34
+ maxControls?: number;
35
+ maxLinks?: number;
36
+ excerptChars?: number;
37
+ media?: boolean;
38
+ }): Promise<PageSnapshot>;
39
+ /**
40
+ * Re-read the page after a reconnect and retain the provider continuity
41
+ * signal returned by the worker.
42
+ */
43
+ refresh(opts?: {
44
+ match?: string;
45
+ }): Promise<{
46
+ page: PageSnapshot;
47
+ providerSession?: ProviderSessionReason;
48
+ }>;
49
+ act(action: Action | OnAction, opts?: SessionActOptions): Promise<ActResult>;
50
+ click(ref: string, opts?: {
51
+ confirm?: boolean;
52
+ } & SessionActOptions): Promise<ActResult>;
53
+ type(ref: string, text: string, opts?: {
54
+ submit?: boolean;
55
+ confirm?: boolean;
56
+ append?: boolean;
57
+ } & SessionActOptions): Promise<ActResult>;
58
+ select(ref: string, value: string, opts?: SessionActOptions): Promise<ActResult>;
59
+ press(key: string, opts?: {
60
+ confirm?: boolean;
61
+ } & SessionActOptions): Promise<ActResult>;
62
+ scroll(to: "top" | "bottom" | {
63
+ ref: string;
64
+ }, opts?: SessionActOptions): Promise<ActResult>;
65
+ /** `settleMs` is the pause after the document commits, not the navigation's
66
+ * own timeout — see the `navigate` action. Default 4000, maximum 15000. */
67
+ navigate(url: string, opts?: {
68
+ settleMs?: number;
69
+ } & SessionActOptions): Promise<ActResult>;
70
+ back(opts?: SessionActOptions): Promise<ActResult>;
71
+ extract(format?: Format, maxWords?: number): Promise<{
72
+ doc: ExtractedDoc;
73
+ content: string;
74
+ url: string;
75
+ contentTruncated?: boolean;
76
+ totalWords?: number;
77
+ }>;
78
+ park(minutes?: number, reason?: string): Promise<{
79
+ ok: boolean;
80
+ until?: string;
81
+ }>;
82
+ downloads(): Promise<{
83
+ downloads: DownloadInfo[];
84
+ }>;
85
+ readDownload(filename: string): Promise<{
86
+ filename: string;
87
+ bytes: number;
88
+ content: string;
89
+ doc: ExtractedDoc;
90
+ }>;
91
+ screenshot(): Promise<string>;
92
+ close(): Promise<{
93
+ alreadyClosed?: boolean;
94
+ wasOpen?: boolean;
95
+ }>;
96
+ }
97
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * A handle to one live browser session.
3
+ *
4
+ * Keep it around across steps: observe to see what is on the page, act to
5
+ * change it, extract to read it clean, screenshot to watch it. Refs come from
6
+ * the latest snapshot and go stale on navigation — observe again after acting.
7
+ */
8
+ export class Session {
9
+ client;
10
+ id;
11
+ initial;
12
+ constructor(client, id,
13
+ /** The snapshot from when the session opened. */
14
+ initial) {
15
+ this.client = client;
16
+ this.id = id;
17
+ this.initial = initial;
18
+ }
19
+ observe(opts) {
20
+ return this.client.observe(this.id, opts);
21
+ }
22
+ /**
23
+ * Re-read the page after a reconnect and retain the provider continuity
24
+ * signal returned by the worker.
25
+ */
26
+ refresh(opts) {
27
+ return this.client.refresh(this.id, opts);
28
+ }
29
+ act(action, opts) {
30
+ return this.client.act(this.id, action, opts);
31
+ }
32
+ click(ref, opts = {}) {
33
+ const { confirm, ...reporting } = opts;
34
+ return this.act({ kind: "click", ref, ...(confirm !== undefined ? { confirm } : {}) }, reporting);
35
+ }
36
+ type(ref, text, opts = {}) {
37
+ const { submit, confirm, append, ...reporting } = opts;
38
+ return this.act({
39
+ kind: "type",
40
+ ref,
41
+ text,
42
+ ...(submit !== undefined ? { submit } : {}),
43
+ ...(confirm !== undefined ? { confirm } : {}),
44
+ ...(append !== undefined ? { append } : {}),
45
+ }, reporting);
46
+ }
47
+ select(ref, value, opts = {}) {
48
+ return this.act({ kind: "select", ref, value }, opts);
49
+ }
50
+ press(key, opts = {}) {
51
+ const { confirm, ...reporting } = opts;
52
+ return this.act({ kind: "press", key, ...(confirm !== undefined ? { confirm } : {}) }, reporting);
53
+ }
54
+ scroll(to, opts = {}) {
55
+ return this.act({ kind: "scroll", to }, opts);
56
+ }
57
+ /** `settleMs` is the pause after the document commits, not the navigation's
58
+ * own timeout — see the `navigate` action. Default 4000, maximum 15000. */
59
+ navigate(url, opts = {}) {
60
+ const { settleMs, ...reporting } = opts;
61
+ return this.act({ kind: "navigate", url, ...(settleMs !== undefined ? { settleMs } : {}) }, reporting);
62
+ }
63
+ back(opts = {}) {
64
+ return this.act({ kind: "back" }, opts);
65
+ }
66
+ extract(format = "markdown", maxWords) {
67
+ return this.client.extract(this.id, format, maxWords);
68
+ }
69
+ park(minutes, reason) {
70
+ return this.client.park(this.id, minutes, reason);
71
+ }
72
+ downloads() {
73
+ return this.client.downloads(this.id);
74
+ }
75
+ readDownload(filename) {
76
+ return this.client.readDownload(this.id, filename);
77
+ }
78
+ screenshot() {
79
+ return this.client.screenshot(this.id);
80
+ }
81
+ close() {
82
+ // Mirrors closeSession's own signature deliberately. Narrowing it here
83
+ // drops `wasOpen` for every caller that goes through a Session — the
84
+ // defect the comment on that method exists to prevent.
85
+ return this.client.closeSession(this.id);
86
+ }
87
+ }
88
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}