@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.
Files changed (149) hide show
  1. package/README.md +8 -9
  2. package/README.zh-CN.md +8 -8
  3. package/cli-manifest.json +97 -271
  4. package/clis/chatgpt/ask.js +1 -1
  5. package/clis/chatgpt/commands.test.js +2 -2
  6. package/clis/chatgpt/detail.js +1 -1
  7. package/clis/chatgpt/history.js +1 -1
  8. package/clis/chatgpt/image.js +38 -4
  9. package/clis/chatgpt/image.test.js +68 -1
  10. package/clis/chatgpt/new.js +1 -1
  11. package/clis/chatgpt/read.js +1 -1
  12. package/clis/chatgpt/send.js +1 -1
  13. package/clis/chatgpt/status.js +1 -1
  14. package/clis/chatgpt/utils.js +208 -16
  15. package/clis/chatgpt/utils.test.js +131 -2
  16. package/clis/claude/ask.js +1 -1
  17. package/clis/claude/detail.js +1 -1
  18. package/clis/claude/history.js +1 -1
  19. package/clis/claude/new.js +1 -1
  20. package/clis/claude/read.js +1 -1
  21. package/clis/claude/send.js +1 -1
  22. package/clis/claude/status.js +1 -1
  23. package/clis/deepseek/ask.js +1 -1
  24. package/clis/deepseek/detail.js +1 -1
  25. package/clis/deepseek/history.js +1 -1
  26. package/clis/deepseek/new.js +1 -1
  27. package/clis/deepseek/read.js +1 -1
  28. package/clis/deepseek/send.js +1 -1
  29. package/clis/deepseek/status.js +1 -1
  30. package/clis/doubao/ask.js +1 -1
  31. package/clis/doubao/detail.js +1 -1
  32. package/clis/doubao/history.js +1 -1
  33. package/clis/doubao/meeting-summary.js +1 -1
  34. package/clis/doubao/meeting-transcript.js +1 -1
  35. package/clis/doubao/new.js +1 -1
  36. package/clis/doubao/read.js +1 -1
  37. package/clis/doubao/send.js +1 -1
  38. package/clis/doubao/status.js +1 -1
  39. package/clis/gemini/ask.js +1 -1
  40. package/clis/gemini/deep-research-result.js +1 -1
  41. package/clis/gemini/deep-research.js +1 -1
  42. package/clis/gemini/image.js +1 -1
  43. package/clis/gemini/new.js +1 -1
  44. package/clis/grok/ask.js +1 -1
  45. package/clis/grok/detail.js +1 -1
  46. package/clis/grok/history.js +1 -1
  47. package/clis/grok/image.js +1 -1
  48. package/clis/grok/new.js +1 -1
  49. package/clis/grok/read.js +1 -1
  50. package/clis/grok/send.js +1 -1
  51. package/clis/grok/status.js +1 -1
  52. package/clis/notebooklm/current.js +1 -1
  53. package/clis/notebooklm/get.js +1 -1
  54. package/clis/notebooklm/history.js +1 -1
  55. package/clis/notebooklm/note-list.js +1 -1
  56. package/clis/notebooklm/notes-get.js +1 -1
  57. package/clis/notebooklm/open.js +2 -2
  58. package/clis/notebooklm/open.test.js +1 -1
  59. package/clis/notebooklm/source-fulltext.js +1 -1
  60. package/clis/notebooklm/source-get.js +1 -1
  61. package/clis/notebooklm/source-guide.js +1 -1
  62. package/clis/notebooklm/source-list.js +1 -1
  63. package/clis/notebooklm/summary.js +1 -1
  64. package/clis/qwen/ask.js +1 -1
  65. package/clis/qwen/detail.js +1 -1
  66. package/clis/qwen/history.js +1 -1
  67. package/clis/qwen/image.js +1 -1
  68. package/clis/qwen/new.js +1 -1
  69. package/clis/qwen/read.js +1 -1
  70. package/clis/qwen/send.js +1 -1
  71. package/clis/qwen/status.js +1 -1
  72. package/clis/reddit/comment.js +1 -1
  73. package/clis/reddit/frontpage.js +1 -1
  74. package/clis/reddit/popular.js +1 -1
  75. package/clis/reddit/read.js +1 -1
  76. package/clis/reddit/read.test.js +2 -2
  77. package/clis/reddit/save.js +1 -1
  78. package/clis/reddit/saved.js +1 -1
  79. package/clis/reddit/search.js +1 -1
  80. package/clis/reddit/subreddit.js +1 -1
  81. package/clis/reddit/subscribe.js +1 -1
  82. package/clis/reddit/upvote.js +1 -1
  83. package/clis/reddit/upvoted.js +1 -1
  84. package/clis/reddit/user-comments.js +1 -1
  85. package/clis/reddit/user-posts.js +1 -1
  86. package/clis/reddit/user.js +1 -1
  87. package/clis/twitter/article.js +1 -1
  88. package/clis/twitter/bookmark-folder.js +1 -1
  89. package/clis/twitter/bookmark-folders.js +1 -1
  90. package/clis/twitter/bookmarks.js +1 -1
  91. package/clis/twitter/download.js +1 -1
  92. package/clis/twitter/followers.js +1 -1
  93. package/clis/twitter/following.js +1 -1
  94. package/clis/twitter/likes.js +1 -1
  95. package/clis/twitter/list-tweets.js +1 -1
  96. package/clis/twitter/lists.js +1 -1
  97. package/clis/twitter/notifications.js +1 -1
  98. package/clis/twitter/profile.js +1 -1
  99. package/clis/twitter/search.js +1 -1
  100. package/clis/twitter/thread.js +1 -1
  101. package/clis/twitter/timeline.js +1 -1
  102. package/clis/twitter/trending.js +1 -1
  103. package/clis/twitter/tweets.js +1 -1
  104. package/clis/yuanbao/ask.js +1 -1
  105. package/clis/yuanbao/detail.js +1 -1
  106. package/clis/yuanbao/history.js +1 -1
  107. package/clis/yuanbao/new.js +1 -1
  108. package/clis/yuanbao/read.js +1 -1
  109. package/clis/yuanbao/send.js +1 -1
  110. package/clis/yuanbao/status.js +1 -1
  111. package/dist/src/browser/bridge.d.ts +3 -1
  112. package/dist/src/browser/bridge.js +3 -1
  113. package/dist/src/browser/cdp.d.ts +3 -1
  114. package/dist/src/browser/daemon-client.d.ts +7 -14
  115. package/dist/src/browser/daemon-client.js +2 -6
  116. package/dist/src/browser/network-cache.d.ts +5 -5
  117. package/dist/src/browser/network-cache.js +8 -8
  118. package/dist/src/browser/network-cache.test.js +4 -4
  119. package/dist/src/browser/page.d.ts +8 -7
  120. package/dist/src/browser/page.js +23 -16
  121. package/dist/src/browser/page.test.js +60 -30
  122. package/dist/src/build-manifest.js +1 -1
  123. package/dist/src/cli.js +60 -162
  124. package/dist/src/cli.test.js +178 -197
  125. package/dist/src/commanderAdapter.js +2 -0
  126. package/dist/src/discovery.js +1 -1
  127. package/dist/src/doctor.d.ts +0 -4
  128. package/dist/src/doctor.js +8 -72
  129. package/dist/src/doctor.test.js +26 -97
  130. package/dist/src/execution.d.ts +1 -0
  131. package/dist/src/execution.js +20 -21
  132. package/dist/src/execution.test.js +27 -31
  133. package/dist/src/help.js +7 -1
  134. package/dist/src/main.js +0 -19
  135. package/dist/src/manifest-types.d.ts +2 -4
  136. package/dist/src/observation/artifact.js +1 -1
  137. package/dist/src/observation/artifact.test.js +3 -3
  138. package/dist/src/observation/events.d.ts +1 -1
  139. package/dist/src/observation/manager.js +1 -1
  140. package/dist/src/observation/manager.test.js +3 -3
  141. package/dist/src/registry-api.d.ts +1 -1
  142. package/dist/src/registry.d.ts +3 -12
  143. package/dist/src/registry.js +6 -10
  144. package/dist/src/runtime.d.ts +7 -2
  145. package/dist/src/runtime.js +3 -1
  146. package/dist/src/serialization.d.ts +1 -1
  147. package/dist/src/serialization.js +1 -1
  148. package/dist/src/types.d.ts +0 -15
  149. package/package.json +1 -1
