@jackwener/opencli 1.7.16 → 1.7.17
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 +8 -9
- package/README.zh-CN.md +8 -8
- package/cli-manifest.json +97 -271
- package/clis/chatgpt/ask.js +1 -1
- package/clis/chatgpt/commands.test.js +2 -2
- package/clis/chatgpt/detail.js +1 -1
- package/clis/chatgpt/history.js +1 -1
- package/clis/chatgpt/image.js +38 -4
- package/clis/chatgpt/image.test.js +68 -1
- package/clis/chatgpt/new.js +1 -1
- package/clis/chatgpt/read.js +1 -1
- package/clis/chatgpt/send.js +1 -1
- package/clis/chatgpt/status.js +1 -1
- package/clis/chatgpt/utils.js +208 -16
- package/clis/chatgpt/utils.test.js +131 -2
- package/clis/claude/ask.js +1 -1
- package/clis/claude/detail.js +1 -1
- package/clis/claude/history.js +1 -1
- package/clis/claude/new.js +1 -1
- package/clis/claude/read.js +1 -1
- package/clis/claude/send.js +1 -1
- package/clis/claude/status.js +1 -1
- package/clis/deepseek/ask.js +1 -1
- package/clis/deepseek/detail.js +1 -1
- package/clis/deepseek/history.js +1 -1
- package/clis/deepseek/new.js +1 -1
- package/clis/deepseek/read.js +1 -1
- package/clis/deepseek/send.js +1 -1
- package/clis/deepseek/status.js +1 -1
- package/clis/doubao/ask.js +1 -1
- package/clis/doubao/detail.js +1 -1
- package/clis/doubao/history.js +1 -1
- package/clis/doubao/meeting-summary.js +1 -1
- package/clis/doubao/meeting-transcript.js +1 -1
- package/clis/doubao/new.js +1 -1
- package/clis/doubao/read.js +1 -1
- package/clis/doubao/send.js +1 -1
- package/clis/doubao/status.js +1 -1
- package/clis/gemini/ask.js +1 -1
- package/clis/gemini/deep-research-result.js +1 -1
- package/clis/gemini/deep-research.js +1 -1
- package/clis/gemini/image.js +1 -1
- package/clis/gemini/new.js +1 -1
- package/clis/grok/ask.js +1 -1
- package/clis/grok/detail.js +1 -1
- package/clis/grok/history.js +1 -1
- package/clis/grok/image.js +1 -1
- package/clis/grok/new.js +1 -1
- package/clis/grok/read.js +1 -1
- package/clis/grok/send.js +1 -1
- package/clis/grok/status.js +1 -1
- package/clis/notebooklm/current.js +1 -1
- package/clis/notebooklm/get.js +1 -1
- package/clis/notebooklm/history.js +1 -1
- package/clis/notebooklm/note-list.js +1 -1
- package/clis/notebooklm/notes-get.js +1 -1
- package/clis/notebooklm/open.js +2 -2
- package/clis/notebooklm/open.test.js +1 -1
- package/clis/notebooklm/source-fulltext.js +1 -1
- package/clis/notebooklm/source-get.js +1 -1
- package/clis/notebooklm/source-guide.js +1 -1
- package/clis/notebooklm/source-list.js +1 -1
- package/clis/notebooklm/summary.js +1 -1
- package/clis/qwen/ask.js +1 -1
- package/clis/qwen/detail.js +1 -1
- package/clis/qwen/history.js +1 -1
- package/clis/qwen/image.js +1 -1
- package/clis/qwen/new.js +1 -1
- package/clis/qwen/read.js +1 -1
- package/clis/qwen/send.js +1 -1
- package/clis/qwen/status.js +1 -1
- package/clis/reddit/comment.js +1 -1
- package/clis/reddit/frontpage.js +1 -1
- package/clis/reddit/popular.js +1 -1
- package/clis/reddit/read.js +1 -1
- package/clis/reddit/read.test.js +2 -2
- package/clis/reddit/save.js +1 -1
- package/clis/reddit/saved.js +1 -1
- package/clis/reddit/search.js +1 -1
- package/clis/reddit/subreddit.js +1 -1
- package/clis/reddit/subscribe.js +1 -1
- package/clis/reddit/upvote.js +1 -1
- package/clis/reddit/upvoted.js +1 -1
- package/clis/reddit/user-comments.js +1 -1
- package/clis/reddit/user-posts.js +1 -1
- package/clis/reddit/user.js +1 -1
- package/clis/twitter/article.js +1 -1
- package/clis/twitter/bookmark-folder.js +1 -1
- package/clis/twitter/bookmark-folders.js +1 -1
- package/clis/twitter/bookmarks.js +1 -1
- package/clis/twitter/download.js +1 -1
- package/clis/twitter/followers.js +1 -1
- package/clis/twitter/following.js +1 -1
- package/clis/twitter/likes.js +1 -1
- package/clis/twitter/list-tweets.js +1 -1
- package/clis/twitter/lists.js +1 -1
- package/clis/twitter/notifications.js +1 -1
- package/clis/twitter/profile.js +1 -1
- package/clis/twitter/search.js +1 -1
- package/clis/twitter/thread.js +1 -1
- package/clis/twitter/timeline.js +1 -1
- package/clis/twitter/trending.js +1 -1
- package/clis/twitter/tweets.js +1 -1
- package/clis/yuanbao/ask.js +1 -1
- package/clis/yuanbao/detail.js +1 -1
- package/clis/yuanbao/history.js +1 -1
- package/clis/yuanbao/new.js +1 -1
- package/clis/yuanbao/read.js +1 -1
- package/clis/yuanbao/send.js +1 -1
- package/clis/yuanbao/status.js +1 -1
- package/dist/src/browser/bridge.d.ts +3 -1
- package/dist/src/browser/bridge.js +3 -1
- package/dist/src/browser/cdp.d.ts +3 -1
- package/dist/src/browser/daemon-client.d.ts +7 -14
- package/dist/src/browser/daemon-client.js +2 -6
- package/dist/src/browser/network-cache.d.ts +5 -5
- package/dist/src/browser/network-cache.js +8 -8
- package/dist/src/browser/network-cache.test.js +4 -4
- package/dist/src/browser/page.d.ts +8 -7
- package/dist/src/browser/page.js +23 -16
- package/dist/src/browser/page.test.js +60 -30
- package/dist/src/build-manifest.js +1 -1
- package/dist/src/cli.js +60 -162
- package/dist/src/cli.test.js +178 -197
- package/dist/src/commanderAdapter.js +2 -0
- package/dist/src/discovery.js +1 -1
- package/dist/src/doctor.d.ts +0 -4
- package/dist/src/doctor.js +8 -72
- package/dist/src/doctor.test.js +26 -97
- package/dist/src/execution.d.ts +1 -0
- package/dist/src/execution.js +20 -21
- package/dist/src/execution.test.js +27 -31
- package/dist/src/help.js +7 -1
- package/dist/src/main.js +0 -19
- package/dist/src/manifest-types.d.ts +2 -4
- package/dist/src/observation/artifact.js +1 -1
- package/dist/src/observation/artifact.test.js +3 -3
- package/dist/src/observation/events.d.ts +1 -1
- package/dist/src/observation/manager.js +1 -1
- package/dist/src/observation/manager.test.js +3 -3
- package/dist/src/registry-api.d.ts +1 -1
- package/dist/src/registry.d.ts +3 -12
- package/dist/src/registry.js +6 -10
- package/dist/src/runtime.d.ts +7 -2
- package/dist/src/runtime.js +3 -1
- package/dist/src/serialization.d.ts +1 -1
- package/dist/src/serialization.js +1 -1
- package/dist/src/types.d.ts +0 -15
- package/package.json +1 -1
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
import { __test__, prepareChatGPTImagePaths, sendChatGPTMessage, uploadChatGPTImages, waitForChatGPTImages } from './utils.js';
|
|
6
|
+
|
|
7
|
+
const tempDirs = [];
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
vi.restoreAllMocks();
|
|
11
|
+
while (tempDirs.length) {
|
|
12
|
+
fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
|
|
13
|
+
}
|
|
14
|
+
});
|
|
3
15
|
|
|
4
16
|
function createPageMock({ location = '', generating = [], imageUrls = [] } = {}) {
|
|
5
17
|
let generatingIndex = 0;
|
|
@@ -96,6 +108,26 @@ describe('chatgpt send selectors', () => {
|
|
|
96
108
|
await expect(sendChatGPTMessage(page, 'hello')).resolves.toBe(true);
|
|
97
109
|
});
|
|
98
110
|
|
|
111
|
+
it('uses the composer submit fallback consistently for readiness and click', async () => {
|
|
112
|
+
const page = {
|
|
113
|
+
wait: vi.fn().mockResolvedValue(undefined),
|
|
114
|
+
nativeType: vi.fn().mockResolvedValue(undefined),
|
|
115
|
+
evaluate: vi.fn((script) => {
|
|
116
|
+
if (script.includes('findComposer')) return Promise.resolve(true);
|
|
117
|
+
if (script.includes('sendBtnFound')) {
|
|
118
|
+
expect(script).toContain('#composer-submit-button:not([disabled])');
|
|
119
|
+
return Promise.resolve({ sendBtnFound: true });
|
|
120
|
+
}
|
|
121
|
+
if (script.includes('if (sendBtn) sendBtn.click')) {
|
|
122
|
+
expect(script).toContain('#composer-submit-button:not([disabled])');
|
|
123
|
+
}
|
|
124
|
+
return Promise.resolve(undefined);
|
|
125
|
+
}),
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
await expect(sendChatGPTMessage(page, 'hello')).resolves.toBe(true);
|
|
129
|
+
});
|
|
130
|
+
|
|
99
131
|
it('keeps zh-CN aria and placeholder fallbacks without replacing English selectors', () => {
|
|
100
132
|
expect(__test__.COMPOSER_SELECTORS).toEqual(expect.arrayContaining([
|
|
101
133
|
'[aria-label="Chat with ChatGPT"]',
|
|
@@ -105,7 +137,104 @@ describe('chatgpt send selectors', () => {
|
|
|
105
137
|
'[data-testid="prompt-textarea"]',
|
|
106
138
|
]));
|
|
107
139
|
expect(__test__.SEND_BUTTON_SELECTOR).toBe('button[data-testid="send-button"]:not([disabled])');
|
|
140
|
+
expect(__test__.SEND_BUTTON_FALLBACK_SELECTORS).toContain('#composer-submit-button:not([disabled])');
|
|
108
141
|
expect(__test__.SEND_BUTTON_LABELS).toEqual(expect.arrayContaining(['Send prompt', 'Send message', 'Send', '发送提示']));
|
|
109
142
|
expect(__test__.CLOSE_SIDEBAR_LABELS).toEqual(expect.arrayContaining(['Close sidebar', '关闭边栏']));
|
|
110
143
|
});
|
|
111
144
|
});
|
|
145
|
+
|
|
146
|
+
describe('chatgpt image upload helper', () => {
|
|
147
|
+
it('validates local images without a browser page', async () => {
|
|
148
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-chatgpt-'));
|
|
149
|
+
tempDirs.push(dir);
|
|
150
|
+
const filePath = path.join(dir, 'cat.png');
|
|
151
|
+
fs.writeFileSync(filePath, 'fake-png');
|
|
152
|
+
|
|
153
|
+
await expect(prepareChatGPTImagePaths([filePath])).resolves.toEqual({ ok: true, paths: [filePath] });
|
|
154
|
+
await expect(prepareChatGPTImagePaths([path.join(dir, 'missing.png')])).resolves.toMatchObject({
|
|
155
|
+
ok: false,
|
|
156
|
+
reason: expect.stringContaining('Image not found'),
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('prefers Browser Bridge file input upload and waits for a preview', async () => {
|
|
161
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-chatgpt-'));
|
|
162
|
+
tempDirs.push(dir);
|
|
163
|
+
const filePath = path.join(dir, 'cat.png');
|
|
164
|
+
fs.writeFileSync(filePath, 'fake-png');
|
|
165
|
+
|
|
166
|
+
const page = {
|
|
167
|
+
setFileInput: vi.fn().mockResolvedValue(undefined),
|
|
168
|
+
wait: vi.fn().mockResolvedValue(undefined),
|
|
169
|
+
evaluate: vi.fn().mockResolvedValue(true),
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const result = await uploadChatGPTImages(page, [filePath]);
|
|
173
|
+
|
|
174
|
+
expect(result).toEqual({ ok: true, files: [filePath] });
|
|
175
|
+
expect(page.setFileInput).toHaveBeenCalledWith([filePath], 'input[type="file"]');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('rejects missing files before touching the page', async () => {
|
|
179
|
+
const page = {
|
|
180
|
+
setFileInput: vi.fn(),
|
|
181
|
+
wait: vi.fn(),
|
|
182
|
+
evaluate: vi.fn(),
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const result = await uploadChatGPTImages(page, ['/no/such/cat.png']);
|
|
186
|
+
|
|
187
|
+
expect(result.ok).toBe(false);
|
|
188
|
+
expect(result.reason).toContain('Image not found');
|
|
189
|
+
expect(page.setFileInput).not.toHaveBeenCalled();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('rejects non-image extensions', async () => {
|
|
193
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-chatgpt-'));
|
|
194
|
+
tempDirs.push(dir);
|
|
195
|
+
const filePath = path.join(dir, 'report.pdf');
|
|
196
|
+
fs.writeFileSync(filePath, 'fake');
|
|
197
|
+
|
|
198
|
+
const page = {
|
|
199
|
+
setFileInput: vi.fn(),
|
|
200
|
+
wait: vi.fn(),
|
|
201
|
+
evaluate: vi.fn(),
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const result = await uploadChatGPTImages(page, [filePath]);
|
|
205
|
+
|
|
206
|
+
expect(result.ok).toBe(false);
|
|
207
|
+
expect(result.reason).toContain('Unsupported image type');
|
|
208
|
+
expect(page.setFileInput).not.toHaveBeenCalled();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('passes a React-compatible change event in fallback upload', async () => {
|
|
212
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-chatgpt-'));
|
|
213
|
+
tempDirs.push(dir);
|
|
214
|
+
const filePath = path.join(dir, 'cat.png');
|
|
215
|
+
fs.writeFileSync(filePath, 'fake-png');
|
|
216
|
+
|
|
217
|
+
const page = {
|
|
218
|
+
setFileInput: vi.fn().mockRejectedValue(new Error('No element found')),
|
|
219
|
+
wait: vi.fn().mockResolvedValue(undefined),
|
|
220
|
+
evaluate: vi.fn((script) => {
|
|
221
|
+
return Promise.resolve({ ok: true });
|
|
222
|
+
}),
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const result = await uploadChatGPTImages(page, [filePath]);
|
|
226
|
+
|
|
227
|
+
expect(result).toEqual({ ok: true, files: [filePath] });
|
|
228
|
+
const fallbackScript = page.evaluate.mock.calls
|
|
229
|
+
.map(([script]) => String(script))
|
|
230
|
+
.find(script => script.includes('new DataTransfer()'));
|
|
231
|
+
expect(fallbackScript).toContain('preventDefault()');
|
|
232
|
+
expect(fallbackScript).toContain('stopPropagation()');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('exposes image MIME inference for fallback upload', () => {
|
|
236
|
+
expect(__test__.imageMimeFromPath('/tmp/a.png')).toBe('image/png');
|
|
237
|
+
expect(__test__.imageMimeFromPath('/tmp/a.webp')).toBe('image/webp');
|
|
238
|
+
expect(__test__.imageMimeFromPath('/tmp/a.jpg')).toBe('image/jpeg');
|
|
239
|
+
});
|
|
240
|
+
});
|
package/clis/claude/ask.js
CHANGED
|
@@ -15,7 +15,7 @@ export const askCommand = cli({
|
|
|
15
15
|
domain: CLAUDE_DOMAIN,
|
|
16
16
|
strategy: Strategy.COOKIE,
|
|
17
17
|
browser: true,
|
|
18
|
-
|
|
18
|
+
siteSession: 'persistent',
|
|
19
19
|
navigateBefore: false,
|
|
20
20
|
args: [
|
|
21
21
|
{ name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
|
package/clis/claude/detail.js
CHANGED
|
@@ -10,7 +10,7 @@ export const detailCommand = cli({
|
|
|
10
10
|
domain: CLAUDE_DOMAIN,
|
|
11
11
|
strategy: Strategy.COOKIE,
|
|
12
12
|
browser: true,
|
|
13
|
-
|
|
13
|
+
siteSession: 'persistent',
|
|
14
14
|
navigateBefore: false,
|
|
15
15
|
args: [
|
|
16
16
|
{ name: 'id', positional: true, required: true, help: 'Conversation ID (UUID from /chat/<id>)' },
|
package/clis/claude/history.js
CHANGED
|
@@ -10,7 +10,7 @@ export const historyCommand = cli({
|
|
|
10
10
|
domain: CLAUDE_DOMAIN,
|
|
11
11
|
strategy: Strategy.COOKIE,
|
|
12
12
|
browser: true,
|
|
13
|
-
|
|
13
|
+
siteSession: 'persistent',
|
|
14
14
|
navigateBefore: false,
|
|
15
15
|
args: [
|
|
16
16
|
{ name: 'limit', type: 'int', default: 20, help: 'Max conversations to show' },
|
package/clis/claude/new.js
CHANGED
package/clis/claude/read.js
CHANGED
package/clis/claude/send.js
CHANGED
|
@@ -10,7 +10,7 @@ export const sendCommand = cli({
|
|
|
10
10
|
domain: CLAUDE_DOMAIN,
|
|
11
11
|
strategy: Strategy.COOKIE,
|
|
12
12
|
browser: true,
|
|
13
|
-
|
|
13
|
+
siteSession: 'persistent',
|
|
14
14
|
navigateBefore: false,
|
|
15
15
|
args: [
|
|
16
16
|
{ name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
|
package/clis/claude/status.js
CHANGED
package/clis/deepseek/ask.js
CHANGED
|
@@ -14,7 +14,7 @@ export const askCommand = cli({
|
|
|
14
14
|
domain: DEEPSEEK_DOMAIN,
|
|
15
15
|
strategy: Strategy.COOKIE,
|
|
16
16
|
browser: true,
|
|
17
|
-
|
|
17
|
+
siteSession: 'persistent',
|
|
18
18
|
navigateBefore: false,
|
|
19
19
|
args: [
|
|
20
20
|
{ name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
|
package/clis/deepseek/detail.js
CHANGED
|
@@ -16,7 +16,7 @@ export const detailCommand = cli({
|
|
|
16
16
|
domain: DEEPSEEK_DOMAIN,
|
|
17
17
|
strategy: Strategy.COOKIE,
|
|
18
18
|
browser: true,
|
|
19
|
-
|
|
19
|
+
siteSession: 'persistent',
|
|
20
20
|
navigateBefore: false,
|
|
21
21
|
args: [
|
|
22
22
|
{ name: 'id', required: true, positional: true, help: 'Conversation ID (UUID) or full /a/chat/s/<id> URL' },
|
package/clis/deepseek/history.js
CHANGED
|
@@ -9,7 +9,7 @@ export const historyCommand = cli({
|
|
|
9
9
|
domain: DEEPSEEK_DOMAIN,
|
|
10
10
|
strategy: Strategy.COOKIE,
|
|
11
11
|
browser: true,
|
|
12
|
-
|
|
12
|
+
siteSession: 'persistent',
|
|
13
13
|
navigateBefore: false,
|
|
14
14
|
args: [
|
|
15
15
|
{ name: 'limit', type: 'int', default: 20, help: 'Max conversations to show' },
|
package/clis/deepseek/new.js
CHANGED
package/clis/deepseek/read.js
CHANGED
package/clis/deepseek/send.js
CHANGED
|
@@ -15,7 +15,7 @@ export const sendCommand = cli({
|
|
|
15
15
|
domain: DEEPSEEK_DOMAIN,
|
|
16
16
|
strategy: Strategy.COOKIE,
|
|
17
17
|
browser: true,
|
|
18
|
-
|
|
18
|
+
siteSession: 'persistent',
|
|
19
19
|
navigateBefore: false,
|
|
20
20
|
args: [
|
|
21
21
|
{ name: 'id', required: true, positional: true, help: 'Conversation ID (UUID) or full /a/chat/s/<id> URL' },
|
package/clis/deepseek/status.js
CHANGED
package/clis/doubao/ask.js
CHANGED
|
@@ -9,7 +9,7 @@ export const askCommand = cli({
|
|
|
9
9
|
domain: DOUBAO_DOMAIN,
|
|
10
10
|
strategy: Strategy.COOKIE,
|
|
11
11
|
browser: true,
|
|
12
|
-
|
|
12
|
+
siteSession: 'persistent',
|
|
13
13
|
navigateBefore: false,
|
|
14
14
|
args: [
|
|
15
15
|
{ name: 'text', required: true, positional: true, help: 'Prompt to send' },
|
package/clis/doubao/detail.js
CHANGED
|
@@ -8,7 +8,7 @@ export const detailCommand = cli({
|
|
|
8
8
|
domain: DOUBAO_DOMAIN,
|
|
9
9
|
strategy: Strategy.COOKIE,
|
|
10
10
|
browser: true,
|
|
11
|
-
|
|
11
|
+
siteSession: 'persistent',
|
|
12
12
|
navigateBefore: false,
|
|
13
13
|
args: [
|
|
14
14
|
{ name: 'id', required: true, positional: true, help: 'Conversation ID (numeric or full URL)' },
|
package/clis/doubao/history.js
CHANGED
|
@@ -8,7 +8,7 @@ export const historyCommand = cli({
|
|
|
8
8
|
domain: DOUBAO_DOMAIN,
|
|
9
9
|
strategy: Strategy.COOKIE,
|
|
10
10
|
browser: true,
|
|
11
|
-
|
|
11
|
+
siteSession: 'persistent',
|
|
12
12
|
navigateBefore: false,
|
|
13
13
|
args: [
|
|
14
14
|
{ name: 'limit', required: false, help: 'Max number of conversations to show', default: '50' },
|
|
@@ -8,7 +8,7 @@ export const meetingSummaryCommand = cli({
|
|
|
8
8
|
domain: DOUBAO_DOMAIN,
|
|
9
9
|
strategy: Strategy.COOKIE,
|
|
10
10
|
browser: true,
|
|
11
|
-
|
|
11
|
+
siteSession: 'persistent',
|
|
12
12
|
navigateBefore: false,
|
|
13
13
|
args: [
|
|
14
14
|
{ name: 'id', required: true, positional: true, help: 'Conversation ID (numeric or full URL)' },
|
|
@@ -8,7 +8,7 @@ export const meetingTranscriptCommand = cli({
|
|
|
8
8
|
domain: DOUBAO_DOMAIN,
|
|
9
9
|
strategy: Strategy.COOKIE,
|
|
10
10
|
browser: true,
|
|
11
|
-
|
|
11
|
+
siteSession: 'persistent',
|
|
12
12
|
navigateBefore: false,
|
|
13
13
|
args: [
|
|
14
14
|
{ name: 'id', required: true, positional: true, help: 'Conversation ID (numeric or full URL)' },
|
package/clis/doubao/new.js
CHANGED
package/clis/doubao/read.js
CHANGED
package/clis/doubao/send.js
CHANGED
|
@@ -8,7 +8,7 @@ export const sendCommand = cli({
|
|
|
8
8
|
domain: DOUBAO_DOMAIN,
|
|
9
9
|
strategy: Strategy.COOKIE,
|
|
10
10
|
browser: true,
|
|
11
|
-
|
|
11
|
+
siteSession: 'persistent',
|
|
12
12
|
navigateBefore: false,
|
|
13
13
|
args: [{ name: 'text', required: true, positional: true, help: 'Message to send' }],
|
|
14
14
|
columns: ['Status', 'SubmittedBy', 'InjectedText'],
|
package/clis/doubao/status.js
CHANGED
package/clis/gemini/ask.js
CHANGED
package/clis/gemini/image.js
CHANGED
package/clis/gemini/new.js
CHANGED
package/clis/grok/ask.js
CHANGED
|
@@ -29,7 +29,7 @@ export const askCommand = cli({
|
|
|
29
29
|
domain: 'grok.com',
|
|
30
30
|
strategy: Strategy.COOKIE,
|
|
31
31
|
browser: true,
|
|
32
|
-
|
|
32
|
+
siteSession: 'persistent',
|
|
33
33
|
args: [
|
|
34
34
|
{ name: 'prompt', positional: true, type: 'string', required: true, help: 'Prompt to send to Grok' },
|
|
35
35
|
{ name: 'timeout', type: 'int', default: 120, help: 'Max seconds to wait for response (default: 120)' },
|
package/clis/grok/detail.js
CHANGED
|
@@ -17,7 +17,7 @@ cli({
|
|
|
17
17
|
strategy: Strategy.COOKIE,
|
|
18
18
|
browser: true,
|
|
19
19
|
navigateBefore: false,
|
|
20
|
-
|
|
20
|
+
siteSession: 'persistent',
|
|
21
21
|
args: [
|
|
22
22
|
{ name: 'id', positional: true, required: true, help: 'Session ID (UUID) or full https://grok.com/c/<id> URL' },
|
|
23
23
|
{ name: 'markdown', type: 'boolean', default: false, help: 'Emit assistant replies as markdown' },
|
package/clis/grok/history.js
CHANGED
|
@@ -16,7 +16,7 @@ cli({
|
|
|
16
16
|
domain: GROK_DOMAIN,
|
|
17
17
|
strategy: Strategy.COOKIE,
|
|
18
18
|
browser: true,
|
|
19
|
-
|
|
19
|
+
siteSession: 'persistent',
|
|
20
20
|
navigateBefore: false,
|
|
21
21
|
args: [
|
|
22
22
|
{ name: 'limit', type: 'int', default: 20, help: 'Max conversations to show (default 20, max 100)' },
|
package/clis/grok/image.js
CHANGED
|
@@ -253,7 +253,7 @@ export const imageCommand = cli({
|
|
|
253
253
|
domain: 'grok.com',
|
|
254
254
|
strategy: Strategy.COOKIE,
|
|
255
255
|
browser: true,
|
|
256
|
-
|
|
256
|
+
siteSession: 'persistent',
|
|
257
257
|
args: [
|
|
258
258
|
{ name: 'prompt', positional: true, type: 'string', required: true, help: 'Image generation prompt' },
|
|
259
259
|
{ name: 'timeout', type: 'int', default: 240, help: 'Max seconds to wait for the image (default: 240)' },
|
package/clis/grok/new.js
CHANGED
package/clis/grok/read.js
CHANGED
|
@@ -15,7 +15,7 @@ cli({
|
|
|
15
15
|
domain: GROK_DOMAIN,
|
|
16
16
|
strategy: Strategy.COOKIE,
|
|
17
17
|
browser: true,
|
|
18
|
-
|
|
18
|
+
siteSession: 'persistent',
|
|
19
19
|
navigateBefore: false,
|
|
20
20
|
args: [
|
|
21
21
|
{ name: 'markdown', type: 'boolean', default: false, help: 'Emit assistant replies as markdown' },
|
package/clis/grok/send.js
CHANGED
|
@@ -18,7 +18,7 @@ cli({
|
|
|
18
18
|
domain: GROK_DOMAIN,
|
|
19
19
|
strategy: Strategy.COOKIE,
|
|
20
20
|
browser: true,
|
|
21
|
-
|
|
21
|
+
siteSession: 'persistent',
|
|
22
22
|
navigateBefore: false,
|
|
23
23
|
args: [
|
|
24
24
|
{ name: 'prompt', required: true, positional: true, help: 'Prompt to send to Grok' },
|
package/clis/grok/status.js
CHANGED
|
@@ -17,7 +17,7 @@ cli({
|
|
|
17
17
|
await requireNotebooklmSession(page);
|
|
18
18
|
const state = await getNotebooklmPageState(page);
|
|
19
19
|
if (state.kind !== 'notebook') {
|
|
20
|
-
throw new EmptyResultError('opencli notebooklm current', 'No NotebookLM notebook is open in the
|
|
20
|
+
throw new EmptyResultError('opencli notebooklm current', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
|
|
21
21
|
}
|
|
22
22
|
const current = await readCurrentNotebooklm(page);
|
|
23
23
|
if (!current) {
|
package/clis/notebooklm/get.js
CHANGED
|
@@ -18,7 +18,7 @@ cli({
|
|
|
18
18
|
await requireNotebooklmSession(page);
|
|
19
19
|
const state = await getNotebooklmPageState(page);
|
|
20
20
|
if (state.kind !== 'notebook') {
|
|
21
|
-
throw new EmptyResultError('opencli notebooklm get', 'No NotebookLM notebook is open in the
|
|
21
|
+
throw new EmptyResultError('opencli notebooklm get', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
|
|
22
22
|
}
|
|
23
23
|
const rpcRow = await getNotebooklmDetailViaRpc(page).catch(() => null);
|
|
24
24
|
if (rpcRow)
|
|
@@ -17,7 +17,7 @@ cli({
|
|
|
17
17
|
await requireNotebooklmSession(page);
|
|
18
18
|
const state = await getNotebooklmPageState(page);
|
|
19
19
|
if (state.kind !== 'notebook') {
|
|
20
|
-
throw new EmptyResultError('opencli notebooklm history', 'No NotebookLM notebook is open in the
|
|
20
|
+
throw new EmptyResultError('opencli notebooklm history', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
|
|
21
21
|
}
|
|
22
22
|
const rows = await listNotebooklmHistoryViaRpc(page);
|
|
23
23
|
return rows;
|
|
@@ -18,7 +18,7 @@ cli({
|
|
|
18
18
|
await requireNotebooklmSession(page);
|
|
19
19
|
const state = await getNotebooklmPageState(page);
|
|
20
20
|
if (state.kind !== 'notebook') {
|
|
21
|
-
throw new EmptyResultError('opencli notebooklm note-list', 'No NotebookLM notebook is open in the
|
|
21
|
+
throw new EmptyResultError('opencli notebooklm note-list', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
|
|
22
22
|
}
|
|
23
23
|
const rows = await listNotebooklmNotesFromPage(page);
|
|
24
24
|
if (rows.length > 0)
|
|
@@ -31,7 +31,7 @@ cli({
|
|
|
31
31
|
await requireNotebooklmSession(page);
|
|
32
32
|
const state = await getNotebooklmPageState(page);
|
|
33
33
|
if (state.kind !== 'notebook') {
|
|
34
|
-
throw new EmptyResultError('opencli notebooklm notes-get', 'No NotebookLM notebook is open in the
|
|
34
|
+
throw new EmptyResultError('opencli notebooklm notes-get', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
|
|
35
35
|
}
|
|
36
36
|
const query = typeof kwargs.note === 'string' ? kwargs.note : String(kwargs.note ?? '');
|
|
37
37
|
const visible = await readNotebooklmVisibleNoteFromPage(page);
|
package/clis/notebooklm/open.js
CHANGED
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
name: 'open',
|
|
8
8
|
access: 'read',
|
|
9
9
|
aliases: ['select'],
|
|
10
|
-
description: 'Open one NotebookLM notebook in the
|
|
10
|
+
description: 'Open one NotebookLM notebook in the adapter session by id or URL',
|
|
11
11
|
domain: NOTEBOOKLM_DOMAIN,
|
|
12
12
|
strategy: Strategy.COOKIE,
|
|
13
13
|
browser: true,
|
|
@@ -28,7 +28,7 @@ cli({
|
|
|
28
28
|
await requireNotebooklmSession(page);
|
|
29
29
|
const state = await getNotebooklmPageState(page);
|
|
30
30
|
if (state.kind !== 'notebook') {
|
|
31
|
-
throw new CliError('NOTEBOOKLM_OPEN_FAILED', `NotebookLM notebook "${notebookId}" did not open in the
|
|
31
|
+
throw new CliError('NOTEBOOKLM_OPEN_FAILED', `NotebookLM notebook "${notebookId}" did not open in the adapter session`, 'Run `opencli notebooklm list -f json` first and pass a valid notebook id.');
|
|
32
32
|
}
|
|
33
33
|
if (state.notebookId !== notebookId) {
|
|
34
34
|
console.warn(`[notebooklm open] expected notebook "${notebookId}" but page reports "${state.notebookId}"; continuing`);
|
|
@@ -38,7 +38,7 @@ describe('notebooklm open', () => {
|
|
|
38
38
|
source: 'current-page',
|
|
39
39
|
});
|
|
40
40
|
});
|
|
41
|
-
it('opens a notebook by id in the
|
|
41
|
+
it('opens a notebook by id in the adapter session', async () => {
|
|
42
42
|
const page = {
|
|
43
43
|
goto: vi.fn(async () => { }),
|
|
44
44
|
wait: vi.fn(async () => { }),
|
|
@@ -24,7 +24,7 @@ cli({
|
|
|
24
24
|
await requireNotebooklmSession(page);
|
|
25
25
|
const state = await getNotebooklmPageState(page);
|
|
26
26
|
if (state.kind !== 'notebook') {
|
|
27
|
-
throw new EmptyResultError('opencli notebooklm source-fulltext', 'No NotebookLM notebook is open in the
|
|
27
|
+
throw new EmptyResultError('opencli notebooklm source-fulltext', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
|
|
28
28
|
}
|
|
29
29
|
const rpcRows = await listNotebooklmSourcesViaRpc(page).catch(() => []);
|
|
30
30
|
const rows = rpcRows.length > 0 ? rpcRows : await listNotebooklmSourcesFromPage(page);
|
|
@@ -24,7 +24,7 @@ cli({
|
|
|
24
24
|
await requireNotebooklmSession(page);
|
|
25
25
|
const state = await getNotebooklmPageState(page);
|
|
26
26
|
if (state.kind !== 'notebook') {
|
|
27
|
-
throw new EmptyResultError('opencli notebooklm source-get', 'No NotebookLM notebook is open in the
|
|
27
|
+
throw new EmptyResultError('opencli notebooklm source-get', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
|
|
28
28
|
}
|
|
29
29
|
const rpcRows = await listNotebooklmSourcesViaRpc(page).catch(() => []);
|
|
30
30
|
const rows = rpcRows.length > 0 ? rpcRows : await listNotebooklmSourcesFromPage(page);
|
|
@@ -24,7 +24,7 @@ cli({
|
|
|
24
24
|
await requireNotebooklmSession(page);
|
|
25
25
|
const state = await getNotebooklmPageState(page);
|
|
26
26
|
if (state.kind !== 'notebook') {
|
|
27
|
-
throw new EmptyResultError('opencli notebooklm source-guide', 'No NotebookLM notebook is open in the
|
|
27
|
+
throw new EmptyResultError('opencli notebooklm source-guide', 'No NotebookLM notebook is open in the adapter session. Run `opencli notebooklm open <notebook>` first.');
|
|
28
28
|
}
|
|
29
29
|
const rpcRows = await listNotebooklmSourcesViaRpc(page).catch(() => []);
|
|
30
30
|
const rows = rpcRows.length > 0 ? rpcRows : await listNotebooklmSourcesFromPage(page);
|