poltertab 1.6.0-beta.1 → 1.6.0-beta.2
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/mcp-server/extract-all.js +10 -12
- package/mcp-server/index.js +162 -12
- package/mcp-server/memory.js +208 -4
- package/mcp-server/recipes.js +1043 -0
- package/mcp-server/tools.js +35 -5
- package/package.json +1 -1
package/mcp-server/tools.js
CHANGED
|
@@ -32,6 +32,28 @@ const SINK = {
|
|
|
32
32
|
// Self-healing: browser_click/browser_fill return the resolved element's
|
|
33
33
|
// fingerprint. Pass it back on a later call and, if the selector has drifted
|
|
34
34
|
// (a renamed id/class), the element is relocated by structural similarity.
|
|
35
|
+
// Learned recipes: a spec that produced clean rows is stored per host and page
|
|
36
|
+
// shape, so a later extract on the same shape can omit it entirely. Shared by
|
|
37
|
+
// browser_extract and browser_extract_all because the stored spec is the same
|
|
38
|
+
// spec — a recipe learned by one is replayed by the other.
|
|
39
|
+
const RECIPE = {
|
|
40
|
+
recipe: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description:
|
|
43
|
+
"Name of a learned recipe to replay. Only needed when more than one has been learned for this page shape — with exactly one, omitting `record`/`fields` uses it. browser_navigate lists what exists in `recipes_available`, and browser_get_site_memory has the detail.",
|
|
44
|
+
},
|
|
45
|
+
variant: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description:
|
|
48
|
+
"Which slice of the recipe to replay (a filter combination it was learned under). Only needed when the recipe has more than one. Variant names are derived from the steps that preceded the extract, so browser_get_site_memory shows which slice each one is.",
|
|
49
|
+
},
|
|
50
|
+
remember: {
|
|
51
|
+
type: "string",
|
|
52
|
+
description:
|
|
53
|
+
"Name this extraction so it can be replayed later, as 'name' or 'name/variant'. Optional: a spec that produced clean rows is remembered anyway, under a name derived from its fields and a variant derived from the clicks, fills and scrolls that preceded it. Nothing is stored from a result that fails the quality bar.",
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
35
57
|
const FINGERPRINT = {
|
|
36
58
|
fingerprint: {
|
|
37
59
|
type: "object",
|
|
@@ -120,7 +142,7 @@ const BROWSER_TOOLS = [
|
|
|
120
142
|
{
|
|
121
143
|
name: "browser_extract",
|
|
122
144
|
description:
|
|
123
|
-
"Extract repeating records (cards, rows, listings) with fields grouped per record. Fields resolve INSIDE each record root and a missing field yields null instead of shifting later records' values. Returns fill rates and warns when a field is empty inside the record scope but matches page-wide (record boundary too narrow).",
|
|
145
|
+
"Extract repeating records (cards, rows, listings) with fields grouped per record. Fields resolve INSIDE each record root and a missing field yields null instead of shifting later records' values. Returns fill rates and warns when a field is empty inside the record scope but matches page-wide (record boundary too narrow). `record` and `fields` are optional when a recipe has already been learned for this page shape: omit them to replay it, and the result names it in `used_recipe` (with `stale: true` if the page no longer matches what was learned). `remember` names what a fresh spec is stored as.",
|
|
124
146
|
inputSchema: {
|
|
125
147
|
type: "object",
|
|
126
148
|
properties: {
|
|
@@ -157,16 +179,20 @@ const BROWSER_TOOLS = [
|
|
|
157
179
|
description:
|
|
158
180
|
"Page-wide re-check of any field that came back entirely empty (default true)",
|
|
159
181
|
},
|
|
182
|
+
...RECIPE,
|
|
160
183
|
...SINK,
|
|
161
184
|
...TARGET,
|
|
162
185
|
},
|
|
163
|
-
required:
|
|
186
|
+
// record/fields are not required: with neither, a recipe learned on this
|
|
187
|
+
// page shape supplies them. Nothing known for the page is an error that
|
|
188
|
+
// says so, never a spec-less extract.
|
|
189
|
+
required: [],
|
|
164
190
|
},
|
|
165
191
|
},
|
|
166
192
|
{
|
|
167
193
|
name: "browser_extract_all",
|
|
168
194
|
description:
|
|
169
|
-
"Paginate and extract in one call, with no model round-trip per page. Takes browser_extract's spec plus a URL template,
|
|
195
|
+
"Paginate and extract in one call, with no model round-trip per page. Takes browser_extract's spec plus a URL template — the spec is optional when a recipe was learned for that page shape, and a recipe learned here stores the template so a later call can replay both. Walks pages, dedups on a key, and halts on: limit reached, empty page, a page whose records repeat an earlier page's (the trap where ignored page-size params silently return page 1 again), fill rates collapsing against page 1's baseline, or max_pages. Always reports which condition fired and returns everything collected so far.",
|
|
170
196
|
inputSchema: {
|
|
171
197
|
type: "object",
|
|
172
198
|
properties: {
|
|
@@ -203,12 +229,16 @@ const BROWSER_TOOLS = [
|
|
|
203
229
|
"Halt when a field well-populated on the baseline page falls below this fraction of it (default 0.5). 0 disables the check.",
|
|
204
230
|
},
|
|
205
231
|
max_text: { type: "number" },
|
|
232
|
+
...RECIPE,
|
|
206
233
|
...SINK,
|
|
207
234
|
// Session only, deliberately: this tool drives its own navigation from
|
|
208
235
|
// url_template, so a tabId would be accepted and then ignored.
|
|
209
236
|
session: TARGET.session,
|
|
210
237
|
},
|
|
211
|
-
|
|
238
|
+
// Same as browser_extract: the spec is optional when a recipe exists for
|
|
239
|
+
// the page shape url_template points at. The template itself is not —
|
|
240
|
+
// it is what says which pages to walk.
|
|
241
|
+
required: ["url_template"],
|
|
212
242
|
},
|
|
213
243
|
},
|
|
214
244
|
{
|
|
@@ -418,7 +448,7 @@ const BROWSER_TOOLS = [
|
|
|
418
448
|
{
|
|
419
449
|
name: "browser_get_site_memory",
|
|
420
450
|
description:
|
|
421
|
-
"Get navigation memory
|
|
451
|
+
"Get navigation memory for a website domain: the obstacles and fixes saved for it, plus any extraction recipes learned there — their fields, their variants, and the steps that were observed before each one worked. The steps are observations, not a script: reissue one only if it still fits the page.",
|
|
422
452
|
inputSchema: {
|
|
423
453
|
type: "object",
|
|
424
454
|
properties: {
|
package/package.json
CHANGED