feat: add conservative capability routing
This commit is contained in:
1 parent
b60c69950d
commit
47a898125f
3 files changed
+77
-1
No files matched your search
@@ -0,0 +1,47 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { Strategy, type CliCommand } from './registry.js';
|
||||
import { shouldUseBrowserSession } from './capabilityRouting.js';
|
||||
|
||||
function makeCmd(partial: Partial<CliCommand>): CliCommand {
|
||||
return {
|
||||
site: 'test',
|
||||
name: 'command',
|
||||
description: '',
|
||||
args: [],
|
||||
...partial,
|
||||
};
|
||||
}
|
||||
|
||||
describe('shouldUseBrowserSession', () => {
|
||||
it('skips browser session for public fetch-only pipelines', () => {
|
||||
expect(shouldUseBrowserSession(makeCmd({
|
||||
browser: true,
|
||||
strategy: Strategy.PUBLIC,
|
||||
pipeline: [{ fetch: 'https://example.com/api' }, { select: 'items' }],
|
||||
}))).toBe(false);
|
||||
});
|
||||
|
||||
it('keeps browser session for public pipelines with browser-only steps', () => {
|
||||
expect(shouldUseBrowserSession(makeCmd({
|
||||
browser: true,
|
||||
strategy: Strategy.PUBLIC,
|
||||
pipeline: [{ navigate: 'https://example.com' }, { evaluate: '() => []' }],
|
||||
}))).toBe(true);
|
||||
});
|
||||
|
||||
it('keeps browser session for non-public strategies', () => {
|
||||
expect(shouldUseBrowserSession(makeCmd({
|
||||
browser: true,
|
||||
strategy: Strategy.COOKIE,
|
||||
pipeline: [{ fetch: 'https://example.com/api' }],
|
||||
}))).toBe(true);
|
||||
});
|
||||
|
||||
it('keeps browser session for function adapters', () => {
|
||||
expect(shouldUseBrowserSession(makeCmd({
|
||||
browser: true,
|
||||
strategy: Strategy.PUBLIC,
|
||||
func: async () => [],
|
||||
}))).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Strategy, type CliCommand } from './registry.js';
|
||||
|
||||
const BROWSER_ONLY_STEPS = new Set([
|
||||
'navigate',
|
||||
'click',
|
||||
'type',
|
||||
'wait',
|
||||
'press',
|
||||
'snapshot',
|
||||
'evaluate',
|
||||
'intercept',
|
||||
'tap',
|
||||
]);
|
||||
|
||||
function pipelineNeedsBrowserSession(pipeline: Record<string, unknown>[]): boolean {
|
||||
return pipeline.some((step) => {
|
||||
if (!step || typeof step !== 'object') return false;
|
||||
return Object.keys(step).some((op) => BROWSER_ONLY_STEPS.has(op));
|
||||
});
|
||||
}
|
||||
|
||||
export function shouldUseBrowserSession(cmd: CliCommand): boolean {
|
||||
if (!cmd.browser) return false;
|
||||
if (cmd.func) return true;
|
||||
if (!cmd.pipeline || cmd.pipeline.length === 0) return true;
|
||||
if (cmd.strategy !== Strategy.PUBLIC) return true;
|
||||
return pipelineNeedsBrowserSession(cmd.pipeline as Record<string, unknown>[]);
|
||||
}
|
||||
+2
-1
@@ -8,6 +8,7 @@ import { browserSession, DEFAULT_BROWSER_COMMAND_TIMEOUT, runWithTimeout } from
|
||||
import { PKG_VERSION } from './version.js';
|
||||
import { printCompletionScript } from './completion.js';
|
||||
import { CliError } from './errors.js';
|
||||
import { shouldUseBrowserSession } from './capabilityRouting.js';
|
||||
|
||||
export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
||||
const program = new Command();
|
||||
@@ -158,7 +159,7 @@ export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
||||
try {
|
||||
if (actionOpts.verbose) process.env.OPENCLI_VERBOSE = '1';
|
||||
let result: any;
|
||||
if (cmd.browser) {
|
||||
if (shouldUseBrowserSession(cmd)) {
|
||||
const BrowserFactory = process.env.OPENCLI_CDP_ENDPOINT ? CDPBridge : BrowserBridge;
|
||||
result = await browserSession(BrowserFactory as any, async (page) => {
|
||||
return runWithTimeout(executeCommand(cmd, page, kwargs, actionOpts.verbose), { timeout: cmd.timeoutSeconds ?? DEFAULT_BROWSER_COMMAND_TIMEOUT, label: fullName(cmd) });
|
||||
|
||||
Reference in new issue
Block a user