@jackwener/opencli 1.5.7 → 1.5.9
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/CHANGELOG.md +29 -0
- package/README.md +17 -1
- package/README.zh-CN.md +17 -1
- package/dist/browser/base-page.d.ts +48 -0
- package/dist/browser/base-page.js +160 -0
- package/dist/browser/cdp.js +4 -106
- package/dist/browser/daemon-client.d.ts +1 -7
- package/dist/browser/daemon-client.js +2 -9
- package/dist/browser/discover.d.ts +1 -4
- package/dist/browser/discover.js +1 -4
- package/dist/browser/errors.d.ts +4 -0
- package/dist/browser/errors.js +20 -0
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/page.d.ts +6 -35
- package/dist/browser/page.js +10 -189
- package/dist/browser/tabs.js +5 -5
- package/dist/browser.test.js +15 -15
- package/dist/cli-manifest.json +294 -22
- package/dist/clis/amazon/bestsellers.d.ts +21 -0
- package/dist/clis/amazon/bestsellers.js +130 -0
- package/dist/clis/amazon/bestsellers.test.js +20 -0
- package/dist/clis/amazon/discussion.d.ts +20 -0
- package/dist/clis/amazon/discussion.js +91 -0
- package/dist/clis/amazon/discussion.test.js +36 -0
- package/dist/clis/amazon/offer.d.ts +23 -0
- package/dist/clis/amazon/offer.js +140 -0
- package/dist/clis/amazon/offer.test.d.ts +1 -0
- package/dist/clis/amazon/offer.test.js +29 -0
- package/dist/clis/amazon/product.d.ts +18 -0
- package/dist/clis/amazon/product.js +92 -0
- package/dist/clis/amazon/product.test.d.ts +1 -0
- package/dist/clis/amazon/product.test.js +24 -0
- package/dist/clis/amazon/search.d.ts +18 -0
- package/dist/clis/amazon/search.js +87 -0
- package/dist/clis/amazon/search.test.d.ts +1 -0
- package/dist/clis/amazon/search.test.js +22 -0
- package/dist/clis/amazon/shared.d.ts +64 -0
- package/dist/clis/amazon/shared.js +255 -0
- package/dist/clis/amazon/shared.test.d.ts +1 -0
- package/dist/clis/amazon/shared.test.js +33 -0
- package/dist/clis/gemini/ask.d.ts +1 -0
- package/dist/clis/gemini/ask.js +40 -0
- package/dist/clis/gemini/image.d.ts +1 -0
- package/dist/clis/gemini/image.js +105 -0
- package/dist/clis/gemini/new.d.ts +1 -0
- package/dist/clis/gemini/new.js +20 -0
- package/dist/clis/gemini/utils.d.ts +34 -0
- package/dist/clis/gemini/utils.js +463 -0
- package/dist/clis/gemini/utils.test.d.ts +1 -0
- package/dist/clis/gemini/utils.test.js +31 -0
- package/dist/clis/notebooklm/compat.test.d.ts +1 -1
- package/dist/clis/notebooklm/compat.test.js +3 -3
- package/dist/clis/notebooklm/current.js +2 -3
- package/dist/clis/notebooklm/get.js +2 -3
- package/dist/clis/notebooklm/history.js +2 -3
- package/dist/clis/notebooklm/note-list.js +2 -3
- package/dist/clis/notebooklm/notes-get.js +2 -3
- package/dist/clis/notebooklm/open.d.ts +1 -0
- package/dist/clis/notebooklm/open.js +41 -0
- package/dist/clis/notebooklm/open.test.d.ts +1 -0
- package/dist/clis/notebooklm/open.test.js +63 -0
- package/dist/clis/notebooklm/source-fulltext.js +2 -3
- package/dist/clis/notebooklm/source-get.js +2 -3
- package/dist/clis/notebooklm/source-guide.js +2 -3
- package/dist/clis/notebooklm/source-list.js +2 -3
- package/dist/clis/notebooklm/status.js +1 -2
- package/dist/clis/notebooklm/summary.js +2 -3
- package/dist/clis/notebooklm/utils.d.ts +2 -1
- package/dist/clis/notebooklm/utils.js +20 -21
- package/dist/clis/xiaohongshu/creator-note-detail.test.js +11 -11
- package/dist/clis/xiaohongshu/creator-notes-summary.test.js +6 -6
- package/dist/clis/xiaohongshu/creator-notes.test.js +22 -22
- package/dist/commanderAdapter.js +6 -3
- package/dist/commanderAdapter.test.js +33 -0
- package/dist/commands/daemon.js +1 -1
- package/dist/commands/daemon.test.js +1 -1
- package/dist/doctor.d.ts +1 -2
- package/dist/doctor.js +7 -8
- package/dist/explore.js +1 -1
- package/dist/extension-manifest-regression.test.js +1 -0
- package/dist/output.js +28 -0
- package/dist/output.test.js +15 -0
- package/dist/pipeline/executor.js +2 -7
- package/dist/pipeline/steps/browser.js +1 -1
- package/dist/pipeline/template.js +25 -3
- package/dist/record.d.ts +50 -0
- package/dist/record.js +298 -57
- package/dist/record.test.d.ts +1 -0
- package/dist/record.test.js +293 -0
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +1 -0
- package/dist/registry.test.js +10 -0
- package/dist/runtime.js +3 -3
- package/dist/snapshotFormatter.d.ts +1 -1
- package/dist/snapshotFormatter.js +4 -4
- package/dist/snapshotFormatter.test.d.ts +1 -1
- package/dist/snapshotFormatter.test.js +2 -2
- package/dist/types.d.ts +3 -1
- package/dist/types.js +1 -1
- package/docs/.vitepress/config.mts +2 -0
- package/docs/adapters/browser/amazon.md +53 -0
- package/docs/adapters/browser/gemini.md +72 -0
- package/docs/adapters/browser/notebooklm.md +5 -5
- package/docs/adapters/index.md +3 -1
- package/extension/dist/background.js +614 -794
- package/extension/manifest.json +2 -1
- package/extension/src/background.test.ts +7 -163
- package/extension/src/background.ts +7 -156
- package/extension/src/cdp.test.ts +75 -0
- package/extension/src/cdp.ts +77 -3
- package/extension/src/protocol.ts +1 -5
- package/package.json +1 -1
- package/skills/opencli-explorer/SKILL.md +847 -0
- package/skills/opencli-oneshot/SKILL.md +216 -0
- package/skills/opencli-usage/SKILL.md +71 -0
- package/skills/opencli-usage/browser.md +429 -0
- package/skills/opencli-usage/desktop.md +118 -0
- package/skills/opencli-usage/plugins.md +82 -0
- package/skills/opencli-usage/public-api.md +149 -0
- package/src/browser/base-page.ts +197 -0
- package/src/browser/cdp.ts +7 -131
- package/src/browser/daemon-client.ts +3 -14
- package/src/browser/discover.ts +1 -4
- package/src/browser/errors.ts +22 -0
- package/src/browser/index.ts +1 -1
- package/src/browser/page.ts +13 -212
- package/src/browser/tabs.ts +5 -5
- package/src/browser.test.ts +15 -15
- package/src/clis/amazon/bestsellers.test.ts +22 -0
- package/src/clis/amazon/bestsellers.ts +180 -0
- package/src/clis/amazon/discussion.test.ts +38 -0
- package/src/clis/amazon/discussion.ts +131 -0
- package/src/clis/amazon/offer.test.ts +35 -0
- package/src/clis/amazon/offer.ts +185 -0
- package/src/clis/amazon/product.test.ts +26 -0
- package/src/clis/amazon/product.ts +131 -0
- package/src/clis/amazon/search.test.ts +24 -0
- package/src/clis/amazon/search.ts +128 -0
- package/src/clis/amazon/shared.test.ts +37 -0
- package/src/clis/amazon/shared.ts +316 -0
- package/src/clis/gemini/ask.ts +46 -0
- package/src/clis/gemini/image.ts +115 -0
- package/src/clis/gemini/new.ts +22 -0
- package/src/clis/gemini/utils.test.ts +36 -0
- package/src/clis/gemini/utils.ts +523 -0
- package/src/clis/notebooklm/compat.test.ts +3 -3
- package/src/clis/notebooklm/current.ts +2 -3
- package/src/clis/notebooklm/get.ts +1 -3
- package/src/clis/notebooklm/history.ts +1 -3
- package/src/clis/notebooklm/note-list.ts +1 -3
- package/src/clis/notebooklm/notes-get.ts +1 -3
- package/src/clis/notebooklm/open.test.ts +78 -0
- package/src/clis/notebooklm/open.ts +61 -0
- package/src/clis/notebooklm/source-fulltext.ts +1 -3
- package/src/clis/notebooklm/source-get.ts +1 -3
- package/src/clis/notebooklm/source-guide.ts +1 -3
- package/src/clis/notebooklm/source-list.ts +1 -3
- package/src/clis/notebooklm/status.ts +1 -2
- package/src/clis/notebooklm/summary.ts +1 -3
- package/src/clis/notebooklm/utils.ts +29 -20
- package/src/clis/xiaohongshu/creator-note-detail.test.ts +11 -11
- package/src/clis/xiaohongshu/creator-notes-summary.test.ts +6 -6
- package/src/clis/xiaohongshu/creator-notes.test.ts +22 -22
- package/src/commanderAdapter.test.ts +47 -0
- package/src/commanderAdapter.ts +7 -3
- package/src/commands/daemon.test.ts +1 -1
- package/src/commands/daemon.ts +1 -1
- package/src/doctor.ts +7 -8
- package/src/explore.ts +1 -1
- package/src/extension-manifest-regression.test.ts +1 -0
- package/src/output.test.ts +17 -0
- package/src/output.ts +27 -0
- package/src/pipeline/executor.ts +2 -7
- package/src/pipeline/steps/browser.ts +1 -1
- package/src/pipeline/template.ts +27 -4
- package/src/record.test.ts +362 -0
- package/src/record.ts +341 -62
- package/src/registry.test.ts +12 -0
- package/src/registry.ts +3 -0
- package/src/runtime.ts +3 -3
- package/src/snapshotFormatter.test.ts +2 -2
- package/src/snapshotFormatter.ts +4 -4
- package/src/types.ts +3 -1
- package/.agents/skills/cross-project-adapter-migration/SKILL.md +0 -249
- package/.agents/workflows/cross-project-adapter-migration.md +0 -54
- package/SKILL.md +0 -879
- package/dist/clis/notebooklm/bind-current.js +0 -29
- package/dist/clis/notebooklm/bind-current.test.d.ts +0 -1
- package/dist/clis/notebooklm/bind-current.test.js +0 -35
- package/dist/clis/notebooklm/binding.test.js +0 -44
- package/src/clis/notebooklm/bind-current.test.ts +0 -43
- package/src/clis/notebooklm/bind-current.ts +0 -36
- package/src/clis/notebooklm/binding.test.ts +0 -53
- /package/dist/browser/{mcp.d.ts → bridge.d.ts} +0 -0
- /package/dist/browser/{mcp.js → bridge.js} +0 -0
- /package/dist/clis/{notebooklm/bind-current.d.ts → amazon/bestsellers.test.d.ts} +0 -0
- /package/dist/clis/{notebooklm/binding.test.d.ts → amazon/discussion.test.d.ts} +0 -0
- /package/src/browser/{mcp.ts → bridge.ts} +0 -0
package/dist/cli-manifest.json
CHANGED
|
@@ -111,6 +111,163 @@
|
|
|
111
111
|
"type": "ts",
|
|
112
112
|
"modulePath": "36kr/search.js"
|
|
113
113
|
},
|
|
114
|
+
{
|
|
115
|
+
"site": "amazon",
|
|
116
|
+
"name": "bestsellers",
|
|
117
|
+
"description": "Amazon Best Sellers pages for category candidate discovery",
|
|
118
|
+
"domain": "amazon.com",
|
|
119
|
+
"strategy": "cookie",
|
|
120
|
+
"browser": true,
|
|
121
|
+
"args": [
|
|
122
|
+
{
|
|
123
|
+
"name": "input",
|
|
124
|
+
"type": "str",
|
|
125
|
+
"required": false,
|
|
126
|
+
"positional": true,
|
|
127
|
+
"help": "Best sellers URL or /zgbs path. Omit to use the root Best Sellers page."
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"name": "limit",
|
|
131
|
+
"type": "int",
|
|
132
|
+
"default": 100,
|
|
133
|
+
"required": false,
|
|
134
|
+
"help": "Maximum number of ranked items to return (default 100)"
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"columns": [
|
|
138
|
+
"rank",
|
|
139
|
+
"asin",
|
|
140
|
+
"title",
|
|
141
|
+
"price_text",
|
|
142
|
+
"rating_value",
|
|
143
|
+
"review_count"
|
|
144
|
+
],
|
|
145
|
+
"type": "ts",
|
|
146
|
+
"modulePath": "amazon/bestsellers.js",
|
|
147
|
+
"navigateBefore": false
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"site": "amazon",
|
|
151
|
+
"name": "discussion",
|
|
152
|
+
"description": "Amazon review summary and sample customer discussion from product review pages",
|
|
153
|
+
"domain": "amazon.com",
|
|
154
|
+
"strategy": "cookie",
|
|
155
|
+
"browser": true,
|
|
156
|
+
"args": [
|
|
157
|
+
{
|
|
158
|
+
"name": "input",
|
|
159
|
+
"type": "str",
|
|
160
|
+
"required": true,
|
|
161
|
+
"positional": true,
|
|
162
|
+
"help": "ASIN or product URL, for example B0FJS72893"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"name": "limit",
|
|
166
|
+
"type": "int",
|
|
167
|
+
"default": 10,
|
|
168
|
+
"required": false,
|
|
169
|
+
"help": "Maximum number of review samples to return (default 10)"
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"columns": [
|
|
173
|
+
"asin",
|
|
174
|
+
"average_rating_value",
|
|
175
|
+
"total_review_count"
|
|
176
|
+
],
|
|
177
|
+
"type": "ts",
|
|
178
|
+
"modulePath": "amazon/discussion.js",
|
|
179
|
+
"navigateBefore": false
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"site": "amazon",
|
|
183
|
+
"name": "offer",
|
|
184
|
+
"description": "Amazon seller, buy box, and fulfillment facts from the product page",
|
|
185
|
+
"domain": "amazon.com",
|
|
186
|
+
"strategy": "cookie",
|
|
187
|
+
"browser": true,
|
|
188
|
+
"args": [
|
|
189
|
+
{
|
|
190
|
+
"name": "input",
|
|
191
|
+
"type": "str",
|
|
192
|
+
"required": true,
|
|
193
|
+
"positional": true,
|
|
194
|
+
"help": "ASIN or product URL, for example B0FJS72893"
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"columns": [
|
|
198
|
+
"asin",
|
|
199
|
+
"price_text",
|
|
200
|
+
"sold_by",
|
|
201
|
+
"ships_from",
|
|
202
|
+
"is_amazon_sold",
|
|
203
|
+
"is_amazon_fulfilled"
|
|
204
|
+
],
|
|
205
|
+
"type": "ts",
|
|
206
|
+
"modulePath": "amazon/offer.js",
|
|
207
|
+
"navigateBefore": false
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"site": "amazon",
|
|
211
|
+
"name": "product",
|
|
212
|
+
"description": "Amazon product page facts for candidate validation",
|
|
213
|
+
"domain": "amazon.com",
|
|
214
|
+
"strategy": "cookie",
|
|
215
|
+
"browser": true,
|
|
216
|
+
"args": [
|
|
217
|
+
{
|
|
218
|
+
"name": "input",
|
|
219
|
+
"type": "str",
|
|
220
|
+
"required": true,
|
|
221
|
+
"positional": true,
|
|
222
|
+
"help": "ASIN or product URL, for example B0FJS72893"
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
"columns": [
|
|
226
|
+
"asin",
|
|
227
|
+
"title",
|
|
228
|
+
"price_text",
|
|
229
|
+
"rating_value",
|
|
230
|
+
"review_count"
|
|
231
|
+
],
|
|
232
|
+
"type": "ts",
|
|
233
|
+
"modulePath": "amazon/product.js",
|
|
234
|
+
"navigateBefore": false
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"site": "amazon",
|
|
238
|
+
"name": "search",
|
|
239
|
+
"description": "Amazon search results for product discovery and coarse filtering",
|
|
240
|
+
"domain": "amazon.com",
|
|
241
|
+
"strategy": "cookie",
|
|
242
|
+
"browser": true,
|
|
243
|
+
"args": [
|
|
244
|
+
{
|
|
245
|
+
"name": "query",
|
|
246
|
+
"type": "str",
|
|
247
|
+
"required": true,
|
|
248
|
+
"positional": true,
|
|
249
|
+
"help": "Search query, for example \"desk shelf organizer\""
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"name": "limit",
|
|
253
|
+
"type": "int",
|
|
254
|
+
"default": 20,
|
|
255
|
+
"required": false,
|
|
256
|
+
"help": "Maximum number of results to return (default 20)"
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
"columns": [
|
|
260
|
+
"rank",
|
|
261
|
+
"asin",
|
|
262
|
+
"title",
|
|
263
|
+
"price_text",
|
|
264
|
+
"rating_value",
|
|
265
|
+
"review_count"
|
|
266
|
+
],
|
|
267
|
+
"type": "ts",
|
|
268
|
+
"modulePath": "amazon/search.js",
|
|
269
|
+
"navigateBefore": false
|
|
270
|
+
},
|
|
114
271
|
{
|
|
115
272
|
"site": "antigravity",
|
|
116
273
|
"name": "dump",
|
|
@@ -5218,6 +5375,114 @@
|
|
|
5218
5375
|
],
|
|
5219
5376
|
"type": "yaml"
|
|
5220
5377
|
},
|
|
5378
|
+
{
|
|
5379
|
+
"site": "gemini",
|
|
5380
|
+
"name": "ask",
|
|
5381
|
+
"description": "Send a prompt to Gemini and return only the assistant response",
|
|
5382
|
+
"domain": "gemini.google.com",
|
|
5383
|
+
"strategy": "cookie",
|
|
5384
|
+
"browser": true,
|
|
5385
|
+
"args": [
|
|
5386
|
+
{
|
|
5387
|
+
"name": "prompt",
|
|
5388
|
+
"type": "str",
|
|
5389
|
+
"required": true,
|
|
5390
|
+
"positional": true,
|
|
5391
|
+
"help": "Prompt to send"
|
|
5392
|
+
},
|
|
5393
|
+
{
|
|
5394
|
+
"name": "timeout",
|
|
5395
|
+
"type": "str",
|
|
5396
|
+
"default": "60",
|
|
5397
|
+
"required": false,
|
|
5398
|
+
"help": "Max seconds to wait (default: 60)"
|
|
5399
|
+
},
|
|
5400
|
+
{
|
|
5401
|
+
"name": "new",
|
|
5402
|
+
"type": "str",
|
|
5403
|
+
"default": "false",
|
|
5404
|
+
"required": false,
|
|
5405
|
+
"help": "Start a new chat first (true/false, default: false)"
|
|
5406
|
+
}
|
|
5407
|
+
],
|
|
5408
|
+
"columns": [
|
|
5409
|
+
"response"
|
|
5410
|
+
],
|
|
5411
|
+
"timeout": 180,
|
|
5412
|
+
"type": "ts",
|
|
5413
|
+
"modulePath": "gemini/ask.js",
|
|
5414
|
+
"navigateBefore": false
|
|
5415
|
+
},
|
|
5416
|
+
{
|
|
5417
|
+
"site": "gemini",
|
|
5418
|
+
"name": "image",
|
|
5419
|
+
"description": "Generate images with Gemini web and save them locally",
|
|
5420
|
+
"domain": "gemini.google.com",
|
|
5421
|
+
"strategy": "cookie",
|
|
5422
|
+
"browser": true,
|
|
5423
|
+
"args": [
|
|
5424
|
+
{
|
|
5425
|
+
"name": "prompt",
|
|
5426
|
+
"type": "str",
|
|
5427
|
+
"required": true,
|
|
5428
|
+
"positional": true,
|
|
5429
|
+
"help": "Image prompt to send to Gemini"
|
|
5430
|
+
},
|
|
5431
|
+
{
|
|
5432
|
+
"name": "rt",
|
|
5433
|
+
"type": "str",
|
|
5434
|
+
"default": "1:1",
|
|
5435
|
+
"required": false,
|
|
5436
|
+
"help": "Ratio shorthand for aspect ratio (1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3)"
|
|
5437
|
+
},
|
|
5438
|
+
{
|
|
5439
|
+
"name": "st",
|
|
5440
|
+
"type": "str",
|
|
5441
|
+
"default": "",
|
|
5442
|
+
"required": false,
|
|
5443
|
+
"help": "Style shorthand, e.g. anime, icon, watercolor"
|
|
5444
|
+
},
|
|
5445
|
+
{
|
|
5446
|
+
"name": "op",
|
|
5447
|
+
"type": "str",
|
|
5448
|
+
"default": "/home/runner/tmp/gemini-images",
|
|
5449
|
+
"required": false,
|
|
5450
|
+
"help": "Output directory shorthand"
|
|
5451
|
+
},
|
|
5452
|
+
{
|
|
5453
|
+
"name": "sd",
|
|
5454
|
+
"type": "boolean",
|
|
5455
|
+
"default": false,
|
|
5456
|
+
"required": false,
|
|
5457
|
+
"help": "Skip download shorthand; only show Gemini page link"
|
|
5458
|
+
}
|
|
5459
|
+
],
|
|
5460
|
+
"columns": [
|
|
5461
|
+
"status",
|
|
5462
|
+
"file",
|
|
5463
|
+
"link"
|
|
5464
|
+
],
|
|
5465
|
+
"timeout": 240,
|
|
5466
|
+
"type": "ts",
|
|
5467
|
+
"modulePath": "gemini/image.js",
|
|
5468
|
+
"navigateBefore": false
|
|
5469
|
+
},
|
|
5470
|
+
{
|
|
5471
|
+
"site": "gemini",
|
|
5472
|
+
"name": "new",
|
|
5473
|
+
"description": "Start a new conversation in Gemini web chat",
|
|
5474
|
+
"domain": "gemini.google.com",
|
|
5475
|
+
"strategy": "cookie",
|
|
5476
|
+
"browser": true,
|
|
5477
|
+
"args": [],
|
|
5478
|
+
"columns": [
|
|
5479
|
+
"Status",
|
|
5480
|
+
"Action"
|
|
5481
|
+
],
|
|
5482
|
+
"type": "ts",
|
|
5483
|
+
"modulePath": "gemini/new.js",
|
|
5484
|
+
"navigateBefore": false
|
|
5485
|
+
},
|
|
5221
5486
|
{
|
|
5222
5487
|
"site": "google",
|
|
5223
5488
|
"name": "news",
|
|
@@ -8079,28 +8344,6 @@
|
|
|
8079
8344
|
"type": "ts",
|
|
8080
8345
|
"modulePath": "medium/user.js"
|
|
8081
8346
|
},
|
|
8082
|
-
{
|
|
8083
|
-
"site": "notebooklm",
|
|
8084
|
-
"name": "bind-current",
|
|
8085
|
-
"aliases": [
|
|
8086
|
-
"use"
|
|
8087
|
-
],
|
|
8088
|
-
"description": "Bind the current active NotebookLM notebook tab into the site:notebooklm workspace",
|
|
8089
|
-
"domain": "notebooklm.google.com",
|
|
8090
|
-
"strategy": "cookie",
|
|
8091
|
-
"browser": true,
|
|
8092
|
-
"args": [],
|
|
8093
|
-
"columns": [
|
|
8094
|
-
"workspace",
|
|
8095
|
-
"tab_id",
|
|
8096
|
-
"notebook_id",
|
|
8097
|
-
"title",
|
|
8098
|
-
"url"
|
|
8099
|
-
],
|
|
8100
|
-
"type": "ts",
|
|
8101
|
-
"modulePath": "notebooklm/bind-current.js",
|
|
8102
|
-
"navigateBefore": false
|
|
8103
|
-
},
|
|
8104
8347
|
{
|
|
8105
8348
|
"site": "notebooklm",
|
|
8106
8349
|
"name": "current",
|
|
@@ -8231,6 +8474,35 @@
|
|
|
8231
8474
|
"modulePath": "notebooklm/notes-get.js",
|
|
8232
8475
|
"navigateBefore": false
|
|
8233
8476
|
},
|
|
8477
|
+
{
|
|
8478
|
+
"site": "notebooklm",
|
|
8479
|
+
"name": "open",
|
|
8480
|
+
"aliases": [
|
|
8481
|
+
"select"
|
|
8482
|
+
],
|
|
8483
|
+
"description": "Open one NotebookLM notebook in the automation workspace by id or URL",
|
|
8484
|
+
"domain": "notebooklm.google.com",
|
|
8485
|
+
"strategy": "cookie",
|
|
8486
|
+
"browser": true,
|
|
8487
|
+
"args": [
|
|
8488
|
+
{
|
|
8489
|
+
"name": "notebook",
|
|
8490
|
+
"type": "str",
|
|
8491
|
+
"required": true,
|
|
8492
|
+
"positional": true,
|
|
8493
|
+
"help": "Notebook id from list output, or a full NotebookLM notebook URL"
|
|
8494
|
+
}
|
|
8495
|
+
],
|
|
8496
|
+
"columns": [
|
|
8497
|
+
"id",
|
|
8498
|
+
"title",
|
|
8499
|
+
"url",
|
|
8500
|
+
"source"
|
|
8501
|
+
],
|
|
8502
|
+
"type": "ts",
|
|
8503
|
+
"modulePath": "notebooklm/open.js",
|
|
8504
|
+
"navigateBefore": false
|
|
8505
|
+
},
|
|
8234
8506
|
{
|
|
8235
8507
|
"site": "notebooklm",
|
|
8236
8508
|
"name": "source-fulltext",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface BestsellersPagePayload {
|
|
2
|
+
href?: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
list_title?: string;
|
|
5
|
+
cards?: Array<{
|
|
6
|
+
rank_text?: string | null;
|
|
7
|
+
asin?: string | null;
|
|
8
|
+
title?: string | null;
|
|
9
|
+
href?: string | null;
|
|
10
|
+
price_text?: string | null;
|
|
11
|
+
rating_text?: string | null;
|
|
12
|
+
review_count_text?: string | null;
|
|
13
|
+
card_text?: string | null;
|
|
14
|
+
}>;
|
|
15
|
+
page_links?: string[];
|
|
16
|
+
}
|
|
17
|
+
declare function normalizeBestsellerCandidate(candidate: NonNullable<BestsellersPagePayload['cards']>[number], rank: number, listTitle: string | null, sourceUrl: string): Record<string, unknown>;
|
|
18
|
+
export declare const __test__: {
|
|
19
|
+
normalizeBestsellerCandidate: typeof normalizeBestsellerCandidate;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { CommandExecutionError } from '../../errors.js';
|
|
2
|
+
import { cli, Strategy } from '../../registry.js';
|
|
3
|
+
import { buildProvenance, cleanText, extractAsin, extractReviewCountFromCardText, firstMeaningfulLine, normalizeProductUrl, parsePriceText, parseRatingValue, parseReviewCount, resolveBestsellersUrl, uniqueNonEmpty, assertUsableState, gotoAndReadState, } from './shared.js';
|
|
4
|
+
function normalizeBestsellerCandidate(candidate, rank, listTitle, sourceUrl) {
|
|
5
|
+
const productUrl = normalizeProductUrl(candidate.href);
|
|
6
|
+
const asin = extractAsin(candidate.asin ?? '') ?? extractAsin(productUrl ?? '') ?? null;
|
|
7
|
+
const title = cleanText(candidate.title) || firstMeaningfulLine(candidate.card_text);
|
|
8
|
+
const price = parsePriceText(cleanText(candidate.price_text) || candidate.card_text);
|
|
9
|
+
const ratingText = cleanText(candidate.rating_text) || null;
|
|
10
|
+
const reviewCountText = cleanText(candidate.review_count_text)
|
|
11
|
+
|| extractReviewCountFromCardText(candidate.card_text)
|
|
12
|
+
|| null;
|
|
13
|
+
const provenance = buildProvenance(sourceUrl);
|
|
14
|
+
return {
|
|
15
|
+
rank,
|
|
16
|
+
asin,
|
|
17
|
+
title: title || null,
|
|
18
|
+
product_url: productUrl,
|
|
19
|
+
list_title: listTitle,
|
|
20
|
+
...provenance,
|
|
21
|
+
price_text: price.price_text,
|
|
22
|
+
price_value: price.price_value,
|
|
23
|
+
currency: price.currency,
|
|
24
|
+
rating_text: ratingText,
|
|
25
|
+
rating_value: parseRatingValue(ratingText),
|
|
26
|
+
review_count_text: reviewCountText,
|
|
27
|
+
review_count: parseReviewCount(reviewCountText),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function readBestsellersPage(page, url) {
|
|
31
|
+
const state = await gotoAndReadState(page, url, 2500, 'bestsellers');
|
|
32
|
+
assertUsableState(state, 'bestsellers');
|
|
33
|
+
return await page.evaluate(`
|
|
34
|
+
(() => ({
|
|
35
|
+
href: window.location.href,
|
|
36
|
+
title: document.title || '',
|
|
37
|
+
list_title:
|
|
38
|
+
document.querySelector('#zg_banner_text')?.textContent
|
|
39
|
+
|| document.querySelector('h1')?.textContent
|
|
40
|
+
|| '',
|
|
41
|
+
cards: Array.from(document.querySelectorAll('.p13n-sc-uncoverable-faceout'))
|
|
42
|
+
.map((card) => ({
|
|
43
|
+
rank_text:
|
|
44
|
+
card.querySelector('.zg-bdg-text')?.textContent
|
|
45
|
+
|| card.querySelector('[class*="rank"]')?.textContent
|
|
46
|
+
|| '',
|
|
47
|
+
asin: card.id || '',
|
|
48
|
+
title:
|
|
49
|
+
card.querySelector('[class*="line-clamp"]')?.textContent
|
|
50
|
+
|| card.querySelector('img')?.getAttribute('alt')
|
|
51
|
+
|| '',
|
|
52
|
+
href: card.querySelector('a[href*="/dp/"]')?.href || '',
|
|
53
|
+
price_text: card.querySelector('.a-price .a-offscreen')?.textContent || '',
|
|
54
|
+
rating_text: card.querySelector('[aria-label*="out of 5 stars"]')?.getAttribute('aria-label') || '',
|
|
55
|
+
review_count_text:
|
|
56
|
+
card.querySelector('a[href*="#customerReviews"]')?.textContent
|
|
57
|
+
|| card.querySelector('.a-size-small')?.textContent
|
|
58
|
+
|| '',
|
|
59
|
+
card_text: card.innerText || '',
|
|
60
|
+
})),
|
|
61
|
+
page_links: Array.from(document.querySelectorAll('li.a-normal a, li.a-selected a'))
|
|
62
|
+
.map((anchor) => anchor.href || '')
|
|
63
|
+
.filter((href) => /\\/zgbs\\//.test(href) && /(?:[?&]pg=|ref=zg_bs_pg_)/.test(href)),
|
|
64
|
+
}))()
|
|
65
|
+
`);
|
|
66
|
+
}
|
|
67
|
+
cli({
|
|
68
|
+
site: 'amazon',
|
|
69
|
+
name: 'bestsellers',
|
|
70
|
+
description: 'Amazon Best Sellers pages for category candidate discovery',
|
|
71
|
+
domain: 'amazon.com',
|
|
72
|
+
strategy: Strategy.COOKIE,
|
|
73
|
+
navigateBefore: false,
|
|
74
|
+
args: [
|
|
75
|
+
{
|
|
76
|
+
name: 'input',
|
|
77
|
+
positional: true,
|
|
78
|
+
help: 'Best sellers URL or /zgbs path. Omit to use the root Best Sellers page.',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'limit',
|
|
82
|
+
type: 'int',
|
|
83
|
+
default: 100,
|
|
84
|
+
help: 'Maximum number of ranked items to return (default 100)',
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
columns: ['rank', 'asin', 'title', 'price_text', 'rating_value', 'review_count'],
|
|
88
|
+
func: async (page, kwargs) => {
|
|
89
|
+
const limit = Math.max(1, Number(kwargs.limit) || 100);
|
|
90
|
+
const initialUrl = resolveBestsellersUrl(typeof kwargs.input === 'string' ? kwargs.input : undefined);
|
|
91
|
+
const queue = [initialUrl];
|
|
92
|
+
const visited = new Set();
|
|
93
|
+
const seenAsins = new Set();
|
|
94
|
+
const results = [];
|
|
95
|
+
let listTitle = null;
|
|
96
|
+
while (queue.length > 0 && results.length < limit) {
|
|
97
|
+
const nextUrl = queue.shift();
|
|
98
|
+
if (visited.has(nextUrl))
|
|
99
|
+
continue;
|
|
100
|
+
visited.add(nextUrl);
|
|
101
|
+
const payload = await readBestsellersPage(page, nextUrl);
|
|
102
|
+
const sourceUrl = cleanText(payload.href) || nextUrl;
|
|
103
|
+
listTitle = cleanText(payload.list_title) || cleanText(payload.title) || listTitle;
|
|
104
|
+
const cards = payload.cards ?? [];
|
|
105
|
+
for (const card of cards) {
|
|
106
|
+
const normalized = normalizeBestsellerCandidate(card, results.length + 1, listTitle, sourceUrl);
|
|
107
|
+
const asin = cleanText(String(normalized.asin ?? ''));
|
|
108
|
+
if (!asin || seenAsins.has(asin))
|
|
109
|
+
continue;
|
|
110
|
+
seenAsins.add(asin);
|
|
111
|
+
results.push(normalized);
|
|
112
|
+
if (results.length >= limit)
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
const pageLinks = uniqueNonEmpty(payload.page_links ?? []);
|
|
116
|
+
for (const href of pageLinks) {
|
|
117
|
+
if (!visited.has(href) && !queue.includes(href)) {
|
|
118
|
+
queue.push(href);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (results.length === 0) {
|
|
123
|
+
throw new CommandExecutionError('amazon bestsellers did not expose any ranked items', 'Open the same best sellers page in Chrome, verify it is a real Amazon ranking page, and retry.');
|
|
124
|
+
}
|
|
125
|
+
return results.slice(0, limit);
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
export const __test__ = {
|
|
129
|
+
normalizeBestsellerCandidate,
|
|
130
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { __test__ } from './bestsellers.js';
|
|
3
|
+
describe('amazon bestsellers normalization', () => {
|
|
4
|
+
it('normalizes bestseller cards and infers review counts from card text', () => {
|
|
5
|
+
const result = __test__.normalizeBestsellerCandidate({
|
|
6
|
+
asin: 'B0DR31GC3D',
|
|
7
|
+
title: '',
|
|
8
|
+
href: 'https://www.amazon.com/NUTIKAS-Shelves-Desktop-Orgnizer-Shlef/dp/B0DR31GC3D/ref=zg_bs',
|
|
9
|
+
price_text: '$25.92',
|
|
10
|
+
rating_text: '4.3 out of 5 stars',
|
|
11
|
+
review_count_text: '',
|
|
12
|
+
card_text: 'Desk Shelves Desktop Organizer Shlef\n4.3 out of 5 stars\n435\n$25.92',
|
|
13
|
+
}, 2, 'Amazon Best Sellers: Best Desktop & Off-Surface Shelves', 'https://www.amazon.com/example');
|
|
14
|
+
expect(result.rank).toBe(2);
|
|
15
|
+
expect(result.asin).toBe('B0DR31GC3D');
|
|
16
|
+
expect(result.title).toBe('Desk Shelves Desktop Organizer Shlef');
|
|
17
|
+
expect(result.review_count).toBe(435);
|
|
18
|
+
expect(result.list_title).toBe('Amazon Best Sellers: Best Desktop & Off-Surface Shelves');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface DiscussionPayload {
|
|
2
|
+
href?: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
average_rating_text?: string | null;
|
|
5
|
+
total_review_count_text?: string | null;
|
|
6
|
+
qa_links?: string[];
|
|
7
|
+
review_samples?: Array<{
|
|
8
|
+
title?: string | null;
|
|
9
|
+
rating_text?: string | null;
|
|
10
|
+
author?: string | null;
|
|
11
|
+
date_text?: string | null;
|
|
12
|
+
body?: string | null;
|
|
13
|
+
verified?: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
declare function normalizeDiscussionPayload(payload: DiscussionPayload): Record<string, unknown>;
|
|
17
|
+
export declare const __test__: {
|
|
18
|
+
normalizeDiscussionPayload: typeof normalizeDiscussionPayload;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { CommandExecutionError } from '../../errors.js';
|
|
2
|
+
import { cli, Strategy } from '../../registry.js';
|
|
3
|
+
import { buildDiscussionUrl, buildProvenance, cleanText, extractAsin, normalizeProductUrl, parseRatingValue, parseReviewCount, trimRatingPrefix, uniqueNonEmpty, assertUsableState, gotoAndReadState, } from './shared.js';
|
|
4
|
+
function normalizeDiscussionPayload(payload) {
|
|
5
|
+
const sourceUrl = cleanText(payload.href) || buildDiscussionUrl(payload.href ?? '');
|
|
6
|
+
const asin = extractAsin(payload.href ?? '') ?? null;
|
|
7
|
+
const averageRatingText = cleanText(payload.average_rating_text) || null;
|
|
8
|
+
const totalReviewCountText = cleanText(payload.total_review_count_text) || null;
|
|
9
|
+
const provenance = buildProvenance(sourceUrl);
|
|
10
|
+
return {
|
|
11
|
+
asin,
|
|
12
|
+
product_url: asin ? normalizeProductUrl(asin) : null,
|
|
13
|
+
discussion_url: sourceUrl,
|
|
14
|
+
...provenance,
|
|
15
|
+
average_rating_text: averageRatingText,
|
|
16
|
+
average_rating_value: parseRatingValue(averageRatingText),
|
|
17
|
+
total_review_count_text: totalReviewCountText,
|
|
18
|
+
total_review_count: parseReviewCount(totalReviewCountText),
|
|
19
|
+
qa_urls: uniqueNonEmpty(payload.qa_links ?? []),
|
|
20
|
+
review_samples: (payload.review_samples ?? []).map((sample) => ({
|
|
21
|
+
title: trimRatingPrefix(sample.title) || null,
|
|
22
|
+
rating_text: cleanText(sample.rating_text) || null,
|
|
23
|
+
rating_value: parseRatingValue(sample.rating_text),
|
|
24
|
+
author: cleanText(sample.author) || null,
|
|
25
|
+
date_text: cleanText(sample.date_text) || null,
|
|
26
|
+
body: cleanText(sample.body) || null,
|
|
27
|
+
verified_purchase: sample.verified === true,
|
|
28
|
+
})),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function readDiscussionPayload(page, input, limit) {
|
|
32
|
+
const url = buildDiscussionUrl(input);
|
|
33
|
+
const state = await gotoAndReadState(page, url, 2500, 'discussion');
|
|
34
|
+
assertUsableState(state, 'discussion');
|
|
35
|
+
return await page.evaluate(`
|
|
36
|
+
(() => ({
|
|
37
|
+
href: window.location.href,
|
|
38
|
+
title: document.title || '',
|
|
39
|
+
average_rating_text: document.querySelector('[data-hook="rating-out-of-text"]')?.textContent || '',
|
|
40
|
+
total_review_count_text: document.querySelector('[data-hook="total-review-count"]')?.textContent || '',
|
|
41
|
+
qa_links: Array.from(document.querySelectorAll('a[href*="ask/questions"]')).map((anchor) => anchor.href || ''),
|
|
42
|
+
review_samples: Array.from(document.querySelectorAll('[data-hook="review"]')).slice(0, ${limit}).map((card) => ({
|
|
43
|
+
title: card.querySelector('[data-hook="review-title"]')?.textContent || '',
|
|
44
|
+
rating_text:
|
|
45
|
+
card.querySelector('[data-hook="review-star-rating"]')?.textContent
|
|
46
|
+
|| card.querySelector('[data-hook="cmps-review-star-rating"]')?.textContent
|
|
47
|
+
|| '',
|
|
48
|
+
author: card.querySelector('.a-profile-name')?.textContent || '',
|
|
49
|
+
date_text: card.querySelector('[data-hook="review-date"]')?.textContent || '',
|
|
50
|
+
body: card.querySelector('[data-hook="review-body"]')?.textContent || '',
|
|
51
|
+
verified: !!card.querySelector('[data-hook="avp-badge"]'),
|
|
52
|
+
})),
|
|
53
|
+
}))()
|
|
54
|
+
`);
|
|
55
|
+
}
|
|
56
|
+
cli({
|
|
57
|
+
site: 'amazon',
|
|
58
|
+
name: 'discussion',
|
|
59
|
+
description: 'Amazon review summary and sample customer discussion from product review pages',
|
|
60
|
+
domain: 'amazon.com',
|
|
61
|
+
strategy: Strategy.COOKIE,
|
|
62
|
+
navigateBefore: false,
|
|
63
|
+
args: [
|
|
64
|
+
{
|
|
65
|
+
name: 'input',
|
|
66
|
+
required: true,
|
|
67
|
+
positional: true,
|
|
68
|
+
help: 'ASIN or product URL, for example B0FJS72893',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'limit',
|
|
72
|
+
type: 'int',
|
|
73
|
+
default: 10,
|
|
74
|
+
help: 'Maximum number of review samples to return (default 10)',
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
columns: ['asin', 'average_rating_value', 'total_review_count'],
|
|
78
|
+
func: async (page, kwargs) => {
|
|
79
|
+
const input = String(kwargs.input ?? '');
|
|
80
|
+
const limit = Math.max(1, Number(kwargs.limit) || 10);
|
|
81
|
+
const payload = await readDiscussionPayload(page, input, limit);
|
|
82
|
+
const normalized = normalizeDiscussionPayload(payload);
|
|
83
|
+
if (!normalized.average_rating_text && !normalized.total_review_count_text) {
|
|
84
|
+
throw new CommandExecutionError('amazon discussion page did not expose review summary', 'The review page may have changed or hit a robot check. Open the review page in Chrome and retry.');
|
|
85
|
+
}
|
|
86
|
+
return [normalized];
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
export const __test__ = {
|
|
90
|
+
normalizeDiscussionPayload,
|
|
91
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { __test__ } from './discussion.js';
|
|
3
|
+
describe('amazon discussion normalization', () => {
|
|
4
|
+
it('normalizes review summary and sample reviews', () => {
|
|
5
|
+
const result = __test__.normalizeDiscussionPayload({
|
|
6
|
+
href: 'https://www.amazon.com/product-reviews/B0FJS72893',
|
|
7
|
+
average_rating_text: '3.9 out of 5',
|
|
8
|
+
total_review_count_text: '27 global ratings',
|
|
9
|
+
qa_links: [],
|
|
10
|
+
review_samples: [
|
|
11
|
+
{
|
|
12
|
+
title: '5.0 out of 5 stars Great value and quality',
|
|
13
|
+
rating_text: '5.0 out of 5 stars',
|
|
14
|
+
author: 'GTreader2',
|
|
15
|
+
date_text: 'Reviewed in the United States on February 21, 2026',
|
|
16
|
+
body: 'Small but mighty.',
|
|
17
|
+
verified: true,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
});
|
|
21
|
+
expect(result.asin).toBe('B0FJS72893');
|
|
22
|
+
expect(result.average_rating_value).toBe(3.9);
|
|
23
|
+
expect(result.total_review_count).toBe(27);
|
|
24
|
+
expect(result.review_samples).toEqual([
|
|
25
|
+
{
|
|
26
|
+
title: 'Great value and quality',
|
|
27
|
+
rating_text: '5.0 out of 5 stars',
|
|
28
|
+
rating_value: 5,
|
|
29
|
+
author: 'GTreader2',
|
|
30
|
+
date_text: 'Reviewed in the United States on February 21, 2026',
|
|
31
|
+
body: 'Small but mighty.',
|
|
32
|
+
verified_purchase: true,
|
|
33
|
+
},
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface OfferPayload {
|
|
2
|
+
href?: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
price_text?: string | null;
|
|
5
|
+
merchant_info?: string | null;
|
|
6
|
+
sold_by?: string | null;
|
|
7
|
+
ships_from_text?: string | null;
|
|
8
|
+
offer_link?: string | null;
|
|
9
|
+
review_url?: string | null;
|
|
10
|
+
qa_url?: string | null;
|
|
11
|
+
buybox_text?: string | null;
|
|
12
|
+
}
|
|
13
|
+
declare function extractShipsFrom(text: string): string | null;
|
|
14
|
+
declare function extractSoldBy(text: string): string | null;
|
|
15
|
+
declare function isDeliveryLocationBlocked(text: string | null | undefined): boolean;
|
|
16
|
+
declare function normalizeOfferPayload(payload: OfferPayload): Record<string, unknown>;
|
|
17
|
+
export declare const __test__: {
|
|
18
|
+
extractShipsFrom: typeof extractShipsFrom;
|
|
19
|
+
extractSoldBy: typeof extractSoldBy;
|
|
20
|
+
isDeliveryLocationBlocked: typeof isDeliveryLocationBlocked;
|
|
21
|
+
normalizeOfferPayload: typeof normalizeOfferPayload;
|
|
22
|
+
};
|
|
23
|
+
export {};
|