@@ -1,5 +1,17 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { __test__, sendChatGPTMessage, waitForChatGPTImages } from './utils.js';
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
+ });
@@ -15,7 +15,7 @@ export const askCommand = cli({
15
15
  domain: CLAUDE_DOMAIN,
16
16
  strategy: Strategy.COOKIE,
17
17
  browser: true,
18
- browserSession: { reuse: 'site' },
18
+ siteSession: 'persistent',
19
19
  navigateBefore: false,
20
20
  args: [
21
21
  { name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
@@ -10,7 +10,7 @@ export const detailCommand = cli({
10
10
  domain: CLAUDE_DOMAIN,
11
11
  strategy: Strategy.COOKIE,
12
12
  browser: true,
13
- browserSession: { reuse: 'site' },
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>)' },
@@ -10,7 +10,7 @@ export const historyCommand = cli({
10
10
  domain: CLAUDE_DOMAIN,
11
11
  strategy: Strategy.COOKIE,
12
12
  browser: true,
13
- browserSession: { reuse: 'site' },
13
+ siteSession: 'persistent',
14
14
  navigateBefore: false,
15
15
  args: [
16
16
  { name: 'limit', type: 'int', default: 20, help: 'Max conversations to show' },
@@ -9,7 +9,7 @@ export const newCommand = cli({
9
9
  domain: CLAUDE_DOMAIN,
10
10
  strategy: Strategy.COOKIE,
11
11
  browser: true,
12
- browserSession: { reuse: 'site' },
12
+ siteSession: 'persistent',
13
13
  navigateBefore: false,
14
14
  args: [],
15
15
  columns: ['Status'],
@@ -10,7 +10,7 @@ export const readCommand = cli({
10
10
  domain: CLAUDE_DOMAIN,
11
11
  strategy: Strategy.COOKIE,
12
12
  browser: true,
13
- browserSession: { reuse: 'site' },
13
+ siteSession: 'persistent',
14
14
  navigateBefore: false,
15
15
  args: [],
16
16
  columns: ['Index', 'Role', 'Text'],
@@ -10,7 +10,7 @@ export const sendCommand = cli({
10
10
  domain: CLAUDE_DOMAIN,
11
11
  strategy: Strategy.COOKIE,
12
12
  browser: true,
13
- browserSession: { reuse: 'site' },
13
+ siteSession: 'persistent',
14
14
  navigateBefore: false,
15
15
  args: [
16
16
  { name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
@@ -9,7 +9,7 @@ export const statusCommand = cli({
9
9
  domain: CLAUDE_DOMAIN,
10
10
  strategy: Strategy.COOKIE,
11
11
  browser: true,
12
- browserSession: { reuse: 'site' },
12
+ siteSession: 'persistent',
13
13
  navigateBefore: false,
14
14
  args: [],
15
15
  columns: ['Status', 'Login', 'Url'],
@@ -14,7 +14,7 @@ export const askCommand = cli({
14
14
  domain: DEEPSEEK_DOMAIN,
15
15
  strategy: Strategy.COOKIE,
16
16
  browser: true,
17
- browserSession: { reuse: 'site' },
17
+ siteSession: 'persistent',
18
18
  navigateBefore: false,
19
19
  args: [
20
20
  { name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
@@ -16,7 +16,7 @@ export const detailCommand = cli({
16
16
  domain: DEEPSEEK_DOMAIN,
17
17
  strategy: Strategy.COOKIE,
18
18
  browser: true,
19
- browserSession: { reuse: 'site' },
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' },
@@ -9,7 +9,7 @@ export const historyCommand = cli({
9
9
  domain: DEEPSEEK_DOMAIN,
10
10
  strategy: Strategy.COOKIE,
11
11
  browser: true,
12
- browserSession: { reuse: 'site' },
12
+ siteSession: 'persistent',
13
13
  navigateBefore: false,
14
14
  args: [
15
15
  { name: 'limit', type: 'int', default: 20, help: 'Max conversations to show' },
@@ -10,7 +10,7 @@ export const newCommand = cli({
10
10
  domain: DEEPSEEK_DOMAIN,
11
11
  strategy: Strategy.COOKIE,
12
12
  browser: true,
13
- browserSession: { reuse: 'site' },
13
+ siteSession: 'persistent',
14
14
  navigateBefore: false,
15
15
  args: [],
16
16
  columns: ['Status'],
@@ -9,7 +9,7 @@ export const readCommand = cli({
9
9
  domain: DEEPSEEK_DOMAIN,
10
10
  strategy: Strategy.COOKIE,
11
11
  browser: true,
12
- browserSession: { reuse: 'site' },
12
+ siteSession: 'persistent',
13
13
  navigateBefore: false,
14
14
  args: [],
15
15
  columns: ['Role', 'Text'],
@@ -15,7 +15,7 @@ export const sendCommand = cli({
15
15
  domain: DEEPSEEK_DOMAIN,
16
16
  strategy: Strategy.COOKIE,
17
17
  browser: true,
18
- browserSession: { reuse: 'site' },
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' },
@@ -9,7 +9,7 @@ export const statusCommand = cli({
9
9
  domain: DEEPSEEK_DOMAIN,
10
10
  strategy: Strategy.COOKIE,
11
11
  browser: true,
12
- browserSession: { reuse: 'site' },
12
+ siteSession: 'persistent',
13
13
  navigateBefore: false,
14
14
  args: [],
15
15
  columns: ['Status', 'Login', 'Url'],
@@ -9,7 +9,7 @@ export const askCommand = cli({
9
9
  domain: DOUBAO_DOMAIN,
10
10
  strategy: Strategy.COOKIE,
11
11
  browser: true,
12
- browserSession: { reuse: 'site' },
12
+ siteSession: 'persistent',
13
13
  navigateBefore: false,
14
14
  args: [
15
15
  { name: 'text', required: true, positional: true, help: 'Prompt to send' },
@@ -8,7 +8,7 @@ export const detailCommand = cli({
8
8
  domain: DOUBAO_DOMAIN,
9
9
  strategy: Strategy.COOKIE,
10
10
  browser: true,
11
- browserSession: { reuse: 'site' },
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 historyCommand = cli({
8
8
  domain: DOUBAO_DOMAIN,
9
9
  strategy: Strategy.COOKIE,
10
10
  browser: true,
11
- browserSession: { reuse: 'site' },
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
- browserSession: { reuse: 'site' },
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
- browserSession: { reuse: 'site' },
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 newCommand = cli({
8
8
  domain: DOUBAO_DOMAIN,
9
9
  strategy: Strategy.COOKIE,
10
10
  browser: true,
11
- browserSession: { reuse: 'site' },
11
+ siteSession: 'persistent',
12
12
  navigateBefore: false,
13
13
  args: [],
14
14
  columns: ['Status', 'Action'],
@@ -8,7 +8,7 @@ export const readCommand = cli({
8
8
  domain: DOUBAO_DOMAIN,
9
9
  strategy: Strategy.COOKIE,
10
10
  browser: true,
11
- browserSession: { reuse: 'site' },
11
+ siteSession: 'persistent',
12
12
  navigateBefore: false,
13
13
  args: [],
14
14
  columns: ['Role', 'Text'],
@@ -8,7 +8,7 @@ export const sendCommand = cli({
8
8
  domain: DOUBAO_DOMAIN,
9
9
  strategy: Strategy.COOKIE,
10
10
  browser: true,
11
- browserSession: { reuse: 'site' },
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'],
@@ -8,7 +8,7 @@ export const statusCommand = cli({
8
8
  domain: DOUBAO_DOMAIN,
9
9
  strategy: Strategy.COOKIE,
10
10
  browser: true,
11
- browserSession: { reuse: 'site' },
11
+ siteSession: 'persistent',
12
12
  navigateBefore: false,
13
13
  args: [],
14
14
  columns: ['Status', 'Login', 'Url', 'Title'],
@@ -16,7 +16,7 @@ export const askCommand = cli({
16
16
  domain: GEMINI_DOMAIN,
17
17
  strategy: Strategy.COOKIE,
18
18
  browser: true,
19
- browserSession: { reuse: 'site' },
19
+ siteSession: 'persistent',
20
20
  navigateBefore: false,
21
21
  defaultFormat: 'plain',
22
22
  args: [
@@ -44,7 +44,7 @@ export const deepResearchResultCommand = cli({
44
44
  domain: GEMINI_DOMAIN,
45
45
  strategy: Strategy.COOKIE,
46
46
  browser: true,
47
- browserSession: { reuse: 'site' },
47
+ siteSession: 'persistent',
48
48
  navigateBefore: false,
49
49
  defaultFormat: 'plain',
50
50
  args: [
@@ -23,7 +23,7 @@ export const deepResearchCommand = cli({
23
23
  domain: GEMINI_DOMAIN,
24
24
  strategy: Strategy.COOKIE,
25
25
  browser: true,
26
- browserSession: { reuse: 'site' },
26
+ siteSession: 'persistent',
27
27
  navigateBefore: false,
28
28
  defaultFormat: 'plain',
29
29
  args: [
@@ -52,7 +52,7 @@ export const imageCommand = cli({
52
52
  domain: GEMINI_DOMAIN,
53
53
  strategy: Strategy.COOKIE,
54
54
  browser: true,
55
- browserSession: { reuse: 'site' },
55
+ siteSession: 'persistent',
56
56
  navigateBefore: false,
57
57
  defaultFormat: 'plain',
58
58
  args: [
@@ -8,7 +8,7 @@ export const newCommand = cli({
8
8
  domain: GEMINI_DOMAIN,
9
9
  strategy: Strategy.COOKIE,
10
10
  browser: true,
11
- browserSession: { reuse: 'site' },
11
+ siteSession: 'persistent',
12
12
  navigateBefore: false,
13
13
  args: [],
14
14
  columns: ['Status', 'Action'],
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
- browserSession: { reuse: 'site' },
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)' },
@@ -17,7 +17,7 @@ cli({
17
17
  strategy: Strategy.COOKIE,
18
18
  browser: true,
19
19
  navigateBefore: false,
20
- browserSession: { reuse: 'site' },
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' },
@@ -16,7 +16,7 @@ cli({
16
16
  domain: GROK_DOMAIN,
17
17
  strategy: Strategy.COOKIE,
18
18
  browser: true,
19
- browserSession: { reuse: 'site' },
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)' },
@@ -253,7 +253,7 @@ export const imageCommand = cli({
253
253
  domain: 'grok.com',
254
254
  strategy: Strategy.COOKIE,
255
255
  browser: true,
256
- browserSession: { reuse: 'site' },
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
@@ -9,7 +9,7 @@ cli({
9
9
  domain: GROK_DOMAIN,
10
10
  strategy: Strategy.COOKIE,
11
11
  browser: true,
12
- browserSession: { reuse: 'site' },
12
+ siteSession: 'persistent',
13
13
  navigateBefore: false,
14
14
  args: [],
15
15
  columns: ['Status'],
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
- browserSession: { reuse: 'site' },
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
- browserSession: { reuse: 'site' },
21
+ siteSession: 'persistent',
22
22
  navigateBefore: false,
23
23
  args: [
24
24
  { name: 'prompt', required: true, positional: true, help: 'Prompt to send to Grok' },
@@ -15,7 +15,7 @@ cli({
15
15
  domain: GROK_DOMAIN,
16
16
  strategy: Strategy.COOKIE,
17
17
  browser: true,
18
- browserSession: { reuse: 'site' },
18
+ siteSession: 'persistent',
19
19
  navigateBefore: false,
20
20
  args: [],
21
21
  columns: ['Status', 'Login', 'Model', 'SessionId', 'Url'],
@@ -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 automation workspace. Run `opencli notebooklm open <notebook>` first.');
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) {
@@ -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 automation workspace. Run `opencli notebooklm open <notebook>` first.');
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 automation workspace. Run `opencli notebooklm open <notebook>` first.');
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 automation workspace. Run `opencli notebooklm open <notebook>` first.');
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 automation workspace. Run `opencli notebooklm open <notebook>` first.');
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);
@@ -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 automation workspace by id or URL',
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 automation workspace`, 'Run `opencli notebooklm list -f json` first and pass a valid notebook id.');
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 automation workspace', async () => {
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 automation workspace. Run `opencli notebooklm open <notebook>` first.');
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 automation workspace. Run `opencli notebooklm open <notebook>` first.');
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 automation workspace. Run `opencli notebooklm open <notebook>` first.');
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);