@jackwener/opencli 1.7.15 → 1.7.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/README.zh-CN.md +9 -6
- package/cli-manifest.json +161 -31
- package/clis/chatgpt/ask.js +2 -1
- package/clis/chatgpt/detail.js +6 -1
- package/clis/chatgpt/read.js +2 -1
- package/clis/chatgpt/send.js +2 -1
- package/clis/chatgpt/utils.js +54 -12
- package/clis/chatgpt/utils.test.js +36 -1
- package/clis/claude/ask.js +22 -7
- package/clis/claude/detail.js +9 -2
- package/clis/claude/new.js +8 -2
- package/clis/claude/read.js +2 -1
- package/clis/claude/send.js +8 -3
- package/clis/claude/utils.js +27 -4
- package/clis/deepseek/ask.js +21 -8
- package/clis/deepseek/detail.js +9 -1
- package/clis/deepseek/new.js +13 -2
- package/clis/deepseek/read.js +2 -1
- package/clis/deepseek/utils.js +8 -1
- package/clis/linkedin/search.js +8 -11
- package/clis/maimai/search-talents.js +10 -6
- package/clis/openreview/author.js +58 -0
- package/clis/openreview/openreview.test.js +83 -1
- package/clis/openreview/utils.js +14 -0
- package/clis/reddit/comment.js +1 -0
- package/clis/reddit/frontpage.js +1 -0
- package/clis/reddit/popular.js +1 -0
- package/clis/reddit/read.js +2 -0
- package/clis/reddit/read.test.js +4 -0
- package/clis/reddit/save.js +1 -0
- package/clis/reddit/saved.js +1 -0
- package/clis/reddit/search.js +1 -0
- package/clis/reddit/subreddit.js +1 -0
- package/clis/reddit/subscribe.js +1 -0
- package/clis/reddit/upvote.js +1 -0
- package/clis/reddit/upvoted.js +1 -0
- package/clis/reddit/user-comments.js +1 -0
- package/clis/reddit/user-posts.js +1 -0
- package/clis/reddit/user.js +1 -0
- package/clis/twitter/article.js +7 -4
- package/clis/twitter/bookmark-folder.js +3 -5
- package/clis/twitter/bookmark-folder.test.js +5 -2
- package/clis/twitter/bookmark-folders.js +3 -5
- package/clis/twitter/bookmark-folders.test.js +3 -1
- package/clis/twitter/bookmarks.js +3 -5
- package/clis/twitter/download.js +1 -0
- package/clis/twitter/followers.js +1 -0
- package/clis/twitter/following.js +3 -6
- package/clis/twitter/following.test.js +2 -1
- package/clis/twitter/likes.js +3 -5
- package/clis/twitter/list-add.js +4 -3
- package/clis/twitter/list-add.test.js +23 -1
- package/clis/twitter/list-remove.js +4 -3
- package/clis/twitter/list-remove.test.js +23 -1
- package/clis/twitter/list-tweets.js +3 -5
- package/clis/twitter/lists.js +3 -5
- package/clis/twitter/notifications.js +1 -0
- package/clis/twitter/profile.js +7 -4
- package/clis/twitter/search.js +1 -0
- package/clis/twitter/thread.js +5 -7
- package/clis/twitter/timeline.js +5 -7
- package/clis/twitter/trending.js +4 -4
- package/clis/twitter/tweets.js +3 -6
- package/clis/youtube/like.js +6 -2
- package/clis/youtube/subscribe.js +6 -2
- package/clis/youtube/unlike.js +6 -2
- package/clis/youtube/unsubscribe.js +6 -2
- package/clis/youtube/utils.js +19 -13
- package/clis/youtube/utils.test.js +17 -1
- package/dist/src/browser/bridge.d.ts +1 -0
- package/dist/src/browser/bridge.js +1 -1
- package/dist/src/browser/cdp.d.ts +1 -0
- package/dist/src/browser/daemon-client.d.ts +2 -2
- package/dist/src/browser/daemon-client.js +6 -3
- package/dist/src/browser/daemon-client.test.js +10 -0
- package/dist/src/browser/page.d.ts +2 -1
- package/dist/src/browser/page.js +5 -1
- package/dist/src/cli.js +70 -2
- package/dist/src/cli.test.js +139 -7
- package/dist/src/commanderAdapter.js +7 -0
- package/dist/src/doctor.js +2 -2
- package/dist/src/doctor.test.js +4 -4
- package/dist/src/execution.d.ts +2 -0
- package/dist/src/execution.js +31 -6
- package/dist/src/execution.test.js +43 -16
- package/dist/src/external-clis.yaml +24 -0
- package/dist/src/help.d.ts +1 -0
- package/dist/src/help.js +29 -0
- package/dist/src/main.js +4 -14
- package/dist/src/runtime.d.ts +3 -0
- package/dist/src/runtime.js +1 -0
- package/dist/src/types.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ OpenCLI gives you one surface for three different kinds of automation:
|
|
|
14
14
|
- **Let AI Agents operate any website** — install the `opencli-adapter-author` skill in your AI agent (Claude Code, Cursor, etc.), and it can navigate, click, type/fill, extract, and inspect any page through your logged-in browser via `opencli browser` primitives.
|
|
15
15
|
- **Write new adapters** end-to-end with `opencli browser` + the `opencli-adapter-author` skill, which guides from first recon through field decoding, code, and `opencli browser verify`.
|
|
16
16
|
|
|
17
|
-
It also works as a **CLI hub** for local tools such as `gh`, `docker`, and other binaries you register yourself, plus **desktop app adapters** for Electron apps like Cursor, Codex, Antigravity, ChatGPT, and Notion.
|
|
17
|
+
It also works as a **CLI hub** for local tools such as `gh`, `docker`, `tg-cli`, `discord-cli`, `wx-cli`, and other binaries you register yourself, plus **desktop app adapters** for Electron apps like Cursor, Codex, Antigravity, ChatGPT, and Notion.
|
|
18
18
|
|
|
19
19
|
## Highlights
|
|
20
20
|
|
|
@@ -24,7 +24,7 @@ It also works as a **CLI hub** for local tools such as `gh`, `docker`, and other
|
|
|
24
24
|
- **Website → CLI** — Turn any website into a deterministic CLI: 100+ site surfaces are already registered, or write your own with the `opencli-adapter-author` skill + `opencli browser verify`.
|
|
25
25
|
- **Account-safe** — Reuses Chrome/Chromium logged-in state; your credentials never leave the browser.
|
|
26
26
|
- **AI Agent ready** — One skill takes you from site recon through API discovery, field decoding, adapter writing, and verification.
|
|
27
|
-
- **CLI Hub** — Discover, auto-install, and passthrough commands to any external CLI (gh, docker, obsidian, etc).
|
|
27
|
+
- **CLI Hub** — Discover, auto-install, and passthrough commands to any external CLI (gh, docker, obsidian, tg-cli, discord-cli, wx-cli, etc).
|
|
28
28
|
- **Zero LLM cost** — No tokens consumed at runtime. Run 10,000 times and pay nothing.
|
|
29
29
|
- **Deterministic** — Same command, same output schema, every time. Pipeable, scriptable, CI-friendly.
|
|
30
30
|
|
|
@@ -181,7 +181,7 @@ When the site you need is not yet covered, use the `opencli-adapter-author` skil
|
|
|
181
181
|
|
|
182
182
|
OpenCLI is not only for websites. It can also:
|
|
183
183
|
|
|
184
|
-
- expose local binaries like `gh`, `docker`, `obsidian`, or custom tools through `opencli <tool> ...`
|
|
184
|
+
- expose local binaries like `gh`, `docker`, `obsidian`, `tg-cli`, `discord-cli`, `wx-cli`, or custom tools through `opencli <tool> ...`
|
|
185
185
|
- control Electron desktop apps through dedicated adapters and CDP-backed integrations
|
|
186
186
|
|
|
187
187
|
## Prerequisites
|
|
@@ -198,8 +198,8 @@ OpenCLI is not only for websites. It can also:
|
|
|
198
198
|
|----------|---------|-------------|
|
|
199
199
|
| `OPENCLI_DAEMON_PORT` | `19825` | HTTP port for the daemon-extension bridge |
|
|
200
200
|
| `OPENCLI_PROFILE` | — | Browser Bridge profile alias/contextId to use when multiple Chrome profiles are connected |
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
201
|
+
| `OPENCLI_WINDOW` | command default | Set to `foreground` or `background` to override Browser Bridge window placement. Browser-backed commands also accept `--window <foreground\|background>`. |
|
|
202
|
+
| `OPENCLI_KEEP_TAB` | command default | Set to `true` or `false` to keep or release the browser tab lease after a browser-backed command. Browser-backed commands also accept `--keep-tab <true\|false>`. |
|
|
203
203
|
| `OPENCLI_BROWSER_REUSE` | adapter default | Set to `none` or `site` to override adapter browser tab reuse. The `--reuse <none\|site>` flag sets this. |
|
|
204
204
|
| `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | Seconds to wait for browser connection |
|
|
205
205
|
| `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | Seconds to wait for a single browser command |
|
|
@@ -208,7 +208,7 @@ OpenCLI is not only for websites. It can also:
|
|
|
208
208
|
| `OPENCLI_VERBOSE` | `false` | Enable verbose logging (`-v` flag also works) |
|
|
209
209
|
| `DEBUG_SNAPSHOT` | — | Set to `1` for DOM snapshot debug output |
|
|
210
210
|
|
|
211
|
-
|
|
211
|
+
`opencli browser *` uses a foreground browser window and keeps its tab lease by default. Browser-backed adapters use a background automation window and release one-shot tab leases by default. Some interactive adapters default to `--reuse site`, which also keeps the site tab lease; pass `--reuse none` for a one-shot tab.
|
|
212
212
|
|
|
213
213
|
## Update
|
|
214
214
|
|
|
@@ -294,6 +294,9 @@ OpenCLI acts as a universal hub for your existing command-line tools — unified
|
|
|
294
294
|
| **lark-cli** | Lark/Feishu — messages, docs, calendar, tasks, 200+ commands | `opencli lark-cli calendar +agenda` |
|
|
295
295
|
| **dws** | DingTalk — cross-platform CLI for DingTalk's full suite, designed for humans and AI agents | `opencli dws msg send --to user "hello"` |
|
|
296
296
|
| **wecom-cli** | WeCom/企业微信 — CLI for WeCom open platform, for humans and AI agents | `opencli wecom-cli msg send --to user "hello"` |
|
|
297
|
+
| **tg-cli** | Telegram — local-first sync, search, and export via MTProto for AI agents | `opencli tg search "AI news" -f json` |
|
|
298
|
+
| **discord-cli** | Discord — local-first sync, search, and export via SQLite for AI agents | `opencli discord recent --channel general` |
|
|
299
|
+
| **wx-cli** | WeChat — query local WeChat data: sessions, messages, search, contacts, export | `opencli wx search "OpenCLI"` |
|
|
297
300
|
| **vercel** | Vercel — deploy projects, manage domains, env vars, logs | `opencli vercel deploy --prod` |
|
|
298
301
|
|
|
299
302
|
**Register your own** — add any local CLI so AI agents can discover it via `opencli list`:
|
package/README.zh-CN.md
CHANGED
|
@@ -14,7 +14,7 @@ OpenCLI 可以用同一套 CLI 做三类事情:
|
|
|
14
14
|
- **让 AI Agent 操作任意网站**:在你的 AI Agent(Claude Code、Cursor 等)中安装 `opencli-adapter-author` skill,Agent 就能用你的已登录浏览器导航、点击、输入/填充、提取任意网页内容。
|
|
15
15
|
- **把新网站写成 CLI**:用 `opencli browser` 原语 + `opencli-adapter-author` skill,从站点侦察、API 发现、字段解码到 `opencli browser verify` 一条龙。
|
|
16
16
|
|
|
17
|
-
除了网站能力,OpenCLI 还是一个 **CLI 枢纽**:你可以把 `gh`、`docker` 等本地工具统一注册到 `opencli` 下,也可以通过桌面端适配器控制 Cursor、Codex、Antigravity、ChatGPT、Notion 等 Electron 应用。
|
|
17
|
+
除了网站能力,OpenCLI 还是一个 **CLI 枢纽**:你可以把 `gh`、`docker`、`tg-cli`、`discord-cli`、`wx-cli` 等本地工具统一注册到 `opencli` 下,也可以通过桌面端适配器控制 Cursor、Codex、Antigravity、ChatGPT、Notion 等 Electron 应用。
|
|
18
18
|
|
|
19
19
|
## 亮点
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ OpenCLI 可以用同一套 CLI 做三类事情:
|
|
|
23
23
|
- **网站 → CLI** — 把任何网站变成确定性 CLI:100+ 站点能力已注册,或用 `opencli-adapter-author` skill + `opencli browser verify` 自己写。
|
|
24
24
|
- **账号安全** — 复用 Chrome/Chromium 登录态,凭证永远不会离开浏览器。
|
|
25
25
|
- **面向 AI Agent** — 一个 skill 带你走完站点侦察、API 发现、字段解码、适配器编写、验证的全流程。
|
|
26
|
-
- **CLI 枢纽** — 统一发现、自动安装、纯透传任何外部 CLI(gh、docker、obsidian 等)。
|
|
26
|
+
- **CLI 枢纽** — 统一发现、自动安装、纯透传任何外部 CLI(gh、docker、obsidian、tg-cli、discord-cli、wx-cli 等)。
|
|
27
27
|
- **零 LLM 成本** — 运行时不消耗模型 token,跑 10,000 次也不花一分钱。
|
|
28
28
|
- **确定性输出** — 相同命令,相同输出结构,每次一致。可管道、可脚本、CI 友好。
|
|
29
29
|
|
|
@@ -165,7 +165,7 @@ Agent 在内部自动处理所有 `opencli browser` 命令——你只需用自
|
|
|
165
165
|
|
|
166
166
|
OpenCLI 不只是网站 CLI,还可以:
|
|
167
167
|
|
|
168
|
-
- 统一代理本地二进制工具,例如 `gh`、`docker`、`obsidian`
|
|
168
|
+
- 统一代理本地二进制工具,例如 `gh`、`docker`、`obsidian`、`tg-cli`、`discord-cli`、`wx-cli`
|
|
169
169
|
- 通过专门适配器和 CDP 集成控制 Electron 桌面应用
|
|
170
170
|
|
|
171
171
|
## 前置要求
|
|
@@ -181,8 +181,8 @@ OpenCLI 不只是网站 CLI,还可以:
|
|
|
181
181
|
| 变量 | 默认值 | 说明 |
|
|
182
182
|
|------|--------|------|
|
|
183
183
|
| `OPENCLI_DAEMON_PORT` | `19825` | daemon-extension 通信端口 |
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
184
|
+
| `OPENCLI_WINDOW` | 命令默认值 | 设为 `foreground` 或 `background` 来覆盖 Browser Bridge 窗口位置。浏览器型命令也支持 `--window <foreground\|background>` |
|
|
185
|
+
| `OPENCLI_KEEP_TAB` | 命令默认值 | 设为 `true` 或 `false` 来控制浏览器型命令结束后是否保留 tab lease。浏览器型命令也支持 `--keep-tab <true\|false>` |
|
|
186
186
|
| `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | 浏览器连接超时(秒) |
|
|
187
187
|
| `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | 单个浏览器命令超时(秒) |
|
|
188
188
|
| `OPENCLI_CDP_ENDPOINT` | — | Chrome DevTools Protocol 端点,用于远程浏览器或 Electron 应用 |
|
|
@@ -190,7 +190,7 @@ OpenCLI 不只是网站 CLI,还可以:
|
|
|
190
190
|
| `OPENCLI_VERBOSE` | `false` | 启用详细日志(`-v` 也可以) |
|
|
191
191
|
| `DEBUG_SNAPSHOT` | — | 设为 `1` 输出 DOM 快照调试信息 |
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
`opencli browser *` 默认使用前台窗口并保留 tab lease,直到你手动执行 `opencli browser close` 或等空闲超时。浏览器型 adapter 默认使用后台 automation 窗口并在命令结束后释放 tab lease;如果需要调试最终页面,可以传 `--window foreground --keep-tab true`。
|
|
194
194
|
|
|
195
195
|
## 更新
|
|
196
196
|
|
|
@@ -336,6 +336,9 @@ OpenCLI 也可以作为你现有命令行工具的统一入口,负责发现、
|
|
|
336
336
|
| **lark-cli** | 飞书 CLI — 消息、文档、日历、任务,200+ 命令 | `opencli lark-cli calendar +agenda` |
|
|
337
337
|
| **dws** | 钉钉 CLI — 钉钉全套产品能力的跨平台命令行工具,支持人类和 AI Agent 使用 | `opencli dws msg send --to user "hello"` |
|
|
338
338
|
| **wecom-cli** | 企业微信 CLI — 企业微信开放平台命令行工具,支持人类和 AI Agent 使用 | `opencli wecom-cli msg send --to user "hello"` |
|
|
339
|
+
| **tg-cli** | Telegram CLI — 基于 MTProto 的本地优先同步、搜索、导出,面向 AI Agent | `opencli tg search "AI news" -f json` |
|
|
340
|
+
| **discord-cli** | Discord CLI — 基于 SQLite 的本地优先同步、搜索、导出,面向 AI Agent | `opencli discord recent --channel general` |
|
|
341
|
+
| **wx-cli** | 微信本地数据 CLI — 会话、聊天记录、搜索、联系人、导出 | `opencli wx search "OpenCLI"` |
|
|
339
342
|
| **vercel** | Vercel — 部署项目、管理域名、环境变量、日志 | `opencli vercel deploy --prod` |
|
|
340
343
|
|
|
341
344
|
**零配置透传**:OpenCLI 会把你的输入原样转发给底层二进制,保留原生 stdout / stderr 行为。
|
package/cli-manifest.json
CHANGED
|
@@ -17181,6 +17181,43 @@
|
|
|
17181
17181
|
"modulePath": "openfda/food-recall.js",
|
|
17182
17182
|
"sourceFile": "openfda/food-recall.js"
|
|
17183
17183
|
},
|
|
17184
|
+
{
|
|
17185
|
+
"site": "openreview",
|
|
17186
|
+
"name": "author",
|
|
17187
|
+
"description": "List OpenReview submissions by an author profile id (newest first)",
|
|
17188
|
+
"access": "read",
|
|
17189
|
+
"domain": "openreview.net",
|
|
17190
|
+
"strategy": "public",
|
|
17191
|
+
"browser": false,
|
|
17192
|
+
"args": [
|
|
17193
|
+
{
|
|
17194
|
+
"name": "profile",
|
|
17195
|
+
"type": "str",
|
|
17196
|
+
"required": true,
|
|
17197
|
+
"positional": true,
|
|
17198
|
+
"help": "OpenReview profile id (e.g. \"~Yoshua_Bengio1\"). Find it on the author profile URL on openreview.net."
|
|
17199
|
+
},
|
|
17200
|
+
{
|
|
17201
|
+
"name": "limit",
|
|
17202
|
+
"type": "int",
|
|
17203
|
+
"default": 50,
|
|
17204
|
+
"required": false,
|
|
17205
|
+
"help": "Max submissions (1-1000)"
|
|
17206
|
+
}
|
|
17207
|
+
],
|
|
17208
|
+
"columns": [
|
|
17209
|
+
"rank",
|
|
17210
|
+
"id",
|
|
17211
|
+
"title",
|
|
17212
|
+
"authors",
|
|
17213
|
+
"venue",
|
|
17214
|
+
"pdate",
|
|
17215
|
+
"url"
|
|
17216
|
+
],
|
|
17217
|
+
"type": "js",
|
|
17218
|
+
"modulePath": "openreview/author.js",
|
|
17219
|
+
"sourceFile": "openreview/author.js"
|
|
17220
|
+
},
|
|
17184
17221
|
{
|
|
17185
17222
|
"site": "openreview",
|
|
17186
17223
|
"name": "paper",
|
|
@@ -19110,7 +19147,10 @@
|
|
|
19110
19147
|
"type": "js",
|
|
19111
19148
|
"modulePath": "reddit/comment.js",
|
|
19112
19149
|
"sourceFile": "reddit/comment.js",
|
|
19113
|
-
"navigateBefore": "https://reddit.com"
|
|
19150
|
+
"navigateBefore": "https://reddit.com",
|
|
19151
|
+
"browserSession": {
|
|
19152
|
+
"reuse": "site"
|
|
19153
|
+
}
|
|
19114
19154
|
},
|
|
19115
19155
|
{
|
|
19116
19156
|
"site": "reddit",
|
|
@@ -19140,7 +19180,10 @@
|
|
|
19140
19180
|
"type": "js",
|
|
19141
19181
|
"modulePath": "reddit/frontpage.js",
|
|
19142
19182
|
"sourceFile": "reddit/frontpage.js",
|
|
19143
|
-
"navigateBefore": "https://reddit.com"
|
|
19183
|
+
"navigateBefore": "https://reddit.com",
|
|
19184
|
+
"browserSession": {
|
|
19185
|
+
"reuse": "site"
|
|
19186
|
+
}
|
|
19144
19187
|
},
|
|
19145
19188
|
{
|
|
19146
19189
|
"site": "reddit",
|
|
@@ -19209,7 +19252,10 @@
|
|
|
19209
19252
|
"type": "js",
|
|
19210
19253
|
"modulePath": "reddit/popular.js",
|
|
19211
19254
|
"sourceFile": "reddit/popular.js",
|
|
19212
|
-
"navigateBefore": "https://reddit.com"
|
|
19255
|
+
"navigateBefore": "https://reddit.com",
|
|
19256
|
+
"browserSession": {
|
|
19257
|
+
"reuse": "site"
|
|
19258
|
+
}
|
|
19213
19259
|
},
|
|
19214
19260
|
{
|
|
19215
19261
|
"site": "reddit",
|
|
@@ -19272,7 +19318,10 @@
|
|
|
19272
19318
|
"type": "js",
|
|
19273
19319
|
"modulePath": "reddit/read.js",
|
|
19274
19320
|
"sourceFile": "reddit/read.js",
|
|
19275
|
-
"navigateBefore": "https://reddit.com"
|
|
19321
|
+
"navigateBefore": "https://reddit.com",
|
|
19322
|
+
"browserSession": {
|
|
19323
|
+
"reuse": "site"
|
|
19324
|
+
}
|
|
19276
19325
|
},
|
|
19277
19326
|
{
|
|
19278
19327
|
"site": "reddit",
|
|
@@ -19305,7 +19354,10 @@
|
|
|
19305
19354
|
"type": "js",
|
|
19306
19355
|
"modulePath": "reddit/save.js",
|
|
19307
19356
|
"sourceFile": "reddit/save.js",
|
|
19308
|
-
"navigateBefore": "https://reddit.com"
|
|
19357
|
+
"navigateBefore": "https://reddit.com",
|
|
19358
|
+
"browserSession": {
|
|
19359
|
+
"reuse": "site"
|
|
19360
|
+
}
|
|
19309
19361
|
},
|
|
19310
19362
|
{
|
|
19311
19363
|
"site": "reddit",
|
|
@@ -19334,7 +19386,10 @@
|
|
|
19334
19386
|
"type": "js",
|
|
19335
19387
|
"modulePath": "reddit/saved.js",
|
|
19336
19388
|
"sourceFile": "reddit/saved.js",
|
|
19337
|
-
"navigateBefore": "https://reddit.com"
|
|
19389
|
+
"navigateBefore": "https://reddit.com",
|
|
19390
|
+
"browserSession": {
|
|
19391
|
+
"reuse": "site"
|
|
19392
|
+
}
|
|
19338
19393
|
},
|
|
19339
19394
|
{
|
|
19340
19395
|
"site": "reddit",
|
|
@@ -19392,7 +19447,10 @@
|
|
|
19392
19447
|
"type": "js",
|
|
19393
19448
|
"modulePath": "reddit/search.js",
|
|
19394
19449
|
"sourceFile": "reddit/search.js",
|
|
19395
|
-
"navigateBefore": "https://reddit.com"
|
|
19450
|
+
"navigateBefore": "https://reddit.com",
|
|
19451
|
+
"browserSession": {
|
|
19452
|
+
"reuse": "site"
|
|
19453
|
+
}
|
|
19396
19454
|
},
|
|
19397
19455
|
{
|
|
19398
19456
|
"site": "reddit",
|
|
@@ -19442,7 +19500,10 @@
|
|
|
19442
19500
|
"type": "js",
|
|
19443
19501
|
"modulePath": "reddit/subreddit.js",
|
|
19444
19502
|
"sourceFile": "reddit/subreddit.js",
|
|
19445
|
-
"navigateBefore": "https://reddit.com"
|
|
19503
|
+
"navigateBefore": "https://reddit.com",
|
|
19504
|
+
"browserSession": {
|
|
19505
|
+
"reuse": "site"
|
|
19506
|
+
}
|
|
19446
19507
|
},
|
|
19447
19508
|
{
|
|
19448
19509
|
"site": "reddit",
|
|
@@ -19475,7 +19536,10 @@
|
|
|
19475
19536
|
"type": "js",
|
|
19476
19537
|
"modulePath": "reddit/subscribe.js",
|
|
19477
19538
|
"sourceFile": "reddit/subscribe.js",
|
|
19478
|
-
"navigateBefore": "https://reddit.com"
|
|
19539
|
+
"navigateBefore": "https://reddit.com",
|
|
19540
|
+
"browserSession": {
|
|
19541
|
+
"reuse": "site"
|
|
19542
|
+
}
|
|
19479
19543
|
},
|
|
19480
19544
|
{
|
|
19481
19545
|
"site": "reddit",
|
|
@@ -19508,7 +19572,10 @@
|
|
|
19508
19572
|
"type": "js",
|
|
19509
19573
|
"modulePath": "reddit/upvote.js",
|
|
19510
19574
|
"sourceFile": "reddit/upvote.js",
|
|
19511
|
-
"navigateBefore": "https://reddit.com"
|
|
19575
|
+
"navigateBefore": "https://reddit.com",
|
|
19576
|
+
"browserSession": {
|
|
19577
|
+
"reuse": "site"
|
|
19578
|
+
}
|
|
19512
19579
|
},
|
|
19513
19580
|
{
|
|
19514
19581
|
"site": "reddit",
|
|
@@ -19537,7 +19604,10 @@
|
|
|
19537
19604
|
"type": "js",
|
|
19538
19605
|
"modulePath": "reddit/upvoted.js",
|
|
19539
19606
|
"sourceFile": "reddit/upvoted.js",
|
|
19540
|
-
"navigateBefore": "https://reddit.com"
|
|
19607
|
+
"navigateBefore": "https://reddit.com",
|
|
19608
|
+
"browserSession": {
|
|
19609
|
+
"reuse": "site"
|
|
19610
|
+
}
|
|
19541
19611
|
},
|
|
19542
19612
|
{
|
|
19543
19613
|
"site": "reddit",
|
|
@@ -19563,7 +19633,10 @@
|
|
|
19563
19633
|
"type": "js",
|
|
19564
19634
|
"modulePath": "reddit/user.js",
|
|
19565
19635
|
"sourceFile": "reddit/user.js",
|
|
19566
|
-
"navigateBefore": "https://reddit.com"
|
|
19636
|
+
"navigateBefore": "https://reddit.com",
|
|
19637
|
+
"browserSession": {
|
|
19638
|
+
"reuse": "site"
|
|
19639
|
+
}
|
|
19567
19640
|
},
|
|
19568
19641
|
{
|
|
19569
19642
|
"site": "reddit",
|
|
@@ -19598,7 +19671,10 @@
|
|
|
19598
19671
|
"type": "js",
|
|
19599
19672
|
"modulePath": "reddit/user-comments.js",
|
|
19600
19673
|
"sourceFile": "reddit/user-comments.js",
|
|
19601
|
-
"navigateBefore": "https://reddit.com"
|
|
19674
|
+
"navigateBefore": "https://reddit.com",
|
|
19675
|
+
"browserSession": {
|
|
19676
|
+
"reuse": "site"
|
|
19677
|
+
}
|
|
19602
19678
|
},
|
|
19603
19679
|
{
|
|
19604
19680
|
"site": "reddit",
|
|
@@ -19634,7 +19710,10 @@
|
|
|
19634
19710
|
"type": "js",
|
|
19635
19711
|
"modulePath": "reddit/user-posts.js",
|
|
19636
19712
|
"sourceFile": "reddit/user-posts.js",
|
|
19637
|
-
"navigateBefore": "https://reddit.com"
|
|
19713
|
+
"navigateBefore": "https://reddit.com",
|
|
19714
|
+
"browserSession": {
|
|
19715
|
+
"reuse": "site"
|
|
19716
|
+
}
|
|
19638
19717
|
},
|
|
19639
19718
|
{
|
|
19640
19719
|
"site": "rest-countries",
|
|
@@ -22175,7 +22254,10 @@
|
|
|
22175
22254
|
"type": "js",
|
|
22176
22255
|
"modulePath": "twitter/article.js",
|
|
22177
22256
|
"sourceFile": "twitter/article.js",
|
|
22178
|
-
"navigateBefore": "https://x.com"
|
|
22257
|
+
"navigateBefore": "https://x.com",
|
|
22258
|
+
"browserSession": {
|
|
22259
|
+
"reuse": "site"
|
|
22260
|
+
}
|
|
22179
22261
|
},
|
|
22180
22262
|
{
|
|
22181
22263
|
"site": "twitter",
|
|
@@ -22273,7 +22355,10 @@
|
|
|
22273
22355
|
"type": "js",
|
|
22274
22356
|
"modulePath": "twitter/bookmark-folder.js",
|
|
22275
22357
|
"sourceFile": "twitter/bookmark-folder.js",
|
|
22276
|
-
"navigateBefore": "https://x.com"
|
|
22358
|
+
"navigateBefore": "https://x.com",
|
|
22359
|
+
"browserSession": {
|
|
22360
|
+
"reuse": "site"
|
|
22361
|
+
}
|
|
22277
22362
|
},
|
|
22278
22363
|
{
|
|
22279
22364
|
"site": "twitter",
|
|
@@ -22293,7 +22378,10 @@
|
|
|
22293
22378
|
"type": "js",
|
|
22294
22379
|
"modulePath": "twitter/bookmark-folders.js",
|
|
22295
22380
|
"sourceFile": "twitter/bookmark-folders.js",
|
|
22296
|
-
"navigateBefore": "https://x.com"
|
|
22381
|
+
"navigateBefore": "https://x.com",
|
|
22382
|
+
"browserSession": {
|
|
22383
|
+
"reuse": "site"
|
|
22384
|
+
}
|
|
22297
22385
|
},
|
|
22298
22386
|
{
|
|
22299
22387
|
"site": "twitter",
|
|
@@ -22332,7 +22420,10 @@
|
|
|
22332
22420
|
"type": "js",
|
|
22333
22421
|
"modulePath": "twitter/bookmarks.js",
|
|
22334
22422
|
"sourceFile": "twitter/bookmarks.js",
|
|
22335
|
-
"navigateBefore": "https://x.com"
|
|
22423
|
+
"navigateBefore": "https://x.com",
|
|
22424
|
+
"browserSession": {
|
|
22425
|
+
"reuse": "site"
|
|
22426
|
+
}
|
|
22336
22427
|
},
|
|
22337
22428
|
{
|
|
22338
22429
|
"site": "twitter",
|
|
@@ -22406,7 +22497,10 @@
|
|
|
22406
22497
|
"type": "js",
|
|
22407
22498
|
"modulePath": "twitter/download.js",
|
|
22408
22499
|
"sourceFile": "twitter/download.js",
|
|
22409
|
-
"navigateBefore": "https://x.com"
|
|
22500
|
+
"navigateBefore": "https://x.com",
|
|
22501
|
+
"browserSession": {
|
|
22502
|
+
"reuse": "site"
|
|
22503
|
+
}
|
|
22410
22504
|
},
|
|
22411
22505
|
{
|
|
22412
22506
|
"site": "twitter",
|
|
@@ -22466,7 +22560,10 @@
|
|
|
22466
22560
|
"type": "js",
|
|
22467
22561
|
"modulePath": "twitter/followers.js",
|
|
22468
22562
|
"sourceFile": "twitter/followers.js",
|
|
22469
|
-
"navigateBefore": true
|
|
22563
|
+
"navigateBefore": true,
|
|
22564
|
+
"browserSession": {
|
|
22565
|
+
"reuse": "site"
|
|
22566
|
+
}
|
|
22470
22567
|
},
|
|
22471
22568
|
{
|
|
22472
22569
|
"site": "twitter",
|
|
@@ -22501,7 +22598,10 @@
|
|
|
22501
22598
|
"type": "js",
|
|
22502
22599
|
"modulePath": "twitter/following.js",
|
|
22503
22600
|
"sourceFile": "twitter/following.js",
|
|
22504
|
-
"navigateBefore": "https://x.com"
|
|
22601
|
+
"navigateBefore": "https://x.com",
|
|
22602
|
+
"browserSession": {
|
|
22603
|
+
"reuse": "site"
|
|
22604
|
+
}
|
|
22505
22605
|
},
|
|
22506
22606
|
{
|
|
22507
22607
|
"site": "twitter",
|
|
@@ -22601,7 +22701,10 @@
|
|
|
22601
22701
|
"type": "js",
|
|
22602
22702
|
"modulePath": "twitter/likes.js",
|
|
22603
22703
|
"sourceFile": "twitter/likes.js",
|
|
22604
|
-
"navigateBefore": "https://x.com"
|
|
22704
|
+
"navigateBefore": "https://x.com",
|
|
22705
|
+
"browserSession": {
|
|
22706
|
+
"reuse": "site"
|
|
22707
|
+
}
|
|
22605
22708
|
},
|
|
22606
22709
|
{
|
|
22607
22710
|
"site": "twitter",
|
|
@@ -22719,7 +22822,10 @@
|
|
|
22719
22822
|
"type": "js",
|
|
22720
22823
|
"modulePath": "twitter/list-tweets.js",
|
|
22721
22824
|
"sourceFile": "twitter/list-tweets.js",
|
|
22722
|
-
"navigateBefore": "https://x.com"
|
|
22825
|
+
"navigateBefore": "https://x.com",
|
|
22826
|
+
"browserSession": {
|
|
22827
|
+
"reuse": "site"
|
|
22828
|
+
}
|
|
22723
22829
|
},
|
|
22724
22830
|
{
|
|
22725
22831
|
"site": "twitter",
|
|
@@ -22748,7 +22854,10 @@
|
|
|
22748
22854
|
"type": "js",
|
|
22749
22855
|
"modulePath": "twitter/lists.js",
|
|
22750
22856
|
"sourceFile": "twitter/lists.js",
|
|
22751
|
-
"navigateBefore": "https://x.com"
|
|
22857
|
+
"navigateBefore": "https://x.com",
|
|
22858
|
+
"browserSession": {
|
|
22859
|
+
"reuse": "site"
|
|
22860
|
+
}
|
|
22752
22861
|
},
|
|
22753
22862
|
{
|
|
22754
22863
|
"site": "twitter",
|
|
@@ -22777,7 +22886,10 @@
|
|
|
22777
22886
|
"type": "js",
|
|
22778
22887
|
"modulePath": "twitter/notifications.js",
|
|
22779
22888
|
"sourceFile": "twitter/notifications.js",
|
|
22780
|
-
"navigateBefore": true
|
|
22889
|
+
"navigateBefore": true,
|
|
22890
|
+
"browserSession": {
|
|
22891
|
+
"reuse": "site"
|
|
22892
|
+
}
|
|
22781
22893
|
},
|
|
22782
22894
|
{
|
|
22783
22895
|
"site": "twitter",
|
|
@@ -22845,7 +22957,10 @@
|
|
|
22845
22957
|
"type": "js",
|
|
22846
22958
|
"modulePath": "twitter/profile.js",
|
|
22847
22959
|
"sourceFile": "twitter/profile.js",
|
|
22848
|
-
"navigateBefore": "https://x.com"
|
|
22960
|
+
"navigateBefore": "https://x.com",
|
|
22961
|
+
"browserSession": {
|
|
22962
|
+
"reuse": "site"
|
|
22963
|
+
}
|
|
22849
22964
|
},
|
|
22850
22965
|
{
|
|
22851
22966
|
"site": "twitter",
|
|
@@ -23113,7 +23228,10 @@
|
|
|
23113
23228
|
"type": "js",
|
|
23114
23229
|
"modulePath": "twitter/search.js",
|
|
23115
23230
|
"sourceFile": "twitter/search.js",
|
|
23116
|
-
"navigateBefore": true
|
|
23231
|
+
"navigateBefore": true,
|
|
23232
|
+
"browserSession": {
|
|
23233
|
+
"reuse": "site"
|
|
23234
|
+
}
|
|
23117
23235
|
},
|
|
23118
23236
|
{
|
|
23119
23237
|
"site": "twitter",
|
|
@@ -23159,7 +23277,10 @@
|
|
|
23159
23277
|
"type": "js",
|
|
23160
23278
|
"modulePath": "twitter/thread.js",
|
|
23161
23279
|
"sourceFile": "twitter/thread.js",
|
|
23162
|
-
"navigateBefore": "https://x.com"
|
|
23280
|
+
"navigateBefore": "https://x.com",
|
|
23281
|
+
"browserSession": {
|
|
23282
|
+
"reuse": "site"
|
|
23283
|
+
}
|
|
23163
23284
|
},
|
|
23164
23285
|
{
|
|
23165
23286
|
"site": "twitter",
|
|
@@ -23212,7 +23333,10 @@
|
|
|
23212
23333
|
"type": "js",
|
|
23213
23334
|
"modulePath": "twitter/timeline.js",
|
|
23214
23335
|
"sourceFile": "twitter/timeline.js",
|
|
23215
|
-
"navigateBefore": "https://x.com"
|
|
23336
|
+
"navigateBefore": "https://x.com",
|
|
23337
|
+
"browserSession": {
|
|
23338
|
+
"reuse": "site"
|
|
23339
|
+
}
|
|
23216
23340
|
},
|
|
23217
23341
|
{
|
|
23218
23342
|
"site": "twitter",
|
|
@@ -23239,7 +23363,10 @@
|
|
|
23239
23363
|
"type": "js",
|
|
23240
23364
|
"modulePath": "twitter/trending.js",
|
|
23241
23365
|
"sourceFile": "twitter/trending.js",
|
|
23242
|
-
"navigateBefore": "https://x.com"
|
|
23366
|
+
"navigateBefore": "https://x.com",
|
|
23367
|
+
"browserSession": {
|
|
23368
|
+
"reuse": "site"
|
|
23369
|
+
}
|
|
23243
23370
|
},
|
|
23244
23371
|
{
|
|
23245
23372
|
"site": "twitter",
|
|
@@ -23289,7 +23416,10 @@
|
|
|
23289
23416
|
"type": "js",
|
|
23290
23417
|
"modulePath": "twitter/tweets.js",
|
|
23291
23418
|
"sourceFile": "twitter/tweets.js",
|
|
23292
|
-
"navigateBefore": "https://x.com"
|
|
23419
|
+
"navigateBefore": "https://x.com",
|
|
23420
|
+
"browserSession": {
|
|
23421
|
+
"reuse": "site"
|
|
23422
|
+
}
|
|
23293
23423
|
},
|
|
23294
23424
|
{
|
|
23295
23425
|
"site": "twitter",
|
package/clis/chatgpt/ask.js
CHANGED
|
@@ -43,7 +43,8 @@ export const askCommand = cli({
|
|
|
43
43
|
} else {
|
|
44
44
|
await ensureOnChatGPT(page);
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
// startNewChat / ensureOnChatGPT now wait for the composer selector
|
|
47
|
+
// after navigating, so the previous standalone 2 s settle is redundant.
|
|
47
48
|
await ensureChatGPTComposer(page, 'ChatGPT ask requires a logged-in ChatGPT session with a visible composer.');
|
|
48
49
|
|
|
49
50
|
const baseline = await getBubbleCount(page);
|
package/clis/chatgpt/detail.js
CHANGED
|
@@ -3,6 +3,7 @@ import { EmptyResultError } from '@jackwener/opencli/errors';
|
|
|
3
3
|
import {
|
|
4
4
|
CHATGPT_DOMAIN,
|
|
5
5
|
CHATGPT_URL,
|
|
6
|
+
CONVERSATION_MESSAGE_SELECTOR,
|
|
6
7
|
ensureChatGPTLogin,
|
|
7
8
|
getVisibleMessages,
|
|
8
9
|
messageHtmlToMarkdown,
|
|
@@ -29,7 +30,11 @@ export const detailCommand = cli({
|
|
|
29
30
|
const id = parseChatGPTConversationId(kwargs.id);
|
|
30
31
|
const wantMarkdown = normalizeBooleanFlag(kwargs.markdown, false);
|
|
31
32
|
await page.goto(`${CHATGPT_URL}/c/${id}`, { settleMs: 2000 });
|
|
32
|
-
|
|
33
|
+
try {
|
|
34
|
+
await page.wait({ selector: CONVERSATION_MESSAGE_SELECTOR, timeout: 10 });
|
|
35
|
+
} catch {
|
|
36
|
+
// Empty conversation, missing access, or login redirect — handled by ensureChatGPTLogin / EmptyResultError below.
|
|
37
|
+
}
|
|
33
38
|
await ensureChatGPTLogin(page, 'ChatGPT detail requires a logged-in ChatGPT session.');
|
|
34
39
|
const messages = await getVisibleMessages(page);
|
|
35
40
|
if (!messages.length) {
|
package/clis/chatgpt/read.js
CHANGED
|
@@ -25,8 +25,9 @@ export const readCommand = cli({
|
|
|
25
25
|
columns: ['Index', 'Role', 'Text'],
|
|
26
26
|
func: async (page, kwargs) => {
|
|
27
27
|
const wantMarkdown = normalizeBooleanFlag(kwargs.markdown, false);
|
|
28
|
+
// ensureOnChatGPT now waits for the composer selector after navigating,
|
|
29
|
+
// so the previous standalone 2 s settle is redundant.
|
|
28
30
|
await ensureOnChatGPT(page);
|
|
29
|
-
await page.wait(2);
|
|
30
31
|
await ensureChatGPTLogin(page, 'ChatGPT read requires a logged-in ChatGPT session.');
|
|
31
32
|
const messages = await getVisibleMessages(page);
|
|
32
33
|
if (!messages.length) {
|
package/clis/chatgpt/send.js
CHANGED
|
@@ -34,7 +34,8 @@ export const sendCommand = cli({
|
|
|
34
34
|
} else {
|
|
35
35
|
await ensureOnChatGPT(page);
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
// startNewChat / ensureOnChatGPT now wait for the composer selector
|
|
38
|
+
// after navigating, so the previous standalone 2 s settle is redundant.
|
|
38
39
|
await ensureChatGPTComposer(page, 'ChatGPT send requires a logged-in ChatGPT session with a visible composer.');
|
|
39
40
|
|
|
40
41
|
const sent = await sendChatGPTMessage(page, prompt);
|