@jackwener/opencli 1.7.14 → 1.7.16
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 +9 -6
- package/README.zh-CN.md +9 -6
- package/cli-manifest.json +374 -74
- package/clis/bilibili/subtitle.js +1 -1
- package/clis/chatgpt/ask.js +2 -1
- package/clis/chatgpt/detail.js +6 -1
- package/clis/chatgpt/read.js +2 -1
- package/clis/chatgpt/send.js +2 -1
- package/clis/chatgpt/utils.js +54 -12
- package/clis/chatgpt/utils.test.js +36 -1
- package/clis/claude/ask.js +22 -7
- package/clis/claude/detail.js +9 -2
- package/clis/claude/new.js +8 -2
- package/clis/claude/read.js +2 -1
- package/clis/claude/send.js +8 -3
- package/clis/claude/utils.js +27 -4
- package/clis/deepseek/ask.js +21 -8
- package/clis/deepseek/detail.js +9 -1
- package/clis/deepseek/new.js +13 -2
- package/clis/deepseek/read.js +2 -1
- package/clis/deepseek/utils.js +8 -1
- package/clis/dianping/cityResolver.js +185 -0
- package/clis/dianping/dianping.test.js +154 -0
- package/clis/dianping/search.js +6 -3
- package/clis/douyin/_shared/browser-fetch.js +14 -2
- package/clis/douyin/_shared/browser-fetch.test.js +13 -0
- package/clis/douyin/stats.js +1 -1
- package/clis/douyin/update.js +1 -1
- package/clis/jike/search.js +1 -1
- package/clis/linkedin/search.js +8 -11
- package/clis/maimai/search-talents.js +10 -6
- package/clis/openreview/author.js +58 -0
- package/clis/openreview/openreview.test.js +83 -1
- package/clis/openreview/utils.js +14 -0
- package/clis/reddit/comment.js +1 -0
- package/clis/reddit/frontpage.js +1 -0
- package/clis/reddit/popular.js +1 -0
- package/clis/reddit/read.js +2 -0
- package/clis/reddit/read.test.js +4 -0
- package/clis/reddit/save.js +1 -0
- package/clis/reddit/saved.js +1 -0
- package/clis/reddit/search.js +2 -1
- package/clis/reddit/subreddit.js +2 -1
- package/clis/reddit/subscribe.js +1 -0
- package/clis/reddit/upvote.js +1 -0
- package/clis/reddit/upvoted.js +1 -0
- package/clis/reddit/user-comments.js +2 -1
- package/clis/reddit/user-posts.js +2 -1
- package/clis/reddit/user.js +2 -1
- package/clis/twitter/article.js +9 -5
- package/clis/twitter/bookmark-folder.js +187 -0
- package/clis/twitter/bookmark-folder.test.js +337 -0
- package/clis/twitter/bookmark-folders.js +115 -0
- package/clis/twitter/bookmark-folders.test.js +152 -0
- package/clis/twitter/bookmark.js +15 -6
- package/clis/twitter/bookmark.test.js +74 -0
- package/clis/twitter/bookmarks.js +10 -10
- package/clis/twitter/delete.js +11 -35
- package/clis/twitter/delete.test.js +21 -9
- package/clis/twitter/download.js +6 -5
- package/clis/twitter/followers.js +10 -3
- package/clis/twitter/following.js +14 -11
- package/clis/twitter/following.test.js +2 -1
- package/clis/twitter/hide-reply.js +24 -5
- package/clis/twitter/hide-reply.test.js +76 -0
- package/clis/twitter/like.js +21 -11
- package/clis/twitter/like.test.js +73 -0
- package/clis/twitter/likes.js +11 -11
- package/clis/twitter/list-add.js +8 -7
- package/clis/twitter/list-add.test.js +23 -1
- package/clis/twitter/list-remove.js +8 -7
- package/clis/twitter/list-remove.test.js +23 -1
- package/clis/twitter/list-tweets.js +9 -9
- package/clis/twitter/lists.js +6 -8
- package/clis/twitter/notifications.js +3 -2
- package/clis/twitter/profile.js +11 -7
- package/clis/twitter/quote.js +60 -32
- package/clis/twitter/quote.test.js +96 -8
- package/clis/twitter/reply.js +24 -178
- package/clis/twitter/reply.test.js +29 -11
- package/clis/twitter/retweet.js +9 -14
- package/clis/twitter/retweet.test.js +5 -1
- package/clis/twitter/search.js +176 -23
- package/clis/twitter/search.test.js +266 -1
- package/clis/twitter/shared.js +43 -0
- package/clis/twitter/shared.test.js +107 -1
- package/clis/twitter/thread.js +11 -11
- package/clis/twitter/timeline.js +13 -13
- package/clis/twitter/trending.js +4 -4
- package/clis/twitter/tweets.js +8 -9
- package/clis/twitter/unbookmark.js +13 -6
- package/clis/twitter/unbookmark.test.js +73 -0
- package/clis/twitter/unlike.js +6 -13
- package/clis/twitter/unlike.test.js +5 -2
- package/clis/twitter/unretweet.js +9 -14
- package/clis/twitter/unretweet.test.js +5 -1
- package/clis/twitter/utils.js +286 -0
- package/clis/twitter/utils.test.js +169 -0
- package/clis/youtube/like.js +6 -2
- package/clis/youtube/subscribe.js +6 -2
- package/clis/youtube/unlike.js +6 -2
- package/clis/youtube/unsubscribe.js +6 -2
- package/clis/youtube/utils.js +19 -13
- package/clis/youtube/utils.test.js +17 -1
- package/dist/src/browser/ax-snapshot.d.ts +37 -0
- package/dist/src/browser/ax-snapshot.js +217 -0
- package/dist/src/browser/ax-snapshot.test.d.ts +1 -0
- package/dist/src/browser/ax-snapshot.test.js +91 -0
- package/dist/src/browser/base-page.d.ts +51 -0
- package/dist/src/browser/base-page.js +545 -2
- package/dist/src/browser/base-page.test.js +520 -4
- package/dist/src/browser/bridge.d.ts +1 -0
- package/dist/src/browser/bridge.js +1 -1
- package/dist/src/browser/cdp-click-fixture.test.d.ts +1 -0
- package/dist/src/browser/cdp-click-fixture.test.js +87 -0
- package/dist/src/browser/cdp.d.ts +1 -0
- package/dist/src/browser/cdp.js +5 -0
- package/dist/src/browser/cdp.test.js +1 -0
- package/dist/src/browser/daemon-client.d.ts +5 -3
- package/dist/src/browser/daemon-client.js +6 -3
- package/dist/src/browser/daemon-client.test.js +10 -0
- package/dist/src/browser/find.d.ts +9 -1
- package/dist/src/browser/find.js +219 -0
- package/dist/src/browser/find.test.js +61 -1
- package/dist/src/browser/page.d.ts +4 -2
- package/dist/src/browser/page.js +18 -1
- package/dist/src/browser/page.test.js +28 -0
- package/dist/src/browser/target-errors.d.ts +3 -1
- package/dist/src/browser/target-errors.js +2 -0
- package/dist/src/browser/target-resolver.d.ts +14 -0
- package/dist/src/browser/target-resolver.js +28 -0
- package/dist/src/browser/visual-refs.d.ts +11 -0
- package/dist/src/browser/visual-refs.js +108 -0
- package/dist/src/build-manifest.d.ts +23 -0
- package/dist/src/build-manifest.js +34 -0
- package/dist/src/build-manifest.test.js +108 -1
- package/dist/src/cli.js +630 -60
- package/dist/src/cli.test.js +731 -1
- package/dist/src/commanderAdapter.js +7 -0
- package/dist/src/doctor.js +2 -2
- package/dist/src/doctor.test.js +4 -4
- package/dist/src/execution.d.ts +2 -0
- package/dist/src/execution.js +31 -6
- package/dist/src/execution.test.js +43 -16
- package/dist/src/external-clis.yaml +24 -0
- package/dist/src/help.d.ts +33 -0
- package/dist/src/help.js +174 -0
- package/dist/src/main.js +4 -14
- package/dist/src/runtime.d.ts +3 -0
- package/dist/src/runtime.js +1 -0
- package/dist/src/types.d.ts +83 -1
- package/package.json +1 -1
- package/scripts/typed-error-lint-baseline.json +18 -18
|
@@ -48,6 +48,11 @@ export function registerCommandToProgram(siteCmd, cmd) {
|
|
|
48
48
|
.option('-f, --format <fmt>', 'Output format: table, plain, json, yaml, md, csv', 'table')
|
|
49
49
|
.option('--trace <mode>', 'Trace capture: off, on, retain-on-failure', 'off')
|
|
50
50
|
.option('-v, --verbose', 'Debug output', false);
|
|
51
|
+
if (cmd.browser) {
|
|
52
|
+
subCmd
|
|
53
|
+
.option('--window <mode>', 'Browser window mode: foreground or background')
|
|
54
|
+
.option('--keep-tab <bool>', 'Keep the browser tab lease after the command finishes');
|
|
55
|
+
}
|
|
51
56
|
const originalHelpInformation = subCmd.helpInformation.bind(subCmd);
|
|
52
57
|
subCmd.helpInformation = ((contextOptions) => {
|
|
53
58
|
const format = getRequestedHelpFormat();
|
|
@@ -102,6 +107,8 @@ export function registerCommandToProgram(siteCmd, cmd) {
|
|
|
102
107
|
prepared: true,
|
|
103
108
|
...(typeof globals.profile === 'string' && globals.profile.trim() ? { profile: globals.profile.trim() } : {}),
|
|
104
109
|
...(typeof optionsRecord.trace === 'string' && optionsRecord.trace !== 'off' ? { trace: optionsRecord.trace } : {}),
|
|
110
|
+
...(cmd.browser && typeof optionsRecord.window === 'string' ? { windowMode: optionsRecord.window } : {}),
|
|
111
|
+
...(cmd.browser && typeof optionsRecord.keepTab === 'string' ? { keepTab: optionsRecord.keepTab } : {}),
|
|
105
112
|
});
|
|
106
113
|
if (result === null || result === undefined) {
|
|
107
114
|
return;
|
package/dist/src/doctor.js
CHANGED
|
@@ -271,8 +271,8 @@ export function renderBrowserDoctorReport(report) {
|
|
|
271
271
|
? `tab ${session.preferredTabId}`
|
|
272
272
|
: `window ${session.windowId ?? 'unknown'}`;
|
|
273
273
|
const mode = session.ownership ?? (session.owned === false ? 'borrowed' : 'owned');
|
|
274
|
-
const
|
|
275
|
-
lines.push(styleText('dim', ` • ${session.workspace ?? 'default'} → ${target}, mode=${mode}${
|
|
274
|
+
const windowRole = session.windowRole ? `, window=${session.windowRole}` : '';
|
|
275
|
+
lines.push(styleText('dim', ` • ${session.workspace ?? 'default'} → ${target}, mode=${mode}${windowRole}, tabs=${session.tabCount ?? 0}, idle=${idle}`));
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
278
|
}
|
package/dist/src/doctor.test.js
CHANGED
|
@@ -116,13 +116,13 @@ describe('doctor report rendering', () => {
|
|
|
116
116
|
windowId: 2,
|
|
117
117
|
preferredTabId: 42,
|
|
118
118
|
ownership: 'borrowed',
|
|
119
|
-
|
|
119
|
+
windowRole: 'borrowed-user',
|
|
120
120
|
tabCount: 1,
|
|
121
121
|
idleMsRemaining: null,
|
|
122
122
|
},
|
|
123
123
|
],
|
|
124
124
|
}));
|
|
125
|
-
expect(text).toContain('bound:default → tab 42, mode=borrowed,
|
|
125
|
+
expect(text).toContain('bound:default → tab 42, mode=borrowed, window=borrowed-user, tabs=1, idle=none');
|
|
126
126
|
});
|
|
127
127
|
it('renders connected profiles and groups sessions by profile', () => {
|
|
128
128
|
const text = strip(renderBrowserDoctorReport({
|
|
@@ -140,7 +140,7 @@ describe('doctor report rendering', () => {
|
|
|
140
140
|
windowId: 2,
|
|
141
141
|
preferredTabId: 42,
|
|
142
142
|
ownership: 'borrowed',
|
|
143
|
-
|
|
143
|
+
windowRole: 'borrowed-user',
|
|
144
144
|
tabCount: 1,
|
|
145
145
|
idleMsRemaining: null,
|
|
146
146
|
},
|
|
@@ -150,7 +150,7 @@ describe('doctor report rendering', () => {
|
|
|
150
150
|
windowId: 1,
|
|
151
151
|
preferredTabId: 10,
|
|
152
152
|
ownership: 'owned',
|
|
153
|
-
|
|
153
|
+
windowRole: 'automation',
|
|
154
154
|
tabCount: 1,
|
|
155
155
|
idleMsRemaining: 1000,
|
|
156
156
|
},
|
package/dist/src/execution.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export declare function executeCommand(cmd: CliCommand, rawKwargs: CommandArgs,
|
|
|
16
16
|
prepared?: boolean;
|
|
17
17
|
profile?: string;
|
|
18
18
|
trace?: string;
|
|
19
|
+
keepTab?: string;
|
|
20
|
+
windowMode?: string;
|
|
19
21
|
onTraceExport?: (trace: ObservationExportResult) => void;
|
|
20
22
|
}): Promise<unknown>;
|
|
21
23
|
export declare function prepareCommandArgs(cmd: CliCommand, rawKwargs: CommandArgs): CommandArgs;
|
package/dist/src/execution.js
CHANGED
|
@@ -215,6 +215,8 @@ export async function executeCommand(cmd, rawKwargs, debug = false, opts = {}) {
|
|
|
215
215
|
const browserReuse = resolveBrowserSessionReuse(cmd);
|
|
216
216
|
const workspace = resolveBrowserWorkspace(cmd, browserReuse);
|
|
217
217
|
const idleTimeout = browserReuse === 'site' ? INTERACTIVE_BROWSER_IDLE_TIMEOUT_SECONDS : undefined;
|
|
218
|
+
const keepTab = resolveKeepTab(browserReuse, opts.keepTab);
|
|
219
|
+
const windowMode = resolveBrowserWindowMode('background', opts.windowMode);
|
|
218
220
|
result = await browserSession(BrowserFactory, async (page) => {
|
|
219
221
|
const observation = traceMode === 'off'
|
|
220
222
|
? null
|
|
@@ -281,9 +283,6 @@ export async function executeCommand(cmd, rawKwargs, debug = false, opts = {}) {
|
|
|
281
283
|
throw wrapped;
|
|
282
284
|
}
|
|
283
285
|
}
|
|
284
|
-
// --live / OPENCLI_LIVE=1 keeps the current automation tab lease after
|
|
285
|
-
// the command finishes, so agents (or humans) can inspect the page state.
|
|
286
|
-
const keepOpen = browserReuse !== 'none' || process.env.OPENCLI_LIVE === '1' || process.env.OPENCLI_LIVE === 'true';
|
|
287
286
|
try {
|
|
288
287
|
const browserTimeout = userTimeoutSec !== null
|
|
289
288
|
? userTimeoutSec + RUNTIME_TIMEOUT_PADDING_SECONDS
|
|
@@ -304,7 +303,7 @@ export async function executeCommand(cmd, rawKwargs, debug = false, opts = {}) {
|
|
|
304
303
|
// Adapter commands are one-shot — release the current tab lease immediately
|
|
305
304
|
// instead of waiting for the 30s idle timeout. The automation container
|
|
306
305
|
// window stays open for reuse.
|
|
307
|
-
if (!
|
|
306
|
+
if (!keepTab)
|
|
308
307
|
await page.closeWindow?.().catch(() => { });
|
|
309
308
|
return result;
|
|
310
309
|
}
|
|
@@ -329,11 +328,11 @@ export async function executeCommand(cmd, rawKwargs, debug = false, opts = {}) {
|
|
|
329
328
|
// Release the tab lease on failure too — without this, the lease lingers
|
|
330
329
|
// until the extension's idle timer fires (unreliable on Windows where
|
|
331
330
|
// MV3 service workers may be suspended before setTimeout triggers).
|
|
332
|
-
if (!
|
|
331
|
+
if (!keepTab)
|
|
333
332
|
await page.closeWindow?.().catch(() => { });
|
|
334
333
|
throw err;
|
|
335
334
|
}
|
|
336
|
-
}, { workspace, cdpEndpoint, contextId, idleTimeout });
|
|
335
|
+
}, { workspace, cdpEndpoint, contextId, idleTimeout, windowMode });
|
|
337
336
|
}
|
|
338
337
|
else {
|
|
339
338
|
// Non-browser commands: enforce a timeout only when the command exposes
|
|
@@ -459,6 +458,32 @@ function resolveBrowserWorkspace(cmd, reuse) {
|
|
|
459
458
|
return `site:${cmd.site}`;
|
|
460
459
|
return `site:${cmd.site}:${crypto.randomUUID()}`;
|
|
461
460
|
}
|
|
461
|
+
function normalizeBooleanOption(name, raw) {
|
|
462
|
+
if (raw === undefined || raw === '')
|
|
463
|
+
return null;
|
|
464
|
+
if (raw === 'true')
|
|
465
|
+
return true;
|
|
466
|
+
if (raw === 'false')
|
|
467
|
+
return false;
|
|
468
|
+
throw new ArgumentError(`${name} must be one of: true, false. Received: "${String(raw)}"`);
|
|
469
|
+
}
|
|
470
|
+
function resolveKeepTab(reuse, rawOption) {
|
|
471
|
+
return normalizeBooleanOption('--keep-tab', rawOption)
|
|
472
|
+
?? normalizeBooleanOption('OPENCLI_KEEP_TAB', process.env.OPENCLI_KEEP_TAB)
|
|
473
|
+
?? reuse !== 'none';
|
|
474
|
+
}
|
|
475
|
+
function normalizeWindowMode(name, raw) {
|
|
476
|
+
if (raw === undefined || raw === '')
|
|
477
|
+
return null;
|
|
478
|
+
if (raw === 'foreground' || raw === 'background')
|
|
479
|
+
return raw;
|
|
480
|
+
throw new ArgumentError(`${name} must be one of: foreground, background. Received: "${String(raw)}"`);
|
|
481
|
+
}
|
|
482
|
+
function resolveBrowserWindowMode(defaultMode = 'background', rawOption) {
|
|
483
|
+
return normalizeWindowMode('--window', rawOption)
|
|
484
|
+
?? normalizeWindowMode('OPENCLI_WINDOW', process.env.OPENCLI_WINDOW)
|
|
485
|
+
?? defaultMode;
|
|
486
|
+
}
|
|
462
487
|
/**
|
|
463
488
|
* Resolve the user-controllable `--timeout` arg, in seconds.
|
|
464
489
|
*
|
|
@@ -157,8 +157,8 @@ describe('executeCommand — non-browser timeout', () => {
|
|
|
157
157
|
await executeCommand(cmd, {});
|
|
158
158
|
await executeCommand(cmd, {});
|
|
159
159
|
expect(sessionOpts).toHaveLength(2);
|
|
160
|
-
expect(sessionOpts[0]).toMatchObject({ workspace: 'site:test-execution', idleTimeout: 600 });
|
|
161
|
-
expect(sessionOpts[1]).toMatchObject({ workspace: 'site:test-execution', idleTimeout: 600 });
|
|
160
|
+
expect(sessionOpts[0]).toMatchObject({ workspace: 'site:test-execution', idleTimeout: 600, windowMode: 'background' });
|
|
161
|
+
expect(sessionOpts[1]).toMatchObject({ workspace: 'site:test-execution', idleTimeout: 600, windowMode: 'background' });
|
|
162
162
|
expect(closeWindow).not.toHaveBeenCalled();
|
|
163
163
|
vi.restoreAllMocks();
|
|
164
164
|
});
|
|
@@ -187,6 +187,8 @@ describe('executeCommand — non-browser timeout', () => {
|
|
|
187
187
|
expect(sessionOpts[0]?.workspace).not.toBe(sessionOpts[1]?.workspace);
|
|
188
188
|
expect(sessionOpts[0]?.idleTimeout).toBeUndefined();
|
|
189
189
|
expect(sessionOpts[1]?.idleTimeout).toBeUndefined();
|
|
190
|
+
expect(sessionOpts[0]?.windowMode).toBe('background');
|
|
191
|
+
expect(sessionOpts[1]?.windowMode).toBe('background');
|
|
190
192
|
expect(closeWindow).toHaveBeenCalledTimes(2);
|
|
191
193
|
vi.restoreAllMocks();
|
|
192
194
|
});
|
|
@@ -372,18 +374,18 @@ describe('executeCommand — non-browser timeout', () => {
|
|
|
372
374
|
expect(closeWindow).toHaveBeenCalledTimes(1);
|
|
373
375
|
vi.restoreAllMocks();
|
|
374
376
|
});
|
|
375
|
-
it('skips closeWindow when
|
|
377
|
+
it('skips closeWindow when OPENCLI_KEEP_TAB=true (success path)', async () => {
|
|
376
378
|
const closeWindow = vi.fn().mockResolvedValue(undefined);
|
|
377
379
|
const mockPage = { closeWindow };
|
|
378
380
|
vi.spyOn(capRouting, 'shouldUseBrowserSession').mockReturnValue(true);
|
|
379
381
|
vi.spyOn(runtime, 'browserSession').mockImplementation(async (_Factory, fn) => fn(mockPage));
|
|
380
|
-
const prev = process.env.
|
|
381
|
-
process.env.
|
|
382
|
+
const prev = process.env.OPENCLI_KEEP_TAB;
|
|
383
|
+
process.env.OPENCLI_KEEP_TAB = 'true';
|
|
382
384
|
try {
|
|
383
385
|
const cmd = cli({
|
|
384
386
|
site: 'test-execution',
|
|
385
|
-
name: 'browser-
|
|
386
|
-
description: 'test closeWindow skipped with --
|
|
387
|
+
name: 'browser-keep-tab-success', access: 'read',
|
|
388
|
+
description: 'test closeWindow skipped with --keep-tab on success',
|
|
387
389
|
browser: true,
|
|
388
390
|
strategy: Strategy.PUBLIC,
|
|
389
391
|
func: async () => [{ ok: true }],
|
|
@@ -393,24 +395,24 @@ describe('executeCommand — non-browser timeout', () => {
|
|
|
393
395
|
}
|
|
394
396
|
finally {
|
|
395
397
|
if (prev === undefined)
|
|
396
|
-
delete process.env.
|
|
398
|
+
delete process.env.OPENCLI_KEEP_TAB;
|
|
397
399
|
else
|
|
398
|
-
process.env.
|
|
400
|
+
process.env.OPENCLI_KEEP_TAB = prev;
|
|
399
401
|
vi.restoreAllMocks();
|
|
400
402
|
}
|
|
401
403
|
});
|
|
402
|
-
it('skips closeWindow when
|
|
404
|
+
it('skips closeWindow when OPENCLI_KEEP_TAB=true (failure path)', async () => {
|
|
403
405
|
const closeWindow = vi.fn().mockResolvedValue(undefined);
|
|
404
406
|
const mockPage = { closeWindow };
|
|
405
407
|
vi.spyOn(capRouting, 'shouldUseBrowserSession').mockReturnValue(true);
|
|
406
408
|
vi.spyOn(runtime, 'browserSession').mockImplementation(async (_Factory, fn) => fn(mockPage));
|
|
407
|
-
const prev = process.env.
|
|
408
|
-
process.env.
|
|
409
|
+
const prev = process.env.OPENCLI_KEEP_TAB;
|
|
410
|
+
process.env.OPENCLI_KEEP_TAB = 'true';
|
|
409
411
|
try {
|
|
410
412
|
const cmd = cli({
|
|
411
413
|
site: 'test-execution',
|
|
412
|
-
name: 'browser-
|
|
413
|
-
description: 'test closeWindow skipped with --
|
|
414
|
+
name: 'browser-keep-tab-failure', access: 'read',
|
|
415
|
+
description: 'test closeWindow skipped with --keep-tab on failure',
|
|
414
416
|
browser: true,
|
|
415
417
|
strategy: Strategy.PUBLIC,
|
|
416
418
|
func: async () => { throw new Error('adapter failure'); },
|
|
@@ -420,12 +422,37 @@ describe('executeCommand — non-browser timeout', () => {
|
|
|
420
422
|
}
|
|
421
423
|
finally {
|
|
422
424
|
if (prev === undefined)
|
|
423
|
-
delete process.env.
|
|
425
|
+
delete process.env.OPENCLI_KEEP_TAB;
|
|
424
426
|
else
|
|
425
|
-
process.env.
|
|
427
|
+
process.env.OPENCLI_KEEP_TAB = prev;
|
|
426
428
|
vi.restoreAllMocks();
|
|
427
429
|
}
|
|
428
430
|
});
|
|
431
|
+
it('lets browser common options override adapter window and keep-tab defaults', async () => {
|
|
432
|
+
const closeWindow = vi.fn().mockResolvedValue(undefined);
|
|
433
|
+
const mockPage = { closeWindow };
|
|
434
|
+
const sessionOpts = [];
|
|
435
|
+
vi.spyOn(capRouting, 'shouldUseBrowserSession').mockReturnValue(true);
|
|
436
|
+
vi.spyOn(runtime, 'browserSession').mockImplementation(async (_Factory, fn, opts) => {
|
|
437
|
+
sessionOpts.push(opts ?? {});
|
|
438
|
+
return fn(mockPage);
|
|
439
|
+
});
|
|
440
|
+
const cmd = cli({
|
|
441
|
+
site: 'test-execution',
|
|
442
|
+
name: 'browser-window-options', access: 'read',
|
|
443
|
+
description: 'test browser common options',
|
|
444
|
+
browser: true,
|
|
445
|
+
strategy: Strategy.PUBLIC,
|
|
446
|
+
func: async () => [{ ok: true }],
|
|
447
|
+
});
|
|
448
|
+
await executeCommand(cmd, {}, false, {
|
|
449
|
+
windowMode: 'foreground',
|
|
450
|
+
keepTab: 'true',
|
|
451
|
+
});
|
|
452
|
+
expect(sessionOpts[0]).toMatchObject({ windowMode: 'foreground' });
|
|
453
|
+
expect(closeWindow).not.toHaveBeenCalled();
|
|
454
|
+
vi.restoreAllMocks();
|
|
455
|
+
});
|
|
429
456
|
it('does not re-run custom validation when args are already prepared', async () => {
|
|
430
457
|
const validateArgs = vi.fn();
|
|
431
458
|
const cmd = {
|
|
@@ -54,3 +54,27 @@
|
|
|
54
54
|
tags: [vercel, deployment, serverless, frontend, devops]
|
|
55
55
|
install:
|
|
56
56
|
default: "npm install -g vercel"
|
|
57
|
+
|
|
58
|
+
- name: tg-cli
|
|
59
|
+
binary: tg
|
|
60
|
+
description: "Telegram CLI — local-first sync, search, export via MTProto for AI agents"
|
|
61
|
+
homepage: "https://github.com/jackwener/tg-cli"
|
|
62
|
+
tags: [telegram, messaging, search, export, ai-agent]
|
|
63
|
+
install:
|
|
64
|
+
default: "uv tool install kabi-tg-cli"
|
|
65
|
+
|
|
66
|
+
- name: discord-cli
|
|
67
|
+
binary: discord
|
|
68
|
+
description: "Discord CLI — local-first sync, search, export via SQLite for AI agents"
|
|
69
|
+
homepage: "https://github.com/jackwener/discord-cli"
|
|
70
|
+
tags: [discord, messaging, search, export, ai-agent]
|
|
71
|
+
install:
|
|
72
|
+
default: "uv tool install kabi-discord-cli"
|
|
73
|
+
|
|
74
|
+
- name: wx-cli
|
|
75
|
+
binary: wx
|
|
76
|
+
description: "WeChat local data CLI — sessions, messages, search, contacts, export for AI agents"
|
|
77
|
+
homepage: "https://github.com/jackwener/wx-cli"
|
|
78
|
+
tags: [wechat, messaging, search, export, ai-agent]
|
|
79
|
+
install:
|
|
80
|
+
default: "npm install -g @jackwener/wx-cli"
|
package/dist/src/help.d.ts
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import type { CliCommand } from './registry.js';
|
|
3
3
|
export type StructuredHelpFormat = 'yaml' | 'json';
|
|
4
|
+
export interface ArgSpec {
|
|
5
|
+
name: string;
|
|
6
|
+
required?: true;
|
|
7
|
+
variadic?: true;
|
|
8
|
+
help?: string;
|
|
9
|
+
default?: unknown;
|
|
10
|
+
choices?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface OptionSpec {
|
|
13
|
+
name: string;
|
|
14
|
+
flags: string;
|
|
15
|
+
help?: string;
|
|
16
|
+
takes_value?: 'required' | 'optional';
|
|
17
|
+
required?: true;
|
|
18
|
+
default?: unknown;
|
|
19
|
+
choices?: string[];
|
|
20
|
+
negate?: true;
|
|
21
|
+
}
|
|
4
22
|
export declare function getRequestedHelpFormat(argv?: readonly string[]): StructuredHelpFormat | undefined;
|
|
5
23
|
export declare function renderStructuredHelp(data: unknown, format: StructuredHelpFormat): string;
|
|
6
24
|
export declare function wrapCommaList(items: readonly string[], opts?: {
|
|
@@ -29,11 +47,26 @@ export interface RootAdapterGroups {
|
|
|
29
47
|
sites: readonly string[];
|
|
30
48
|
}
|
|
31
49
|
export declare function formatRootAdapterHelpText(groups: RootAdapterGroups): string;
|
|
50
|
+
export declare function commanderNamespaceHelpData(namespaceRoot: Command, opts?: {
|
|
51
|
+
globalCommand?: Command;
|
|
52
|
+
description?: string;
|
|
53
|
+
}): Record<string, unknown>;
|
|
54
|
+
export declare function commanderCommandHelpData(namespaceRoot: Command, command: Command, opts?: {
|
|
55
|
+
globalCommand?: Command;
|
|
56
|
+
}): Record<string, unknown>;
|
|
57
|
+
export declare function commanderGroupHelpData(namespaceRoot: Command, groupCommand: Command, opts?: {
|
|
58
|
+
globalCommand?: Command;
|
|
59
|
+
}): Record<string, unknown>;
|
|
60
|
+
export declare function installCommanderNamespaceStructuredHelp(namespaceRoot: Command, opts?: {
|
|
61
|
+
globalCommand?: Command;
|
|
62
|
+
description?: string;
|
|
63
|
+
}): void;
|
|
32
64
|
export declare function formatCommandListTerm(cmd: CliCommand): string;
|
|
33
65
|
export declare function rootHelpData(program: Command, groups: RootAdapterGroups): Record<string, unknown>;
|
|
34
66
|
export declare function siteHelpData(site: string, commands: readonly CliCommand[]): Record<string, unknown>;
|
|
35
67
|
export declare function commandHelpData(cmd: CliCommand): Record<string, unknown>;
|
|
36
68
|
export declare function formatCommonOptionsHelpText(): string;
|
|
69
|
+
export declare function formatBrowserCommonOptionsHelpText(): string;
|
|
37
70
|
export declare function formatSiteHelpText(site: string, commands: readonly CliCommand[]): string;
|
|
38
71
|
export declare function formatCommandHelpText(cmd: CliCommand): string;
|
|
39
72
|
export declare function installStructuredHelp(command: Command, data: () => unknown, textSuffix?: string | (() => string)): void;
|
package/dist/src/help.js
CHANGED
|
@@ -28,6 +28,20 @@ const COMMON_OPTIONS = [
|
|
|
28
28
|
help: 'display help for command',
|
|
29
29
|
},
|
|
30
30
|
];
|
|
31
|
+
const BROWSER_COMMON_OPTIONS = [
|
|
32
|
+
{
|
|
33
|
+
flags: '--window <mode>',
|
|
34
|
+
name: 'window',
|
|
35
|
+
help: 'Browser window mode: foreground or background',
|
|
36
|
+
choices: ['foreground', 'background'],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
flags: '--keep-tab <bool>',
|
|
40
|
+
name: 'keep-tab',
|
|
41
|
+
help: 'Keep the browser tab lease after the command finishes',
|
|
42
|
+
choices: ['true', 'false'],
|
|
43
|
+
},
|
|
44
|
+
];
|
|
31
45
|
function normalizeStructuredHelpFormat(value) {
|
|
32
46
|
const normalized = value?.toLowerCase();
|
|
33
47
|
if (normalized === 'yaml' || normalized === 'yml')
|
|
@@ -125,6 +139,151 @@ function compactCommonOption(option) {
|
|
|
125
139
|
...('choices' in option ? { choices: option.choices } : {}),
|
|
126
140
|
};
|
|
127
141
|
}
|
|
142
|
+
function compactCommanderArgument(arg) {
|
|
143
|
+
return {
|
|
144
|
+
name: arg.name(),
|
|
145
|
+
...(arg.required ? { required: true } : {}),
|
|
146
|
+
...(arg.variadic ? { variadic: true } : {}),
|
|
147
|
+
...(arg.description ? { help: arg.description } : {}),
|
|
148
|
+
...(arg.defaultValue !== undefined ? { default: arg.defaultValue } : {}),
|
|
149
|
+
...(arg.argChoices?.length ? { choices: [...arg.argChoices] } : {}),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function compactCommanderOption(option) {
|
|
153
|
+
if (option.hidden)
|
|
154
|
+
return null;
|
|
155
|
+
return {
|
|
156
|
+
name: option.attributeName(),
|
|
157
|
+
flags: option.flags,
|
|
158
|
+
...(option.description ? { help: option.description } : {}),
|
|
159
|
+
...(option.required ? { takes_value: 'required' } : {}),
|
|
160
|
+
...(option.optional ? { takes_value: 'optional' } : {}),
|
|
161
|
+
...(option.mandatory ? { required: true } : {}),
|
|
162
|
+
...(option.defaultValue !== undefined ? { default: option.defaultValue } : {}),
|
|
163
|
+
...(option.argChoices?.length ? { choices: [...option.argChoices] } : {}),
|
|
164
|
+
...(option.negate ? { negate: true } : {}),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function compactCommanderOptions(options) {
|
|
168
|
+
return options
|
|
169
|
+
.map(compactCommanderOption)
|
|
170
|
+
.filter((option) => option !== null);
|
|
171
|
+
}
|
|
172
|
+
function commanderPath(command) {
|
|
173
|
+
const parts = [];
|
|
174
|
+
let current = command;
|
|
175
|
+
while (current) {
|
|
176
|
+
const name = current.name();
|
|
177
|
+
if (name)
|
|
178
|
+
parts.push(name);
|
|
179
|
+
current = current.parent;
|
|
180
|
+
}
|
|
181
|
+
return parts.reverse();
|
|
182
|
+
}
|
|
183
|
+
function commandPathFromRoot(namespaceRoot, command) {
|
|
184
|
+
const rootPath = commanderPath(namespaceRoot);
|
|
185
|
+
const commandPath = commanderPath(command);
|
|
186
|
+
return commandPath.slice(rootPath.length);
|
|
187
|
+
}
|
|
188
|
+
function collectLeafCommands(command) {
|
|
189
|
+
if (command.commands.length === 0)
|
|
190
|
+
return [command];
|
|
191
|
+
return command.commands.flatMap(child => collectLeafCommands(child));
|
|
192
|
+
}
|
|
193
|
+
function collectDescendantCommands(command) {
|
|
194
|
+
return command.commands.flatMap(child => [child, ...collectDescendantCommands(child)]);
|
|
195
|
+
}
|
|
196
|
+
function formatCommanderPositionals(args) {
|
|
197
|
+
return args
|
|
198
|
+
.map(arg => {
|
|
199
|
+
const name = `${arg.name()}${arg.variadic ? '...' : ''}`;
|
|
200
|
+
return arg.required ? `<${name}>` : `[${name}]`;
|
|
201
|
+
})
|
|
202
|
+
.join(' ');
|
|
203
|
+
}
|
|
204
|
+
function formatCommanderUsage(command, opts = {}) {
|
|
205
|
+
const path = commanderPath(command).join(' ');
|
|
206
|
+
const positionalText = formatCommanderPositionals(command.registeredArguments);
|
|
207
|
+
const hasOptions = compactCommanderOptions(command.options).length > 0
|
|
208
|
+
|| (opts.namespaceRoot ? compactCommanderOptions(opts.namespaceRoot.options).length > 0 : false)
|
|
209
|
+
|| (opts.globalCommand ? compactCommanderOptions(opts.globalCommand.options).length > 0 : false);
|
|
210
|
+
const optionText = hasOptions ? ' [options]' : '';
|
|
211
|
+
return `${path}${positionalText ? ` ${positionalText}` : ''}${optionText}`;
|
|
212
|
+
}
|
|
213
|
+
function compactCommanderCommand(namespaceRoot, command, opts = {}) {
|
|
214
|
+
const relativePath = commandPathFromRoot(namespaceRoot, command);
|
|
215
|
+
return {
|
|
216
|
+
name: relativePath.join(' '),
|
|
217
|
+
command: commanderPath(command).join(' '),
|
|
218
|
+
usage: formatCommanderUsage(command, { namespaceRoot, globalCommand: opts.globalCommand }),
|
|
219
|
+
description: command.description(),
|
|
220
|
+
...(command.aliases().length ? { aliases: command.aliases() } : {}),
|
|
221
|
+
positionals: command.registeredArguments.map(compactCommanderArgument),
|
|
222
|
+
command_options: compactCommanderOptions(command.options),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
export function commanderNamespaceHelpData(namespaceRoot, opts = {}) {
|
|
226
|
+
const leaves = collectLeafCommands(namespaceRoot)
|
|
227
|
+
.filter(command => command !== namespaceRoot)
|
|
228
|
+
.sort((a, b) => commandPathFromRoot(namespaceRoot, a).join(' ').localeCompare(commandPathFromRoot(namespaceRoot, b).join(' ')));
|
|
229
|
+
return {
|
|
230
|
+
namespace: namespaceRoot.name(),
|
|
231
|
+
command: commanderPath(namespaceRoot).join(' '),
|
|
232
|
+
usage: `${commanderPath(namespaceRoot).join(' ')} <command> [args] [options]`,
|
|
233
|
+
description: opts.description ?? namespaceRoot.description(),
|
|
234
|
+
command_count: leaves.length,
|
|
235
|
+
commands: leaves.map(command => compactCommanderCommand(namespaceRoot, command, opts)),
|
|
236
|
+
namespace_options: compactCommanderOptions(namespaceRoot.options),
|
|
237
|
+
...(opts.globalCommand ? { global_options: compactCommanderOptions(opts.globalCommand.options) } : {}),
|
|
238
|
+
structured_help: {
|
|
239
|
+
formats: ['yaml', 'json'],
|
|
240
|
+
usage: `${commanderPath(namespaceRoot).join(' ')} --help -f yaml`,
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
export function commanderCommandHelpData(namespaceRoot, command, opts = {}) {
|
|
245
|
+
return {
|
|
246
|
+
namespace: namespaceRoot.name(),
|
|
247
|
+
...compactCommanderCommand(namespaceRoot, command, opts),
|
|
248
|
+
namespace_options: compactCommanderOptions(namespaceRoot.options),
|
|
249
|
+
...(opts.globalCommand ? { global_options: compactCommanderOptions(opts.globalCommand.options) } : {}),
|
|
250
|
+
structured_help: {
|
|
251
|
+
formats: ['yaml', 'json'],
|
|
252
|
+
usage: `${commanderPath(command).join(' ')} --help -f yaml`,
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
export function commanderGroupHelpData(namespaceRoot, groupCommand, opts = {}) {
|
|
257
|
+
const leaves = collectLeafCommands(groupCommand)
|
|
258
|
+
.filter(command => command !== groupCommand)
|
|
259
|
+
.sort((a, b) => commandPathFromRoot(namespaceRoot, a).join(' ').localeCompare(commandPathFromRoot(namespaceRoot, b).join(' ')));
|
|
260
|
+
return {
|
|
261
|
+
namespace: namespaceRoot.name(),
|
|
262
|
+
group: commandPathFromRoot(namespaceRoot, groupCommand).join(' '),
|
|
263
|
+
command: commanderPath(groupCommand).join(' '),
|
|
264
|
+
usage: `${commanderPath(groupCommand).join(' ')} <command> [args] [options]`,
|
|
265
|
+
description: groupCommand.description(),
|
|
266
|
+
command_count: leaves.length,
|
|
267
|
+
commands: leaves.map(command => compactCommanderCommand(namespaceRoot, command, opts)),
|
|
268
|
+
namespace_options: compactCommanderOptions(namespaceRoot.options),
|
|
269
|
+
...(opts.globalCommand ? { global_options: compactCommanderOptions(opts.globalCommand.options) } : {}),
|
|
270
|
+
structured_help: {
|
|
271
|
+
formats: ['yaml', 'json'],
|
|
272
|
+
usage: `${commanderPath(groupCommand).join(' ')} --help -f yaml`,
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
export function installCommanderNamespaceStructuredHelp(namespaceRoot, opts = {}) {
|
|
277
|
+
installStructuredHelp(namespaceRoot, () => commanderNamespaceHelpData(namespaceRoot, opts));
|
|
278
|
+
for (const command of collectDescendantCommands(namespaceRoot)) {
|
|
279
|
+
if (command.commands.length > 0) {
|
|
280
|
+
installStructuredHelp(command, () => commanderGroupHelpData(namespaceRoot, command, opts));
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
installStructuredHelp(command, () => commanderCommandHelpData(namespaceRoot, command, opts));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
128
287
|
function positionals(cmd) {
|
|
129
288
|
return cmd.args.filter(arg => arg.positional);
|
|
130
289
|
}
|
|
@@ -162,6 +321,7 @@ function compactCommand(cmd) {
|
|
|
162
321
|
...(cmd.aliases?.length ? { aliases: cmd.aliases } : {}),
|
|
163
322
|
positionals: positionals(cmd).map(compactArg),
|
|
164
323
|
command_options: commandOptions(cmd).map(compactArg),
|
|
324
|
+
...(cmd.browser ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
|
|
165
325
|
example: formatCommandExample(cmd),
|
|
166
326
|
...(cmd.browserSession ? { browserSession: cmd.browserSession } : {}),
|
|
167
327
|
...(cmd.defaultFormat ? { defaultFormat: cmd.defaultFormat } : {}),
|
|
@@ -208,6 +368,7 @@ export function siteHelpData(site, commands) {
|
|
|
208
368
|
command_count: unique.length,
|
|
209
369
|
commands: unique.map(cmd => compactCommand(cmd)),
|
|
210
370
|
common_options: COMMON_OPTIONS.map(compactCommonOption),
|
|
371
|
+
...(unique.some(cmd => cmd.browser) ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
|
|
211
372
|
next: [
|
|
212
373
|
`opencli ${site} <command> --help -f yaml`,
|
|
213
374
|
`opencli ${site} <command> -f yaml`,
|
|
@@ -219,6 +380,7 @@ export function commandHelpData(cmd) {
|
|
|
219
380
|
site: cmd.site,
|
|
220
381
|
...compactCommand(cmd),
|
|
221
382
|
common_options: COMMON_OPTIONS.map(compactCommonOption),
|
|
383
|
+
...(cmd.browser ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
|
|
222
384
|
output_formats: ['table', 'plain', 'yaml', 'json', 'md', 'csv'],
|
|
223
385
|
};
|
|
224
386
|
}
|
|
@@ -249,6 +411,15 @@ export function formatCommonOptionsHelpText() {
|
|
|
249
411
|
});
|
|
250
412
|
return ['Common options:', ...formatRows(rows)].join('\n');
|
|
251
413
|
}
|
|
414
|
+
export function formatBrowserCommonOptionsHelpText() {
|
|
415
|
+
const rows = BROWSER_COMMON_OPTIONS.map(option => {
|
|
416
|
+
const details = [option.help];
|
|
417
|
+
if ('choices' in option)
|
|
418
|
+
details.push(`choices: ${option.choices.join(', ')}`);
|
|
419
|
+
return [option.flags, details.join(' ')];
|
|
420
|
+
});
|
|
421
|
+
return ['Browser common options:', ...formatRows(rows)].join('\n');
|
|
422
|
+
}
|
|
252
423
|
export function formatSiteHelpText(site, commands) {
|
|
253
424
|
const unique = [...new Map(commands.map(cmd => [fullName(cmd), cmd])).values()]
|
|
254
425
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -261,6 +432,7 @@ export function formatSiteHelpText(site, commands) {
|
|
|
261
432
|
...formatRows(unique.map(cmd => [formatCommandListTerm(cmd), formatSiteCommandDescription(cmd)])),
|
|
262
433
|
'',
|
|
263
434
|
formatCommonOptionsHelpText(),
|
|
435
|
+
...(unique.some(cmd => cmd.browser) ? ['', formatBrowserCommonOptionsHelpText()] : []),
|
|
264
436
|
'',
|
|
265
437
|
`Agent tip: use 'opencli ${site} --help -f yaml' to get all command args/options in one structured response.`,
|
|
266
438
|
'',
|
|
@@ -289,6 +461,8 @@ export function formatCommandHelpText(cmd) {
|
|
|
289
461
|
lines.push('Command options:', ...formatRows(optionRows), '');
|
|
290
462
|
}
|
|
291
463
|
lines.push(formatCommonOptionsHelpText(), '');
|
|
464
|
+
if (cmd.browser)
|
|
465
|
+
lines.push(formatBrowserCommonOptionsHelpText(), '');
|
|
292
466
|
const meta = [];
|
|
293
467
|
meta.push(`Access: ${cmd.access}`);
|
|
294
468
|
meta.push(`Browser: ${cmd.browser ? 'yes' : 'no'}`);
|
package/dist/src/main.js
CHANGED
|
@@ -27,21 +27,11 @@ const __dirname = path.dirname(__filename);
|
|
|
27
27
|
// Use findPackageRoot so the path works both in dev (src/main.ts) and prod (dist/src/main.js).
|
|
28
28
|
const BUILTIN_CLIS = path.join(findPackageRoot(__filename), 'clis');
|
|
29
29
|
const USER_CLIS = path.join(os.homedir(), '.opencli', 'clis');
|
|
30
|
-
// ──
|
|
31
|
-
// `--
|
|
32
|
-
//
|
|
33
|
-
//
|
|
30
|
+
// ── Browser reuse flag ───────────────────────────────────────────────────
|
|
31
|
+
// `--reuse` is a runtime-level browser session override rather than an adapter
|
|
32
|
+
// arg. Strip it before Commander runs and expose it through an explicit env
|
|
33
|
+
// name. Window/keep-tab are registered on browser-backed commands directly.
|
|
34
34
|
{
|
|
35
|
-
const liveIdx = process.argv.indexOf('--live');
|
|
36
|
-
if (liveIdx !== -1) {
|
|
37
|
-
process.env.OPENCLI_LIVE = '1';
|
|
38
|
-
process.argv.splice(liveIdx, 1);
|
|
39
|
-
}
|
|
40
|
-
const focusIdx = process.argv.indexOf('--focus');
|
|
41
|
-
if (focusIdx !== -1) {
|
|
42
|
-
process.env.OPENCLI_WINDOW_FOCUSED = '1';
|
|
43
|
-
process.argv.splice(focusIdx, 1);
|
|
44
|
-
}
|
|
45
35
|
const reuseIdx = process.argv.findIndex(arg => arg === '--reuse' || arg.startsWith('--reuse='));
|
|
46
36
|
if (reuseIdx !== -1) {
|
|
47
37
|
const arg = process.argv[reuseIdx];
|
package/dist/src/runtime.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { IPage } from './types.js';
|
|
|
6
6
|
export declare function getBrowserFactory(site?: string): new () => IBrowserFactory;
|
|
7
7
|
export declare const DEFAULT_BROWSER_CONNECT_TIMEOUT: number;
|
|
8
8
|
export declare const DEFAULT_BROWSER_COMMAND_TIMEOUT: number;
|
|
9
|
+
export type BrowserWindowMode = 'foreground' | 'background';
|
|
9
10
|
/**
|
|
10
11
|
* Timeout with seconds unit. Used for high-level command timeouts.
|
|
11
12
|
*/
|
|
@@ -28,6 +29,7 @@ export interface IBrowserFactory {
|
|
|
28
29
|
cdpEndpoint?: string;
|
|
29
30
|
contextId?: string;
|
|
30
31
|
idleTimeout?: number;
|
|
32
|
+
windowMode?: BrowserWindowMode;
|
|
31
33
|
}): Promise<IPage>;
|
|
32
34
|
close(): Promise<void>;
|
|
33
35
|
}
|
|
@@ -36,4 +38,5 @@ export declare function browserSession<T>(BrowserFactory: new () => IBrowserFact
|
|
|
36
38
|
cdpEndpoint?: string;
|
|
37
39
|
contextId?: string;
|
|
38
40
|
idleTimeout?: number;
|
|
41
|
+
windowMode?: BrowserWindowMode;
|
|
39
42
|
}): Promise<T>;
|
package/dist/src/runtime.js
CHANGED