@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.
Files changed (126) hide show
  1. package/README.md +71 -49
  2. package/README.zh-CN.md +73 -60
  3. package/cli-manifest.json +3261 -1758
  4. package/clis/antigravity/serve.js +71 -25
  5. package/clis/baidu-scholar/search.js +87 -0
  6. package/clis/baidu-scholar/search.test.js +23 -0
  7. package/clis/deepseek/ask.js +74 -0
  8. package/clis/deepseek/history.js +25 -0
  9. package/clis/deepseek/new.js +20 -0
  10. package/clis/deepseek/read.js +22 -0
  11. package/clis/deepseek/status.js +24 -0
  12. package/clis/deepseek/utils.js +208 -0
  13. package/clis/eastmoney/_secid.js +78 -0
  14. package/clis/eastmoney/announcement.js +52 -0
  15. package/clis/eastmoney/convertible.js +73 -0
  16. package/clis/eastmoney/etf.js +65 -0
  17. package/clis/eastmoney/holders.js +78 -0
  18. package/clis/eastmoney/index-board.js +96 -0
  19. package/clis/eastmoney/kline.js +87 -0
  20. package/clis/eastmoney/kuaixun.js +54 -0
  21. package/clis/eastmoney/longhu.js +67 -0
  22. package/clis/eastmoney/money-flow.js +78 -0
  23. package/clis/eastmoney/northbound.js +57 -0
  24. package/clis/eastmoney/quote.js +107 -0
  25. package/clis/eastmoney/rank.js +94 -0
  26. package/clis/eastmoney/sectors.js +76 -0
  27. package/clis/google-scholar/search.js +58 -0
  28. package/clis/google-scholar/search.test.js +23 -0
  29. package/clis/gov-law/commands.test.js +39 -0
  30. package/clis/gov-law/recent.js +22 -0
  31. package/clis/gov-law/search.js +41 -0
  32. package/clis/gov-law/shared.js +51 -0
  33. package/clis/gov-policy/commands.test.js +27 -0
  34. package/clis/gov-policy/recent.js +47 -0
  35. package/clis/gov-policy/search.js +48 -0
  36. package/clis/nowcoder/companies.js +23 -0
  37. package/clis/nowcoder/creators.js +27 -0
  38. package/clis/nowcoder/detail.js +61 -0
  39. package/clis/nowcoder/experience.js +36 -0
  40. package/clis/nowcoder/hot.js +24 -0
  41. package/clis/nowcoder/jobs.js +21 -0
  42. package/clis/nowcoder/notifications.js +29 -0
  43. package/clis/nowcoder/papers.js +40 -0
  44. package/clis/nowcoder/practice.js +37 -0
  45. package/clis/nowcoder/recommend.js +30 -0
  46. package/clis/nowcoder/referral.js +39 -0
  47. package/clis/nowcoder/salary.js +40 -0
  48. package/clis/nowcoder/search.js +49 -0
  49. package/clis/nowcoder/suggest.js +33 -0
  50. package/clis/nowcoder/topics.js +27 -0
  51. package/clis/nowcoder/trending.js +25 -0
  52. package/clis/twitter/list-add.js +337 -0
  53. package/clis/twitter/list-add.test.js +15 -0
  54. package/clis/twitter/list-remove.js +297 -0
  55. package/clis/twitter/list-remove.test.js +14 -0
  56. package/clis/twitter/list-tweets.js +185 -0
  57. package/clis/twitter/list-tweets.test.js +108 -0
  58. package/clis/twitter/lists.js +134 -47
  59. package/clis/twitter/lists.test.js +105 -38
  60. package/clis/wanfang/search.js +66 -0
  61. package/clis/wanfang/search.test.js +23 -0
  62. package/clis/web/read.js +1 -1
  63. package/clis/weixin/download.js +3 -2
  64. package/clis/xiaohongshu/publish.js +149 -28
  65. package/clis/xiaohongshu/publish.test.js +319 -6
  66. package/clis/xiaoyuzhou/download.js +8 -4
  67. package/clis/xiaoyuzhou/download.test.js +23 -13
  68. package/clis/xiaoyuzhou/episode.js +9 -4
  69. package/clis/xiaoyuzhou/podcast-episodes.js +15 -11
  70. package/clis/xiaoyuzhou/podcast.js +9 -4
  71. package/clis/xiaoyuzhou/utils.js +0 -40
  72. package/clis/xiaoyuzhou/utils.test.js +15 -75
  73. package/clis/zsxq/dynamics.js +1 -1
  74. package/clis/zsxq/utils.js +6 -3
  75. package/clis/zsxq/utils.test.js +31 -0
  76. package/dist/src/browser/base-page.d.ts +1 -1
  77. package/dist/src/browser/bridge.d.ts +1 -0
  78. package/dist/src/browser/bridge.js +1 -1
  79. package/dist/src/browser/cdp.js +1 -1
  80. package/dist/src/browser/daemon-client.d.ts +6 -4
  81. package/dist/src/browser/daemon-client.js +6 -1
  82. package/dist/src/browser/daemon-client.test.js +40 -1
  83. package/dist/src/browser/dom-snapshot.js +7 -2
  84. package/dist/src/browser/page.d.ts +14 -4
  85. package/dist/src/browser/page.js +48 -7
  86. package/dist/src/browser/page.test.js +97 -0
  87. package/dist/src/cli.js +227 -150
  88. package/dist/src/cli.test.js +167 -90
  89. package/dist/src/commanderAdapter.d.ts +0 -1
  90. package/dist/src/commanderAdapter.js +2 -16
  91. package/dist/src/commanderAdapter.test.js +1 -1
  92. package/dist/src/completion-shared.js +2 -5
  93. package/dist/src/daemon.js +8 -0
  94. package/dist/src/download/article-download.d.ts +1 -0
  95. package/dist/src/download/article-download.js +3 -0
  96. package/dist/src/download/article-download.test.js +39 -0
  97. package/dist/src/plugin.d.ts +1 -8
  98. package/dist/src/plugin.js +1 -27
  99. package/dist/src/plugin.test.js +1 -59
  100. package/dist/src/registry.d.ts +1 -0
  101. package/dist/src/registry.js +3 -2
  102. package/dist/src/registry.test.js +22 -0
  103. package/dist/src/types.d.ts +14 -5
  104. package/package.json +1 -1
  105. package/clis/twitter/lists-parser.js +0 -77
  106. package/clis/twitter/lists.d.ts +0 -5
  107. package/dist/src/cascade.d.ts +0 -46
  108. package/dist/src/cascade.js +0 -135
  109. package/dist/src/explore.d.ts +0 -99
  110. package/dist/src/explore.js +0 -402
  111. package/dist/src/generate-verified.d.ts +0 -105
  112. package/dist/src/generate-verified.js +0 -696
  113. package/dist/src/generate-verified.test.js +0 -925
  114. package/dist/src/generate.d.ts +0 -46
  115. package/dist/src/generate.js +0 -117
  116. package/dist/src/record.d.ts +0 -96
  117. package/dist/src/record.js +0 -657
  118. package/dist/src/record.test.d.ts +0 -1
  119. package/dist/src/record.test.js +0 -293
  120. package/dist/src/skill-generate.d.ts +0 -30
  121. package/dist/src/skill-generate.js +0 -75
  122. package/dist/src/skill-generate.test.d.ts +0 -1
  123. package/dist/src/skill-generate.test.js +0 -173
  124. package/dist/src/synthesize.d.ts +0 -97
  125. package/dist/src/synthesize.js +0 -208
  126. /package/dist/src/{generate-verified.test.d.ts → download/article-download.test.d.ts} +0 -0
@@ -27,9 +27,11 @@ function isUnsupportedNetworkCaptureError(err) {
27
27
  */
28
28
  export class Page extends BasePage {
29
29
  workspace;
30
- constructor(workspace = 'default') {
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
- /** @deprecated Use getActivePage() instead */
106
- getActiveTabId() {
107
- return undefined;
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 selectTab(index) {
154
- const result = await sendCommandFull('tabs', { op: 'select', index, ...this._wsOpt() });
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
+ });