@jackwener/opencli 0.8.0 → 0.9.1
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 +7 -2
- package/README.zh-CN.md +9 -2
- package/SKILL.md +11 -2
- package/dist/cli-manifest.json +343 -0
- package/dist/clis/antigravity/dump.d.ts +1 -0
- package/dist/clis/antigravity/dump.js +28 -0
- package/dist/clis/antigravity/extract-code.d.ts +1 -0
- package/dist/clis/antigravity/extract-code.js +32 -0
- package/dist/clis/antigravity/model.d.ts +1 -0
- package/dist/clis/antigravity/model.js +44 -0
- package/dist/clis/antigravity/new.d.ts +1 -0
- package/dist/clis/antigravity/new.js +25 -0
- package/dist/clis/antigravity/read.d.ts +1 -0
- package/dist/clis/antigravity/read.js +34 -0
- package/dist/clis/antigravity/send.d.ts +1 -0
- package/dist/clis/antigravity/send.js +35 -0
- package/dist/clis/antigravity/status.d.ts +1 -0
- package/dist/clis/antigravity/status.js +18 -0
- package/dist/clis/antigravity/watch.d.ts +1 -0
- package/dist/clis/antigravity/watch.js +41 -0
- package/dist/clis/codex/dump.d.ts +1 -0
- package/dist/clis/codex/dump.js +25 -0
- package/dist/clis/codex/extract-diff.d.ts +1 -0
- package/dist/clis/codex/extract-diff.js +44 -0
- package/dist/clis/codex/new.d.ts +1 -0
- package/dist/clis/codex/new.js +25 -0
- package/dist/clis/codex/read.d.ts +1 -0
- package/dist/clis/codex/read.js +31 -0
- package/dist/clis/codex/send.d.ts +1 -0
- package/dist/clis/codex/send.js +44 -0
- package/dist/clis/codex/status.d.ts +1 -0
- package/dist/clis/codex/status.js +21 -0
- package/dist/clis/xiaoyuzhou/episode.d.ts +1 -0
- package/dist/clis/xiaoyuzhou/episode.js +28 -0
- package/dist/clis/xiaoyuzhou/podcast-episodes.d.ts +1 -0
- package/dist/clis/xiaoyuzhou/podcast-episodes.js +36 -0
- package/dist/clis/xiaoyuzhou/podcast.d.ts +1 -0
- package/dist/clis/xiaoyuzhou/podcast.js +27 -0
- package/dist/clis/xiaoyuzhou/utils.d.ts +16 -0
- package/dist/clis/xiaoyuzhou/utils.js +55 -0
- package/dist/clis/xiaoyuzhou/utils.test.d.ts +1 -0
- package/dist/clis/xiaoyuzhou/utils.test.js +99 -0
- package/package.json +1 -1
- package/src/clis/antigravity/README.md +49 -0
- package/src/clis/antigravity/README.zh-CN.md +52 -0
- package/src/clis/antigravity/SKILL.md +42 -0
- package/src/clis/antigravity/dump.ts +30 -0
- package/src/clis/antigravity/extract-code.ts +34 -0
- package/src/clis/antigravity/model.ts +47 -0
- package/src/clis/antigravity/new.ts +28 -0
- package/src/clis/antigravity/read.ts +36 -0
- package/src/clis/antigravity/send.ts +40 -0
- package/src/clis/antigravity/status.ts +19 -0
- package/src/clis/antigravity/watch.ts +45 -0
- package/src/clis/codex/README.md +33 -0
- package/src/clis/codex/README.zh-CN.md +33 -0
- package/src/clis/codex/dump.ts +28 -0
- package/src/clis/codex/extract-diff.ts +47 -0
- package/src/clis/codex/new.ts +29 -0
- package/src/clis/codex/read.ts +33 -0
- package/src/clis/codex/send.ts +48 -0
- package/src/clis/codex/status.ts +23 -0
- package/src/clis/xiaoyuzhou/episode.ts +28 -0
- package/src/clis/xiaoyuzhou/podcast-episodes.ts +36 -0
- package/src/clis/xiaoyuzhou/podcast.ts +27 -0
- package/src/clis/xiaoyuzhou/utils.test.ts +122 -0
- package/src/clis/xiaoyuzhou/utils.ts +65 -0
- package/tests/e2e/public-commands.test.ts +62 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenCLI
|
|
2
2
|
|
|
3
|
-
> **Make any website your CLI.**
|
|
3
|
+
> **Make any website or Electron App your CLI.**
|
|
4
4
|
> Zero risk · Reuse Chrome login · AI-powered discovery · 80+ commands · 19 sites
|
|
5
5
|
|
|
6
6
|
[中文文档](./README.zh-CN.md)
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
[](https://nodejs.org)
|
|
10
10
|
[](./LICENSE)
|
|
11
11
|
|
|
12
|
-
A CLI tool that turns **any website** into a command-line interface — Bilibili, Zhihu, 小红书, Twitter/X, Reddit, YouTube, and [many more](#built-in-commands) — powered by browser session reuse and AI-native discovery.
|
|
12
|
+
A CLI tool that turns **any website** or **Electron app** into a command-line interface — Bilibili, Zhihu, 小红书, Twitter/X, Reddit, YouTube, Antigravity, and [many more](#built-in-commands) — powered by browser session reuse and AI-native discovery.
|
|
13
|
+
|
|
14
|
+
🔥 **CLI All Electron Apps! The Most Powerful Update Has Arrived!** 🔥
|
|
15
|
+
Turn ANY Electron application into a CLI tool! Recombine, script, and extend applications like Antigravity Ultra seamlessly. Now AI can control itself natively. Unlimited possibilities await!
|
|
13
16
|
|
|
14
17
|
---
|
|
15
18
|
|
|
@@ -31,6 +34,7 @@ A CLI tool that turns **any website** into a command-line interface — Bilibili
|
|
|
31
34
|
|
|
32
35
|
## Highlights
|
|
33
36
|
|
|
37
|
+
- **CLI All Electron** — CLI-ify apps like Antigravity Ultra! Now AI can control itself natively using cc/openclaw!
|
|
34
38
|
- **Account-safe** — Reuses Chrome's logged-in state; your credentials never leave the browser.
|
|
35
39
|
- **AI Agent ready** — `explore` discovers APIs, `synthesize` generates adapters, `cascade` finds auth strategies.
|
|
36
40
|
- **Self-healing setup** — `opencli setup` auto-discovers tokens; `opencli doctor` diagnoses config across 10+ tools; `--fix` repairs them all.
|
|
@@ -149,6 +153,7 @@ npm install -g @jackwener/opencli@latest
|
|
|
149
153
|
| **v2ex** | `hot` `latest` `topic` `daily` `me` `notifications` | 6 | 🌐 / 🔐 |
|
|
150
154
|
| **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` | 6 | 🔐 Browser |
|
|
151
155
|
| **xiaohongshu** | `search` `notifications` `feed` `me` `user` | 5 | 🔐 Browser |
|
|
156
|
+
| **xiaoyuzhou** | `podcast` `podcast-episodes` `episode` | 3 | 🌐 Public |
|
|
152
157
|
| **youtube** | `search` `video` `transcript` | 3 | 🔐 Browser |
|
|
153
158
|
| **zhihu** | `hot` `search` `question` | 3 | 🔐 Browser |
|
|
154
159
|
| **boss** | `search` `detail` | 2 | 🔐 Browser |
|
package/README.zh-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenCLI
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **把任何网站或 Electron 应用变成你的命令行工具。**
|
|
4
4
|
> 零风控 · 复用 Chrome 登录 · AI 自动发现接口 · 80+ 命令 · 19 站点
|
|
5
5
|
|
|
6
6
|
[English](./README.md)
|
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
[](https://nodejs.org)
|
|
10
10
|
[](./LICENSE)
|
|
11
11
|
|
|
12
|
-
OpenCLI
|
|
12
|
+
OpenCLI 将任何网站或 Electron 应用(如 Antigravity)变成命令行工具 — B站、知乎、小红书、Twitter/X、Reddit、YouTube 等 [19 个站点](#内置命令) — 复用浏览器登录态,AI 驱动探索。
|
|
13
|
+
|
|
14
|
+
🔥 **opencli 支持 CLI 化所有 electron 应用!最强大更新来袭!** 🔥
|
|
15
|
+
CLI all electron!现在支持把所有 electron 应用 CLI 化,从而组合出各种神奇的能力。
|
|
16
|
+
如果你在使用诸如 Antigravity Ultra 等工具时觉得不够灵活或难以扩展,现在通过 OpenCLI 把他 CLI 化,轻松打破界限。
|
|
17
|
+
现在,**AI 可以自己控制自己**!结合 cc/openclaw 就可以远程控制任何 electron 应用!无限玩法!!
|
|
13
18
|
|
|
14
19
|
---
|
|
15
20
|
|
|
@@ -30,6 +35,7 @@ OpenCLI 将任何网站变成命令行工具 — B站、知乎、小红书、Twi
|
|
|
30
35
|
|
|
31
36
|
## 亮点
|
|
32
37
|
|
|
38
|
+
- **CLI All Electron** — 支持把所有 electron 应用(如 Antigravity Ultra)CLI 化,让 AI 控制自己!
|
|
33
39
|
- **多站点覆盖** — B站、知乎、小红书、Twitter、Reddit 等 19 个站点,80+ 命令
|
|
34
40
|
- **零风控** — 复用 Chrome 登录态,无需存储任何凭证
|
|
35
41
|
- **自修复配置** — `opencli setup` 自动发现 Token;`opencli doctor` 诊断 10+ 工具配置;`--fix` 一键修复
|
|
@@ -148,6 +154,7 @@ npm install -g @jackwener/opencli@latest
|
|
|
148
154
|
| **v2ex** | `hot` `latest` `topic` `daily` `me` `notifications` | 6 | 🌐 / 🔐 |
|
|
149
155
|
| **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` | 6 | 🔐 浏览器 |
|
|
150
156
|
| **xiaohongshu** | `search` `notifications` `feed` `me` `user` | 5 | 🔐 浏览器 |
|
|
157
|
+
| **xiaoyuzhou** | `podcast` `podcast-episodes` `episode` | 3 | 🌐 公开 |
|
|
151
158
|
| **youtube** | `search` `video` `transcript` | 3 | 🔐 浏览器 |
|
|
152
159
|
| **zhihu** | `hot` `search` `question` | 3 | 🔐 浏览器 |
|
|
153
160
|
| **boss** | `search` `detail` | 2 | 🔐 浏览器 |
|
package/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opencli
|
|
3
|
-
description: "OpenCLI — Make any website your CLI. Zero risk, AI-powered, reuse Chrome login. 80+ commands across 19 sites."
|
|
3
|
+
description: "OpenCLI — Make any website or Electron App your CLI. Zero risk, AI-powered, reuse Chrome login. 80+ commands across 19 sites."
|
|
4
4
|
version: 0.7.3
|
|
5
5
|
author: jackwener
|
|
6
6
|
tags: [cli, browser, web, mcp, playwright, bilibili, zhihu, twitter, github, v2ex, hackernews, reddit, xiaohongshu, xueqiu, youtube, boss, coupang, AI, agent]
|
|
@@ -8,7 +8,7 @@ tags: [cli, browser, web, mcp, playwright, bilibili, zhihu, twitter, github, v2e
|
|
|
8
8
|
|
|
9
9
|
# OpenCLI
|
|
10
10
|
|
|
11
|
-
> Make any website your CLI. Reuse Chrome login, zero risk, AI-powered discovery.
|
|
11
|
+
> Make any website or Electron App your CLI. Reuse Chrome login, zero risk, AI-powered discovery.
|
|
12
12
|
|
|
13
13
|
> [!CAUTION]
|
|
14
14
|
> **AI Agent 必读:创建或修改任何适配器之前,你必须先阅读 [CLI-EXPLORER.md](./CLI-EXPLORER.md)!**
|
|
@@ -151,6 +151,15 @@ opencli smzdm search --keyword "耳机" # 搜索好价
|
|
|
151
151
|
|
|
152
152
|
# 携程 (browser)
|
|
153
153
|
opencli ctrip search --query "三亚" # 搜索目的地
|
|
154
|
+
|
|
155
|
+
# Antigravity (Electron/CDP)
|
|
156
|
+
opencli antigravity status # 检查 CDP 连接
|
|
157
|
+
opencli antigravity send "hello" # 发送文本到当前 agent 聊天框
|
|
158
|
+
opencli antigravity read # 读取整个聊天记录面板
|
|
159
|
+
opencli antigravity new # 清空聊天、开启新对话
|
|
160
|
+
opencli antigravity extract-code # 自动抽取 AI 回复中的代码块
|
|
161
|
+
opencli antigravity model claude # 切换底层模型
|
|
162
|
+
opencli antigravity watch # 流式监听增量消息
|
|
154
163
|
```
|
|
155
164
|
|
|
156
165
|
### Management Commands
|
package/dist/cli-manifest.json
CHANGED
|
@@ -1,4 +1,142 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"site": "antigravity",
|
|
4
|
+
"name": "dump",
|
|
5
|
+
"description": "Dump the DOM to help AI understand the UI",
|
|
6
|
+
"strategy": "ui",
|
|
7
|
+
"browser": true,
|
|
8
|
+
"args": [],
|
|
9
|
+
"type": "ts",
|
|
10
|
+
"modulePath": "antigravity/dump.js",
|
|
11
|
+
"domain": "localhost",
|
|
12
|
+
"columns": [
|
|
13
|
+
"htmlFile",
|
|
14
|
+
"snapFile"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"site": "antigravity",
|
|
19
|
+
"name": "extract-code",
|
|
20
|
+
"description": "Extract multi-line code blocks from the current Antigravity conversation",
|
|
21
|
+
"strategy": "ui",
|
|
22
|
+
"browser": true,
|
|
23
|
+
"args": [],
|
|
24
|
+
"type": "ts",
|
|
25
|
+
"modulePath": "antigravity/extract-code.js",
|
|
26
|
+
"domain": "localhost",
|
|
27
|
+
"columns": [
|
|
28
|
+
"code"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"site": "antigravity",
|
|
33
|
+
"name": "model",
|
|
34
|
+
"description": "Switch the active LLM model in Antigravity",
|
|
35
|
+
"strategy": "ui",
|
|
36
|
+
"browser": true,
|
|
37
|
+
"args": [
|
|
38
|
+
{
|
|
39
|
+
"name": "name",
|
|
40
|
+
"type": "str",
|
|
41
|
+
"required": true,
|
|
42
|
+
"positional": true,
|
|
43
|
+
"help": "Target model name (e.g. claude, gemini, o1)"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"type": "ts",
|
|
47
|
+
"modulePath": "antigravity/model.js",
|
|
48
|
+
"domain": "localhost",
|
|
49
|
+
"columns": [
|
|
50
|
+
"status"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"site": "antigravity",
|
|
55
|
+
"name": "new",
|
|
56
|
+
"description": "Start a new conversation / clear context in Antigravity",
|
|
57
|
+
"strategy": "ui",
|
|
58
|
+
"browser": true,
|
|
59
|
+
"args": [],
|
|
60
|
+
"type": "ts",
|
|
61
|
+
"modulePath": "antigravity/new.js",
|
|
62
|
+
"domain": "localhost",
|
|
63
|
+
"columns": [
|
|
64
|
+
"status"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"site": "antigravity",
|
|
69
|
+
"name": "read",
|
|
70
|
+
"description": "Read the latest chat messages from Antigravity AI",
|
|
71
|
+
"strategy": "ui",
|
|
72
|
+
"browser": true,
|
|
73
|
+
"args": [
|
|
74
|
+
{
|
|
75
|
+
"name": "last",
|
|
76
|
+
"type": "str",
|
|
77
|
+
"required": false,
|
|
78
|
+
"help": "Number of recent messages to read (not fully implemented due to generic structure, currently returns full history text or latest chunk)"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"type": "ts",
|
|
82
|
+
"modulePath": "antigravity/read.js",
|
|
83
|
+
"domain": "localhost",
|
|
84
|
+
"columns": [
|
|
85
|
+
"role",
|
|
86
|
+
"content"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"site": "antigravity",
|
|
91
|
+
"name": "send",
|
|
92
|
+
"description": "Send a message to Antigravity AI via the internal Lexical editor",
|
|
93
|
+
"strategy": "ui",
|
|
94
|
+
"browser": true,
|
|
95
|
+
"args": [
|
|
96
|
+
{
|
|
97
|
+
"name": "message",
|
|
98
|
+
"type": "str",
|
|
99
|
+
"required": true,
|
|
100
|
+
"positional": true,
|
|
101
|
+
"help": "The message text to send"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"type": "ts",
|
|
105
|
+
"modulePath": "antigravity/send.js",
|
|
106
|
+
"domain": "localhost",
|
|
107
|
+
"columns": [
|
|
108
|
+
"status",
|
|
109
|
+
"message"
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"site": "antigravity",
|
|
114
|
+
"name": "status",
|
|
115
|
+
"description": "Check Antigravity CDP connection and get current page state",
|
|
116
|
+
"strategy": "ui",
|
|
117
|
+
"browser": true,
|
|
118
|
+
"args": [],
|
|
119
|
+
"type": "ts",
|
|
120
|
+
"modulePath": "antigravity/status.js",
|
|
121
|
+
"domain": "localhost",
|
|
122
|
+
"columns": [
|
|
123
|
+
"status",
|
|
124
|
+
"url",
|
|
125
|
+
"title"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"site": "antigravity",
|
|
130
|
+
"name": "watch",
|
|
131
|
+
"description": "Stream new chat messages from Antigravity in real-time",
|
|
132
|
+
"strategy": "ui",
|
|
133
|
+
"browser": true,
|
|
134
|
+
"args": [],
|
|
135
|
+
"type": "ts",
|
|
136
|
+
"modulePath": "antigravity/watch.js",
|
|
137
|
+
"domain": "localhost",
|
|
138
|
+
"columns": []
|
|
139
|
+
},
|
|
2
140
|
{
|
|
3
141
|
"site": "barchart",
|
|
4
142
|
"name": "flow",
|
|
@@ -672,6 +810,103 @@
|
|
|
672
810
|
"url"
|
|
673
811
|
]
|
|
674
812
|
},
|
|
813
|
+
{
|
|
814
|
+
"site": "codex",
|
|
815
|
+
"name": "dump",
|
|
816
|
+
"description": "Dump the DOM and Accessibility tree of Codex for reverse-engineering",
|
|
817
|
+
"strategy": "ui",
|
|
818
|
+
"browser": true,
|
|
819
|
+
"args": [],
|
|
820
|
+
"type": "ts",
|
|
821
|
+
"modulePath": "codex/dump.js",
|
|
822
|
+
"domain": "localhost",
|
|
823
|
+
"columns": [
|
|
824
|
+
"action",
|
|
825
|
+
"files"
|
|
826
|
+
]
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
"site": "codex",
|
|
830
|
+
"name": "extract-diff",
|
|
831
|
+
"description": "Extract visual code review diff patches from Codex",
|
|
832
|
+
"strategy": "ui",
|
|
833
|
+
"browser": true,
|
|
834
|
+
"args": [],
|
|
835
|
+
"type": "ts",
|
|
836
|
+
"modulePath": "codex/extract-diff.js",
|
|
837
|
+
"domain": "localhost",
|
|
838
|
+
"columns": [
|
|
839
|
+
"File",
|
|
840
|
+
"Diff"
|
|
841
|
+
]
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
"site": "codex",
|
|
845
|
+
"name": "new",
|
|
846
|
+
"description": "Start a new Codex conversation thread / isolated workspace",
|
|
847
|
+
"strategy": "ui",
|
|
848
|
+
"browser": true,
|
|
849
|
+
"args": [],
|
|
850
|
+
"type": "ts",
|
|
851
|
+
"modulePath": "codex/new.js",
|
|
852
|
+
"domain": "localhost",
|
|
853
|
+
"columns": [
|
|
854
|
+
"Status",
|
|
855
|
+
"Action"
|
|
856
|
+
]
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
"site": "codex",
|
|
860
|
+
"name": "read",
|
|
861
|
+
"description": "Read the contents of the current Codex conversation thread",
|
|
862
|
+
"strategy": "ui",
|
|
863
|
+
"browser": true,
|
|
864
|
+
"args": [],
|
|
865
|
+
"type": "ts",
|
|
866
|
+
"modulePath": "codex/read.js",
|
|
867
|
+
"domain": "localhost",
|
|
868
|
+
"columns": [
|
|
869
|
+
"Thread_Content"
|
|
870
|
+
]
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
"site": "codex",
|
|
874
|
+
"name": "send",
|
|
875
|
+
"description": "Send text/commands to the Codex AI composer",
|
|
876
|
+
"strategy": "ui",
|
|
877
|
+
"browser": true,
|
|
878
|
+
"args": [
|
|
879
|
+
{
|
|
880
|
+
"name": "text",
|
|
881
|
+
"type": "str",
|
|
882
|
+
"required": true,
|
|
883
|
+
"help": "Text, command (e.g. /review), or skill (e.g. $imagegen)"
|
|
884
|
+
}
|
|
885
|
+
],
|
|
886
|
+
"type": "ts",
|
|
887
|
+
"modulePath": "codex/send.js",
|
|
888
|
+
"domain": "localhost",
|
|
889
|
+
"columns": [
|
|
890
|
+
"Status",
|
|
891
|
+
"InjectedText"
|
|
892
|
+
]
|
|
893
|
+
},
|
|
894
|
+
{
|
|
895
|
+
"site": "codex",
|
|
896
|
+
"name": "status",
|
|
897
|
+
"description": "Check active CDP connection to OpenAI Codex App",
|
|
898
|
+
"strategy": "ui",
|
|
899
|
+
"browser": true,
|
|
900
|
+
"args": [],
|
|
901
|
+
"type": "ts",
|
|
902
|
+
"modulePath": "codex/status.js",
|
|
903
|
+
"domain": "localhost",
|
|
904
|
+
"columns": [
|
|
905
|
+
"Status",
|
|
906
|
+
"Url",
|
|
907
|
+
"Title"
|
|
908
|
+
]
|
|
909
|
+
},
|
|
675
910
|
{
|
|
676
911
|
"site": "coupang",
|
|
677
912
|
"name": "add-to-cart",
|
|
@@ -2522,6 +2757,114 @@
|
|
|
2522
2757
|
"url"
|
|
2523
2758
|
]
|
|
2524
2759
|
},
|
|
2760
|
+
{
|
|
2761
|
+
"site": "xiaoyuzhou",
|
|
2762
|
+
"name": "episode",
|
|
2763
|
+
"description": "View details of a Xiaoyuzhou podcast episode",
|
|
2764
|
+
"strategy": "public",
|
|
2765
|
+
"browser": false,
|
|
2766
|
+
"args": [
|
|
2767
|
+
{
|
|
2768
|
+
"name": "id",
|
|
2769
|
+
"type": "str",
|
|
2770
|
+
"required": true,
|
|
2771
|
+
"positional": true,
|
|
2772
|
+
"help": "Episode ID (eid from podcast-episodes output)"
|
|
2773
|
+
}
|
|
2774
|
+
],
|
|
2775
|
+
"type": "ts",
|
|
2776
|
+
"modulePath": "xiaoyuzhou/episode.js",
|
|
2777
|
+
"domain": "www.xiaoyuzhoufm.com",
|
|
2778
|
+
"columns": [
|
|
2779
|
+
"title",
|
|
2780
|
+
"podcast",
|
|
2781
|
+
"duration",
|
|
2782
|
+
"plays",
|
|
2783
|
+
"comments",
|
|
2784
|
+
"likes",
|
|
2785
|
+
"date"
|
|
2786
|
+
]
|
|
2787
|
+
},
|
|
2788
|
+
{
|
|
2789
|
+
"site": "xiaoyuzhou",
|
|
2790
|
+
"name": "podcast-episodes",
|
|
2791
|
+
"description": "List recent episodes of a Xiaoyuzhou podcast (up to 15, SSR limit)",
|
|
2792
|
+
"strategy": "public",
|
|
2793
|
+
"browser": false,
|
|
2794
|
+
"args": [
|
|
2795
|
+
{
|
|
2796
|
+
"name": "id",
|
|
2797
|
+
"type": "str",
|
|
2798
|
+
"required": true,
|
|
2799
|
+
"positional": true,
|
|
2800
|
+
"help": "Podcast ID (from xiaoyuzhoufm.com URL)"
|
|
2801
|
+
},
|
|
2802
|
+
{
|
|
2803
|
+
"name": "limit",
|
|
2804
|
+
"type": "int",
|
|
2805
|
+
"default": 15,
|
|
2806
|
+
"required": false,
|
|
2807
|
+
"help": "Max episodes to show (up to 15, SSR limit)"
|
|
2808
|
+
}
|
|
2809
|
+
],
|
|
2810
|
+
"type": "ts",
|
|
2811
|
+
"modulePath": "xiaoyuzhou/podcast-episodes.js",
|
|
2812
|
+
"domain": "www.xiaoyuzhoufm.com",
|
|
2813
|
+
"columns": [
|
|
2814
|
+
"eid",
|
|
2815
|
+
"title",
|
|
2816
|
+
"duration",
|
|
2817
|
+
"plays",
|
|
2818
|
+
"date"
|
|
2819
|
+
]
|
|
2820
|
+
},
|
|
2821
|
+
{
|
|
2822
|
+
"site": "xiaoyuzhou",
|
|
2823
|
+
"name": "podcast",
|
|
2824
|
+
"description": "View a Xiaoyuzhou podcast profile",
|
|
2825
|
+
"strategy": "public",
|
|
2826
|
+
"browser": false,
|
|
2827
|
+
"args": [
|
|
2828
|
+
{
|
|
2829
|
+
"name": "id",
|
|
2830
|
+
"type": "str",
|
|
2831
|
+
"required": true,
|
|
2832
|
+
"positional": true,
|
|
2833
|
+
"help": "Podcast ID (from xiaoyuzhoufm.com URL)"
|
|
2834
|
+
}
|
|
2835
|
+
],
|
|
2836
|
+
"type": "ts",
|
|
2837
|
+
"modulePath": "xiaoyuzhou/podcast.js",
|
|
2838
|
+
"domain": "www.xiaoyuzhoufm.com",
|
|
2839
|
+
"columns": [
|
|
2840
|
+
"title",
|
|
2841
|
+
"author",
|
|
2842
|
+
"description",
|
|
2843
|
+
"subscribers",
|
|
2844
|
+
"episodes",
|
|
2845
|
+
"updated"
|
|
2846
|
+
]
|
|
2847
|
+
},
|
|
2848
|
+
{
|
|
2849
|
+
"site": "xiaoyuzhou",
|
|
2850
|
+
"name": "utils",
|
|
2851
|
+
"description": "",
|
|
2852
|
+
"strategy": "cookie",
|
|
2853
|
+
"browser": true,
|
|
2854
|
+
"args": [],
|
|
2855
|
+
"type": "ts",
|
|
2856
|
+
"modulePath": "xiaoyuzhou/utils.js"
|
|
2857
|
+
},
|
|
2858
|
+
{
|
|
2859
|
+
"site": "xiaoyuzhou",
|
|
2860
|
+
"name": "utils.test",
|
|
2861
|
+
"description": "",
|
|
2862
|
+
"strategy": "cookie",
|
|
2863
|
+
"browser": true,
|
|
2864
|
+
"args": [],
|
|
2865
|
+
"type": "ts",
|
|
2866
|
+
"modulePath": "xiaoyuzhou/utils.test.js"
|
|
2867
|
+
},
|
|
2525
2868
|
{
|
|
2526
2869
|
"site": "xueqiu",
|
|
2527
2870
|
"name": "feed",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const dumpCommand: import("../../registry.js").CliCommand;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
export const dumpCommand = cli({
|
|
4
|
+
site: 'antigravity',
|
|
5
|
+
name: 'dump',
|
|
6
|
+
description: 'Dump the DOM to help AI understand the UI',
|
|
7
|
+
domain: 'localhost',
|
|
8
|
+
strategy: Strategy.UI,
|
|
9
|
+
browser: true,
|
|
10
|
+
args: [],
|
|
11
|
+
columns: ['htmlFile', 'snapFile'],
|
|
12
|
+
func: async (page) => {
|
|
13
|
+
// Extract HTML
|
|
14
|
+
const html = await page.evaluate('document.body.innerHTML');
|
|
15
|
+
fs.writeFileSync('/tmp/antigravity-dom.html', html);
|
|
16
|
+
// Extract Snapshot
|
|
17
|
+
let snapFile = '';
|
|
18
|
+
try {
|
|
19
|
+
const snap = await page.snapshot({ raw: true });
|
|
20
|
+
snapFile = '/tmp/antigravity-snapshot.json';
|
|
21
|
+
fs.writeFileSync(snapFile, JSON.stringify(snap, null, 2));
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
snapFile = 'Failed';
|
|
25
|
+
}
|
|
26
|
+
return [{ htmlFile: '/tmp/antigravity-dom.html', snapFile }];
|
|
27
|
+
},
|
|
28
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const extractCodeCommand: import("../../registry.js").CliCommand;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
export const extractCodeCommand = cli({
|
|
3
|
+
site: 'antigravity',
|
|
4
|
+
name: 'extract-code',
|
|
5
|
+
description: 'Extract multi-line code blocks from the current Antigravity conversation',
|
|
6
|
+
domain: 'localhost',
|
|
7
|
+
strategy: Strategy.UI,
|
|
8
|
+
browser: true,
|
|
9
|
+
args: [],
|
|
10
|
+
columns: ['code'],
|
|
11
|
+
func: async (page) => {
|
|
12
|
+
const blocks = await page.evaluate(`
|
|
13
|
+
async () => {
|
|
14
|
+
// Find standard pre/code blocks
|
|
15
|
+
let elements = Array.from(document.querySelectorAll('pre code'));
|
|
16
|
+
|
|
17
|
+
// Fallback to Monaco editor content inside the UI
|
|
18
|
+
if (elements.length === 0) {
|
|
19
|
+
elements = Array.from(document.querySelectorAll('.monaco-editor'));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Generic fallback to any code tag that spans multiple lines
|
|
23
|
+
if (elements.length === 0) {
|
|
24
|
+
elements = Array.from(document.querySelectorAll('code')).filter(c => c.innerText.includes('\\n'));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return elements.map(el => el.innerText).filter(text => text.trim().length > 0);
|
|
28
|
+
}
|
|
29
|
+
`);
|
|
30
|
+
return blocks.map((code) => ({ code }));
|
|
31
|
+
},
|
|
32
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const modelCommand: import("../../registry.js").CliCommand;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
export const modelCommand = cli({
|
|
3
|
+
site: 'antigravity',
|
|
4
|
+
name: 'model',
|
|
5
|
+
description: 'Switch the active LLM model in Antigravity',
|
|
6
|
+
domain: 'localhost',
|
|
7
|
+
strategy: Strategy.UI,
|
|
8
|
+
browser: true,
|
|
9
|
+
args: [
|
|
10
|
+
{ name: 'name', help: 'Target model name (e.g. claude, gemini, o1)', required: true, positional: true }
|
|
11
|
+
],
|
|
12
|
+
columns: ['status'],
|
|
13
|
+
func: async (page, kwargs) => {
|
|
14
|
+
const targetName = kwargs.name.toLowerCase();
|
|
15
|
+
await page.evaluate(`
|
|
16
|
+
async () => {
|
|
17
|
+
const targetModelName = ${JSON.stringify(targetName)};
|
|
18
|
+
|
|
19
|
+
// 1. Locate the model selector dropdown trigger
|
|
20
|
+
const trigger = document.querySelector('div[aria-haspopup="dialog"] > div[tabindex="0"]');
|
|
21
|
+
if (!trigger) throw new Error('Could not find the model selector trigger in the UI');
|
|
22
|
+
trigger.click();
|
|
23
|
+
|
|
24
|
+
// 2. Wait a brief moment for React to mount the Portal/Dialog
|
|
25
|
+
await new Promise(r => setTimeout(r, 200));
|
|
26
|
+
|
|
27
|
+
// 3. Find the option spanning target text
|
|
28
|
+
const spans = Array.from(document.querySelectorAll('[role="dialog"] span'));
|
|
29
|
+
const target = spans.find(s => s.innerText.toLowerCase().includes(targetModelName));
|
|
30
|
+
if (!target) {
|
|
31
|
+
// If not found, click the trigger again to close it safely
|
|
32
|
+
trigger.click();
|
|
33
|
+
throw new Error('Model matching "' + targetModelName + '" was not found in the dropdown list.');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 4. Click the closest parent that handles the row action
|
|
37
|
+
const optionNode = target.closest('.cursor-pointer') || target;
|
|
38
|
+
optionNode.click();
|
|
39
|
+
}
|
|
40
|
+
`);
|
|
41
|
+
await page.wait(0.5);
|
|
42
|
+
return [{ status: `Model switched to: ${kwargs.name}` }];
|
|
43
|
+
},
|
|
44
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const newCommand: import("../../registry.js").CliCommand;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
export const newCommand = cli({
|
|
3
|
+
site: 'antigravity',
|
|
4
|
+
name: 'new',
|
|
5
|
+
description: 'Start a new conversation / clear context in Antigravity',
|
|
6
|
+
domain: 'localhost',
|
|
7
|
+
strategy: Strategy.UI,
|
|
8
|
+
browser: true,
|
|
9
|
+
args: [],
|
|
10
|
+
columns: ['status'],
|
|
11
|
+
func: async (page) => {
|
|
12
|
+
await page.evaluate(`
|
|
13
|
+
async () => {
|
|
14
|
+
const btn = document.querySelector('[data-tooltip-id="new-conversation-tooltip"]');
|
|
15
|
+
if (!btn) throw new Error('Could not find New Conversation button');
|
|
16
|
+
|
|
17
|
+
// In case it's disabled, we must check, but we'll try to click it anyway
|
|
18
|
+
btn.click();
|
|
19
|
+
}
|
|
20
|
+
`);
|
|
21
|
+
// Give it a moment to reset the UI
|
|
22
|
+
await page.wait(0.5);
|
|
23
|
+
return [{ status: 'Successfully started a new conversation' }];
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const readCommand: import("../../registry.js").CliCommand;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
export const readCommand = cli({
|
|
3
|
+
site: 'antigravity',
|
|
4
|
+
name: 'read',
|
|
5
|
+
description: 'Read the latest chat messages from Antigravity AI',
|
|
6
|
+
domain: 'localhost',
|
|
7
|
+
strategy: Strategy.UI,
|
|
8
|
+
browser: true,
|
|
9
|
+
args: [
|
|
10
|
+
{ name: 'last', help: 'Number of recent messages to read (not fully implemented due to generic structure, currently returns full history text or latest chunk)' }
|
|
11
|
+
],
|
|
12
|
+
columns: ['role', 'content'],
|
|
13
|
+
func: async (page, kwargs) => {
|
|
14
|
+
// We execute a script inside Antigravity's Chromium environment to extract the text
|
|
15
|
+
// of the entire conversation pane.
|
|
16
|
+
const rawText = await page.evaluate(`
|
|
17
|
+
async () => {
|
|
18
|
+
const container = document.getElementById('conversation');
|
|
19
|
+
if (!container) throw new Error('Could not find conversation container');
|
|
20
|
+
|
|
21
|
+
// Extract the full visible text of the conversation
|
|
22
|
+
// In Electron/Chromium, innerText preserves basic visual line breaks nicely
|
|
23
|
+
return container.innerText;
|
|
24
|
+
}
|
|
25
|
+
`);
|
|
26
|
+
// We can do simple heuristic parsing based on typical visual markers if needed.
|
|
27
|
+
// For now, we return the entire text blob, or just the last 2000 characters if it's too long.
|
|
28
|
+
const cleanText = String(rawText).trim();
|
|
29
|
+
return [{
|
|
30
|
+
role: 'history',
|
|
31
|
+
content: cleanText
|
|
32
|
+
}];
|
|
33
|
+
},
|
|
34
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sendCommand: import("../../registry.js").CliCommand;
|