feat: add conservative capability routing

This commit is contained in:
jackwener committed 2026-03-20 14:10:51 +08:00
1 parent b60c69950d
commit 47a898125f
3 files changed
+77 -1

No files matched your search

+47
View File
@@ -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);
});
});
+28
View File
@@ -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
View File
@@ -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) });