Skip to content

Commit 2ddf571

Browse files
authored
feat: auto-close adapter windows, add OPENCLI_WINDOW_FOCUSED, document config (#915)
* feat: auto-close adapter windows, add OPENCLI_WINDOW_FOCUSED, document config 1. Adapter commands now close the automation window immediately after completion instead of waiting for the 30s idle timeout. 2. OPENCLI_WINDOW_FOCUSED=1 opens automation windows in the foreground (useful for debugging). Default remains background. 3. Add Configuration section to README (EN/ZH) and opencli-usage skill listing all stable user-facing environment variables. * Fix OPENCLI_WINDOW_FOCUSED to be per-request, not frozen at daemon startup Move env var read from daemon (startup-time constant) to CLI side (sendCommandRaw), so it works correctly with the persistent daemon model. Each request now reads the env var fresh and includes windowFocused in the command payload.
1 parent 7f31df2 commit 2ddf571

File tree

7 files changed

+57
-3
lines changed

7 files changed

+57
-3
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,20 @@ OpenCLI is not only for websites. It can also:
141141

142142
> **Important**: Browser-backed commands reuse your Chrome/Chromium login session. If you get empty data or permission-like failures, first confirm the site is already open and authenticated in Chrome/Chromium.
143143
144+
## Configuration
145+
146+
| Variable | Default | Description |
147+
|----------|---------|-------------|
148+
| `OPENCLI_DAEMON_PORT` | `19825` | HTTP port for the daemon-extension bridge |
149+
| `OPENCLI_WINDOW_FOCUSED` | `false` | Set to `1` to open automation windows in the foreground (useful for debugging) |
150+
| `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | Seconds to wait for browser connection |
151+
| `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | Seconds to wait for a single browser command |
152+
| `OPENCLI_BROWSER_EXPLORE_TIMEOUT` | `120` | Seconds to wait for explore/record operations |
153+
| `OPENCLI_CDP_ENDPOINT` || Chrome DevTools Protocol endpoint for remote browser or Electron apps |
154+
| `OPENCLI_CDP_TARGET` || Filter CDP targets by URL substring (e.g. `detail.1688.com`) |
155+
| `OPENCLI_VERBOSE` | `false` | Enable verbose logging (`-v` flag also works) |
156+
| `OPENCLI_DIAGNOSTIC` | `false` | Set to `1` to capture structured diagnostic context on failures |
157+
144158
## Update
145159

146160
```bash

README.zh-CN.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ OpenCLI 不只是网站 CLI,还可以:
129129

130130
> **重要**:浏览器型命令直接复用你的 Chrome/Chromium 登录态。如果拿到空数据或出现权限类失败,先确认目标站点已经在浏览器里打开并完成登录。
131131
132+
## 配置
133+
134+
| 变量 | 默认值 | 说明 |
135+
|------|--------|------|
136+
| `OPENCLI_DAEMON_PORT` | `19825` | daemon-extension 通信端口 |
137+
| `OPENCLI_WINDOW_FOCUSED` | `false` | 设为 `1` 时 automation 窗口在前台打开(适合调试) |
138+
| `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | 浏览器连接超时(秒) |
139+
| `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | 单个浏览器命令超时(秒) |
140+
| `OPENCLI_BROWSER_EXPLORE_TIMEOUT` | `120` | explore/record 操作超时(秒) |
141+
| `OPENCLI_CDP_ENDPOINT` || Chrome DevTools Protocol 端点,用于远程浏览器或 Electron 应用 |
142+
| `OPENCLI_CDP_TARGET` || 按 URL 子串过滤 CDP target(如 `detail.1688.com`|
143+
| `OPENCLI_VERBOSE` | `false` | 启用详细日志(`-v` 也可以) |
144+
| `OPENCLI_DIAGNOSTIC` | `false` | 设为 `1` 时在失败时输出结构化诊断上下文 |
145+
132146
## 更新
133147

134148
```bash

extension/src/background.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ type AutomationSession = {
124124

125125
const automationSessions = new Map<string, AutomationSession>();
126126
const WINDOW_IDLE_TIMEOUT = 30000; // 30s — quick cleanup after command finishes
127+
let windowFocused = false; // set per-command from daemon's OPENCLI_WINDOW_FOCUSED
127128

128129
function getWorkspaceKey(workspace?: string): string {
129130
return workspace?.trim() || 'default';
@@ -176,7 +177,7 @@ async function getAutomationWindow(workspace: string, initialUrl?: string): Prom
176177
// state value for windows.create(). The window defaults to 'normal' state anyway.
177178
const win = await chrome.windows.create({
178179
url: startUrl,
179-
focused: false,
180+
focused: windowFocused,
180181
width: 1280,
181182
height: 900,
182183
type: 'normal',
@@ -272,6 +273,7 @@ chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
272273

273274
async function handleCommand(cmd: Command): Promise<Result> {
274275
const workspace = getWorkspaceKey(cmd.workspace);
276+
windowFocused = cmd.windowFocused === true;
275277
// Reset idle timer on every command (window stays alive while active)
276278
resetWindowIdleTimer(workspace);
277279
try {

extension/src/protocol.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export interface Command {
6363
cdpMethod?: string;
6464
/** CDP method params for 'cdp' action */
6565
cdpParams?: Record<string, unknown>;
66+
/** When true, automation windows are created in the foreground (focused) */
67+
windowFocused?: boolean;
6668
}
6769

6870
export interface Result {

skills/opencli-usage/SKILL.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,20 @@ opencli record <url> # Record API calls manually
182182

183183
All commands support: `--format` / `-f` with `table` `json` `yaml` `md` `csv`
184184

185+
## Configuration
186+
187+
| Variable | Default | Description |
188+
|----------|---------|-------------|
189+
| `OPENCLI_DAEMON_PORT` | `19825` | Daemon-extension bridge port |
190+
| `OPENCLI_WINDOW_FOCUSED` | `false` | `1` = open automation windows in foreground |
191+
| `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | Browser connection timeout (seconds) |
192+
| `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | Single command timeout (seconds) |
193+
| `OPENCLI_BROWSER_EXPLORE_TIMEOUT` | `120` | Explore/record timeout (seconds) |
194+
| `OPENCLI_CDP_ENDPOINT` || CDP endpoint for remote browser / Electron apps |
195+
| `OPENCLI_CDP_TARGET` || Filter CDP targets by URL substring |
196+
| `OPENCLI_VERBOSE` | `false` | Verbose logging (`-v` flag also works) |
197+
| `OPENCLI_DIAGNOSTIC` | `false` | `1` = structured diagnostic on failures |
198+
185199
## Self-Repair
186200

187201
If a command fails due to a site change (selector, API, or response schema), **automatically fix the adapter and retry** instead of reporting failure. Re-run the command with `OPENCLI_DIAGNOSTIC=1` to get structured diagnostic context, then fix the adapter file at `RepairContext.adapter.sourcePath` and retry. Max 3 repair rounds. See the `opencli-autofix` skill for the full workflow.

src/browser/daemon-client.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ export interface DaemonCommand {
4848
pattern?: string;
4949
cdpMethod?: string;
5050
cdpParams?: Record<string, unknown>;
51+
/** When true, automation windows are created in the foreground */
52+
windowFocused?: boolean;
5153
}
5254

5355
export interface DaemonResult {
@@ -137,7 +139,9 @@ async function sendCommandRaw(
137139

138140
for (let attempt = 1; attempt <= maxRetries; attempt++) {
139141
const id = generateId();
140-
const command: DaemonCommand = { id, action, ...params };
142+
const wf = process.env.OPENCLI_WINDOW_FOCUSED;
143+
const windowFocused = (wf === '1' || wf === 'true') ? true : undefined;
144+
const command: DaemonCommand = { id, action, ...params, ...(windowFocused && { windowFocused }) };
141145
try {
142146
const res = await requestDaemon('/command', {
143147
method: 'POST',

src/execution.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,14 @@ export async function executeCommand(
193193
}
194194
}
195195
try {
196-
return await runWithTimeout(runCommand(cmd, page, kwargs, debug), {
196+
const result = await runWithTimeout(runCommand(cmd, page, kwargs, debug), {
197197
timeout: cmd.timeoutSeconds ?? DEFAULT_BROWSER_COMMAND_TIMEOUT,
198198
label: fullName(cmd),
199199
});
200+
// Adapter commands are one-shot — close the automation window immediately
201+
// instead of waiting for the 30s idle timeout.
202+
await page.closeWindow?.().catch(() => {});
203+
return result;
200204
} catch (err) {
201205
// Collect diagnostic while page is still alive (before browserSession closes it).
202206
if (isDiagnosticEnabled()) {

0 commit comments

Comments
 (0)