@jackwener/opencli 1.7.4 → 1.7.5
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 +71 -49
- package/README.zh-CN.md +73 -60
- package/cli-manifest.json +3261 -1758
- package/clis/antigravity/serve.js +71 -25
- package/clis/baidu-scholar/search.js +87 -0
- package/clis/baidu-scholar/search.test.js +23 -0
- package/clis/deepseek/ask.js +74 -0
- package/clis/deepseek/history.js +25 -0
- package/clis/deepseek/new.js +20 -0
- package/clis/deepseek/read.js +22 -0
- package/clis/deepseek/status.js +24 -0
- package/clis/deepseek/utils.js +208 -0
- package/clis/eastmoney/_secid.js +78 -0
- package/clis/eastmoney/announcement.js +52 -0
- package/clis/eastmoney/convertible.js +73 -0
- package/clis/eastmoney/etf.js +65 -0
- package/clis/eastmoney/holders.js +78 -0
- package/clis/eastmoney/index-board.js +96 -0
- package/clis/eastmoney/kline.js +87 -0
- package/clis/eastmoney/kuaixun.js +54 -0
- package/clis/eastmoney/longhu.js +67 -0
- package/clis/eastmoney/money-flow.js +78 -0
- package/clis/eastmoney/northbound.js +57 -0
- package/clis/eastmoney/quote.js +107 -0
- package/clis/eastmoney/rank.js +94 -0
- package/clis/eastmoney/sectors.js +76 -0
- package/clis/google-scholar/search.js +58 -0
- package/clis/google-scholar/search.test.js +23 -0
- package/clis/gov-law/commands.test.js +39 -0
- package/clis/gov-law/recent.js +22 -0
- package/clis/gov-law/search.js +41 -0
- package/clis/gov-law/shared.js +51 -0
- package/clis/gov-policy/commands.test.js +27 -0
- package/clis/gov-policy/recent.js +47 -0
- package/clis/gov-policy/search.js +48 -0
- package/clis/nowcoder/companies.js +23 -0
- package/clis/nowcoder/creators.js +27 -0
- package/clis/nowcoder/detail.js +61 -0
- package/clis/nowcoder/experience.js +36 -0
- package/clis/nowcoder/hot.js +24 -0
- package/clis/nowcoder/jobs.js +21 -0
- package/clis/nowcoder/notifications.js +29 -0
- package/clis/nowcoder/papers.js +40 -0
- package/clis/nowcoder/practice.js +37 -0
- package/clis/nowcoder/recommend.js +30 -0
- package/clis/nowcoder/referral.js +39 -0
- package/clis/nowcoder/salary.js +40 -0
- package/clis/nowcoder/search.js +49 -0
- package/clis/nowcoder/suggest.js +33 -0
- package/clis/nowcoder/topics.js +27 -0
- package/clis/nowcoder/trending.js +25 -0
- package/clis/twitter/list-add.js +337 -0
- package/clis/twitter/list-add.test.js +15 -0
- package/clis/twitter/list-remove.js +297 -0
- package/clis/twitter/list-remove.test.js +14 -0
- package/clis/twitter/list-tweets.js +185 -0
- package/clis/twitter/list-tweets.test.js +108 -0
- package/clis/twitter/lists.js +134 -47
- package/clis/twitter/lists.test.js +105 -38
- package/clis/wanfang/search.js +66 -0
- package/clis/wanfang/search.test.js +23 -0
- package/clis/web/read.js +1 -1
- package/clis/weixin/download.js +3 -2
- package/clis/xiaohongshu/publish.js +149 -28
- package/clis/xiaohongshu/publish.test.js +319 -6
- package/clis/xiaoyuzhou/download.js +8 -4
- package/clis/xiaoyuzhou/download.test.js +23 -13
- package/clis/xiaoyuzhou/episode.js +9 -4
- package/clis/xiaoyuzhou/podcast-episodes.js +15 -11
- package/clis/xiaoyuzhou/podcast.js +9 -4
- package/clis/xiaoyuzhou/utils.js +0 -40
- package/clis/xiaoyuzhou/utils.test.js +15 -75
- package/clis/zsxq/dynamics.js +1 -1
- package/clis/zsxq/utils.js +6 -3
- package/clis/zsxq/utils.test.js +31 -0
- package/dist/src/browser/base-page.d.ts +1 -1
- package/dist/src/browser/bridge.d.ts +1 -0
- package/dist/src/browser/bridge.js +1 -1
- package/dist/src/browser/cdp.js +1 -1
- package/dist/src/browser/daemon-client.d.ts +6 -4
- package/dist/src/browser/daemon-client.js +6 -1
- package/dist/src/browser/daemon-client.test.js +40 -1
- package/dist/src/browser/dom-snapshot.js +7 -2
- package/dist/src/browser/page.d.ts +14 -4
- package/dist/src/browser/page.js +48 -7
- package/dist/src/browser/page.test.js +97 -0
- package/dist/src/cli.js +227 -150
- package/dist/src/cli.test.js +167 -90
- package/dist/src/commanderAdapter.d.ts +0 -1
- package/dist/src/commanderAdapter.js +2 -16
- package/dist/src/commanderAdapter.test.js +1 -1
- package/dist/src/completion-shared.js +2 -5
- package/dist/src/daemon.js +8 -0
- package/dist/src/download/article-download.d.ts +1 -0
- package/dist/src/download/article-download.js +3 -0
- package/dist/src/download/article-download.test.js +39 -0
- package/dist/src/plugin.d.ts +1 -8
- package/dist/src/plugin.js +1 -27
- package/dist/src/plugin.test.js +1 -59
- package/dist/src/registry.d.ts +1 -0
- package/dist/src/registry.js +3 -2
- package/dist/src/registry.test.js +22 -0
- package/dist/src/types.d.ts +14 -5
- package/package.json +1 -1
- package/clis/twitter/lists-parser.js +0 -77
- package/clis/twitter/lists.d.ts +0 -5
- package/dist/src/cascade.d.ts +0 -46
- package/dist/src/cascade.js +0 -135
- package/dist/src/explore.d.ts +0 -99
- package/dist/src/explore.js +0 -402
- package/dist/src/generate-verified.d.ts +0 -105
- package/dist/src/generate-verified.js +0 -696
- package/dist/src/generate-verified.test.js +0 -925
- package/dist/src/generate.d.ts +0 -46
- package/dist/src/generate.js +0 -117
- package/dist/src/record.d.ts +0 -96
- package/dist/src/record.js +0 -657
- package/dist/src/record.test.d.ts +0 -1
- package/dist/src/record.test.js +0 -293
- package/dist/src/skill-generate.d.ts +0 -30
- package/dist/src/skill-generate.js +0 -75
- package/dist/src/skill-generate.test.d.ts +0 -1
- package/dist/src/skill-generate.test.js +0 -173
- package/dist/src/synthesize.d.ts +0 -97
- package/dist/src/synthesize.js +0 -208
- /package/dist/src/{generate-verified.test.d.ts → download/article-download.test.d.ts} +0 -0
package/dist/src/browser/page.js
CHANGED
|
@@ -27,9 +27,11 @@ function isUnsupportedNetworkCaptureError(err) {
|
|
|
27
27
|
*/
|
|
28
28
|
export class Page extends BasePage {
|
|
29
29
|
workspace;
|
|
30
|
-
|
|
30
|
+
_idleTimeout;
|
|
31
|
+
constructor(workspace = 'default', idleTimeout) {
|
|
31
32
|
super();
|
|
32
33
|
this.workspace = workspace;
|
|
34
|
+
this._idleTimeout = idleTimeout;
|
|
33
35
|
}
|
|
34
36
|
/** Active page identity (targetId), set after navigate and used in all subsequent commands */
|
|
35
37
|
_page;
|
|
@@ -37,13 +39,14 @@ export class Page extends BasePage {
|
|
|
37
39
|
_networkCaptureWarned = false;
|
|
38
40
|
/** Helper: spread workspace into command params */
|
|
39
41
|
_wsOpt() {
|
|
40
|
-
return { workspace: this.workspace };
|
|
42
|
+
return { workspace: this.workspace, ...(this._idleTimeout != null && { idleTimeout: this._idleTimeout }) };
|
|
41
43
|
}
|
|
42
44
|
/** Helper: spread workspace + page identity into command params */
|
|
43
45
|
_cmdOpts() {
|
|
44
46
|
return {
|
|
45
47
|
workspace: this.workspace,
|
|
46
48
|
...(this._page !== undefined && { page: this._page }),
|
|
49
|
+
...(this._idleTimeout != null && { idleTimeout: this._idleTimeout }),
|
|
47
50
|
};
|
|
48
51
|
}
|
|
49
52
|
async goto(url, options) {
|
|
@@ -102,9 +105,10 @@ export class Page extends BasePage {
|
|
|
102
105
|
getActivePage() {
|
|
103
106
|
return this._page;
|
|
104
107
|
}
|
|
105
|
-
/**
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
/** Bind this Page instance to a specific page identity (targetId). */
|
|
109
|
+
setActivePage(page) {
|
|
110
|
+
this._page = page;
|
|
111
|
+
this._lastUrl = null;
|
|
108
112
|
}
|
|
109
113
|
_markUnsupportedNetworkCapture() {
|
|
110
114
|
this._networkCaptureUnsupported = true;
|
|
@@ -150,10 +154,39 @@ export class Page extends BasePage {
|
|
|
150
154
|
const result = await sendCommand('tabs', { op: 'list', ...this._wsOpt() });
|
|
151
155
|
return Array.isArray(result) ? result : [];
|
|
152
156
|
}
|
|
153
|
-
async
|
|
154
|
-
const result = await sendCommandFull('tabs', {
|
|
157
|
+
async newTab(url) {
|
|
158
|
+
const result = await sendCommandFull('tabs', {
|
|
159
|
+
op: 'new',
|
|
160
|
+
...(url !== undefined && { url }),
|
|
161
|
+
...this._wsOpt(),
|
|
162
|
+
});
|
|
163
|
+
this._lastUrl = null;
|
|
164
|
+
return result.page;
|
|
165
|
+
}
|
|
166
|
+
async closeTab(target) {
|
|
167
|
+
const params = { op: 'close', ...this._wsOpt() };
|
|
168
|
+
if (typeof target === 'number')
|
|
169
|
+
params.index = target;
|
|
170
|
+
else if (typeof target === 'string')
|
|
171
|
+
params.page = target;
|
|
172
|
+
else if (this._page !== undefined)
|
|
173
|
+
params.page = this._page;
|
|
174
|
+
const result = await sendCommand('tabs', params);
|
|
175
|
+
const closedPage = typeof result?.closed === 'string' ? result.closed : undefined;
|
|
176
|
+
if ((closedPage && closedPage === this._page) || (!closedPage && (target === undefined || target === this._page))) {
|
|
177
|
+
this._page = undefined;
|
|
178
|
+
this._lastUrl = null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async selectTab(target) {
|
|
182
|
+
const result = await sendCommandFull('tabs', {
|
|
183
|
+
op: 'select',
|
|
184
|
+
...(typeof target === 'number' ? { index: target } : { page: target }),
|
|
185
|
+
...this._wsOpt(),
|
|
186
|
+
});
|
|
155
187
|
if (result.page)
|
|
156
188
|
this._page = result.page;
|
|
189
|
+
this._lastUrl = null;
|
|
157
190
|
}
|
|
158
191
|
/**
|
|
159
192
|
* Capture a screenshot via CDP Page.captureScreenshot.
|
|
@@ -227,6 +260,14 @@ export class Page extends BasePage {
|
|
|
227
260
|
throw new Error('insertText returned no inserted flag — command may not be supported by the extension');
|
|
228
261
|
}
|
|
229
262
|
}
|
|
263
|
+
async frames() {
|
|
264
|
+
const result = await sendCommand('frames', { ...this._cmdOpts() });
|
|
265
|
+
return Array.isArray(result) ? result : [];
|
|
266
|
+
}
|
|
267
|
+
async evaluateInFrame(js, frameIndex) {
|
|
268
|
+
const code = wrapForEval(js);
|
|
269
|
+
return sendCommand('exec', { code, frameIndex, ...this._cmdOpts() });
|
|
270
|
+
}
|
|
230
271
|
async cdp(method, params = {}) {
|
|
231
272
|
return sendCommand('cdp', {
|
|
232
273
|
cdpMethod: method,
|
|
@@ -102,3 +102,100 @@ describe('Page network capture compatibility', () => {
|
|
|
102
102
|
expect(warnMock).toHaveBeenCalledTimes(1);
|
|
103
103
|
});
|
|
104
104
|
});
|
|
105
|
+
describe('Page active target tracking', () => {
|
|
106
|
+
beforeEach(() => {
|
|
107
|
+
sendCommandMock.mockReset();
|
|
108
|
+
sendCommandFullMock.mockReset();
|
|
109
|
+
warnMock.mockReset();
|
|
110
|
+
});
|
|
111
|
+
it('tracks only one active page identity at a time', async () => {
|
|
112
|
+
sendCommandFullMock
|
|
113
|
+
.mockResolvedValueOnce({ data: { url: 'https://first.example' }, page: 'page-1' })
|
|
114
|
+
.mockResolvedValueOnce({ data: { selected: true }, page: 'page-2' });
|
|
115
|
+
sendCommandMock.mockResolvedValue('ok');
|
|
116
|
+
const page = new Page('browser:default');
|
|
117
|
+
await page.goto('https://first.example', { waitUntil: 'none' });
|
|
118
|
+
expect(page.getActivePage()).toBe('page-1');
|
|
119
|
+
await page.selectTab(1);
|
|
120
|
+
expect(page.getActivePage()).toBe('page-2');
|
|
121
|
+
await page.evaluate('1 + 1');
|
|
122
|
+
expect(sendCommandMock).toHaveBeenLastCalledWith('exec', expect.objectContaining({
|
|
123
|
+
workspace: 'browser:default',
|
|
124
|
+
page: 'page-2',
|
|
125
|
+
}));
|
|
126
|
+
});
|
|
127
|
+
it('allows the caller to bind a specific active page identity explicitly', async () => {
|
|
128
|
+
sendCommandMock.mockResolvedValue('bound');
|
|
129
|
+
const page = new Page('browser:default');
|
|
130
|
+
page.setActivePage?.('page-explicit');
|
|
131
|
+
await page.evaluate('1 + 1');
|
|
132
|
+
expect(sendCommandMock).toHaveBeenCalledWith('exec', expect.objectContaining({
|
|
133
|
+
workspace: 'browser:default',
|
|
134
|
+
page: 'page-explicit',
|
|
135
|
+
}));
|
|
136
|
+
});
|
|
137
|
+
it('creates a new tab without changing the current active page binding', async () => {
|
|
138
|
+
sendCommandFullMock
|
|
139
|
+
.mockResolvedValueOnce({ data: { url: 'https://first.example' }, page: 'page-1' })
|
|
140
|
+
.mockResolvedValueOnce({
|
|
141
|
+
data: { url: 'https://second.example' },
|
|
142
|
+
page: 'page-2',
|
|
143
|
+
});
|
|
144
|
+
sendCommandMock.mockResolvedValue('ok');
|
|
145
|
+
const page = new Page('browser:default');
|
|
146
|
+
await page.goto('https://first.example', { waitUntil: 'none' });
|
|
147
|
+
const created = await page.newTab?.('https://second.example');
|
|
148
|
+
expect(created).toBe('page-2');
|
|
149
|
+
expect(page.getActivePage()).toBe('page-1');
|
|
150
|
+
await page.evaluate('1 + 1');
|
|
151
|
+
expect(sendCommandMock).toHaveBeenLastCalledWith('exec', expect.objectContaining({
|
|
152
|
+
workspace: 'browser:default',
|
|
153
|
+
page: 'page-1',
|
|
154
|
+
}));
|
|
155
|
+
});
|
|
156
|
+
it('allows the caller to adopt a new tab explicitly after creation', async () => {
|
|
157
|
+
sendCommandFullMock.mockResolvedValueOnce({
|
|
158
|
+
data: { url: 'https://second.example' },
|
|
159
|
+
page: 'page-2',
|
|
160
|
+
});
|
|
161
|
+
const page = new Page('browser:default');
|
|
162
|
+
const created = await page.newTab?.('https://second.example');
|
|
163
|
+
expect(created).toBe('page-2');
|
|
164
|
+
expect(page.getActivePage()).toBeUndefined();
|
|
165
|
+
page.setActivePage?.(created);
|
|
166
|
+
expect(page.getActivePage()).toBe('page-2');
|
|
167
|
+
expect(sendCommandFullMock).toHaveBeenCalledWith('tabs', expect.objectContaining({
|
|
168
|
+
op: 'new',
|
|
169
|
+
url: 'https://second.example',
|
|
170
|
+
workspace: 'browser:default',
|
|
171
|
+
}));
|
|
172
|
+
});
|
|
173
|
+
it('closes a tab by explicit page identity', async () => {
|
|
174
|
+
sendCommandMock.mockResolvedValueOnce({ closed: 'page-2' });
|
|
175
|
+
const page = new Page('browser:default');
|
|
176
|
+
await page.closeTab?.('page-2');
|
|
177
|
+
expect(sendCommandMock).toHaveBeenCalledWith('tabs', expect.objectContaining({
|
|
178
|
+
op: 'close',
|
|
179
|
+
workspace: 'browser:default',
|
|
180
|
+
page: 'page-2',
|
|
181
|
+
}));
|
|
182
|
+
});
|
|
183
|
+
it('clears the active page binding when closing the selected tab by numeric index', async () => {
|
|
184
|
+
sendCommandFullMock.mockResolvedValueOnce({ data: { selected: true }, page: 'page-2' });
|
|
185
|
+
sendCommandMock
|
|
186
|
+
.mockResolvedValueOnce({ closed: 'page-2' })
|
|
187
|
+
.mockResolvedValueOnce('ok');
|
|
188
|
+
const page = new Page('browser:default');
|
|
189
|
+
await page.selectTab(1);
|
|
190
|
+
expect(page.getActivePage()).toBe('page-2');
|
|
191
|
+
await page.closeTab?.(1);
|
|
192
|
+
expect(page.getActivePage()).toBeUndefined();
|
|
193
|
+
await page.evaluate('1 + 1');
|
|
194
|
+
const evalCall = sendCommandMock.mock.calls.at(-1);
|
|
195
|
+
expect(evalCall?.[0]).toBe('exec');
|
|
196
|
+
expect(evalCall?.[1]).toEqual(expect.objectContaining({
|
|
197
|
+
workspace: 'browser:default',
|
|
198
|
+
}));
|
|
199
|
+
expect(evalCall?.[1]).not.toHaveProperty('page');
|
|
200
|
+
});
|
|
201
|
+
});
|