Skip to content
Open

V1 #1498

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
148 commits
Select commit Hold shift + click to select a range
c1a3398
fix(cli): allow duplicate YAML files in config.yaml (#1327)
Copilot Oct 17, 2025
46ffc1d
refactor(core): remove non-OpenAI SDK support and upgrade to OpenAI 6…
quanru Oct 17, 2025
80a2c97
feat(core,shared): enforce VL mode requirement for Planning (#1332)
quanru Oct 17, 2025
2a98471
chore(core): remove warning msg for gpt-4 (#1331)
yuyutaotao Oct 20, 2025
23c49d3
feat(core): update recorder (#1330)
yuyutaotao Oct 20, 2025
68952aa
refactor: rename API methods for improved clarity (#1335)
quanru Oct 20, 2025
c9b385b
chore(core): update tasks impementation (#1338)
yuyutaotao Oct 20, 2025
d91e8f7
chore(release): upgrade all packages to v1.0.0 (#1340)
quanru Oct 20, 2025
469b843
refactor(core): remove unused getXpathsById method (#1342)
quanru Oct 20, 2025
89b4067
feat(core): support custom OpenAI client instances for observability …
quanru Oct 21, 2025
95eb850
chore(ci): enable workflows for PRs targeting 1.0 branch (#1345)
quanru Oct 21, 2025
581d5fb
Merge main to 1.0 (#1348)
quanru Oct 21, 2025
dc60bc3
refine(core): use 'subTask' flag to reuse context (#1350)
yuyutaotao Oct 21, 2025
641d326
chore(lint): fix linting and formatting issues (#1351)
quanru Oct 21, 2025
767127e
feat(chrome-extension): enable hot reload for development (#1353)
quanru Oct 21, 2025
b150f2f
Merge main (#1371)
quanru Oct 23, 2025
5c5b7bd
feat(bridge-mode): add remote access support for cross-machine commun…
quanru Oct 24, 2025
b10ad89
fix(build): switch from nano-staged to lint-staged for proper auto-fi…
quanru Oct 24, 2025
fd58ead
feat(yaml): Support all device options in YAML configuration (#1367)
quanru Oct 24, 2025
87026c4
feat(report): update task display naming conventions (#1379)
quanru Oct 27, 2025
edc4064
fix(cli): use clonedYamlScript consistently for agent configuration (…
quanru Oct 27, 2025
5300926
refactor(env): modernize model configuration environment variables (#…
quanru Oct 27, 2025
57cd24a
refactor(core): remove tree in context (#1376)
yuyutaotao Oct 27, 2025
9894171
feat(core): update signature of warp-openai (#1383)
yuyutaotao Oct 27, 2025
4ee95a8
feat(env): add backward compatibility for MIDSCENE_OPENAI_* environme…
quanru Oct 27, 2025
52db2aa
feat(android): add screenshot polling fallback for remote devices (#1…
quanru Oct 27, 2025
b709f7f
refactor(report): consolidate PlaygroundSDK creation for report compo…
quanru Oct 28, 2025
2820964
refactor(core): rename Insight class to Service (#1386)
quanru Oct 28, 2025
bdf0999
docs(site): clarify file execution order in YAML scripts docs (#1397)
quanru Oct 29, 2025
11046a8
fix(core): improve Assert task error handling (#1399)
quanru Oct 29, 2025
75f2ff1
fix(web-integration): prevent temp file leakage in Playwright tests (…
quanru Oct 29, 2025
41944c9
feat(core): reuse context for screenshot (#1401)
yuyutaotao Oct 29, 2025
ef94425
chore(core): remove @midscene/recorder from core.deps (#1394)
EAGzzyCSL Oct 29, 2025
ff7ccb2
feat(core): optimize AI prompts and implement order-sensitive judgmen…
quanru Oct 29, 2025
77aa9dc
fix(ios): use WebDriver Clear API for dynamic input fields (#1403)
quanru Oct 30, 2025
cdeae16
feat(shared): add XPath match count helper and warning for ambiguous …
quanru Oct 30, 2025
c7fe766
fix(visualizer): prevent video export hang caused by animation race c…
quanru Oct 30, 2025
5baeddd
docs(site): add WebDriverAgent version requirement to iOS guide (#1411)
quanru Nov 1, 2025
9bffc83
fix(core): action context as param (#1415)
yuyutaotao Nov 3, 2025
6e4b196
feat(core): add runAdbShell support to YAML automation scripts (#1391)
Copilot Nov 3, 2025
44589ae
feat(core): show intent in report (#1407)
yuyutaotao Nov 4, 2025
7a454d5
refactor(core): change Locate task from Insight to Planning type (#1406)
quanru Nov 4, 2025
706f70c
feat(core): update timeout strategy of aiWaitFor (#1419)
yuyutaotao Nov 4, 2025
ee2ff72
chore(core): refine error processing of agent (#1417)
yuyutaotao Nov 4, 2025
94f4f74
feat(android,ios): expose mobile system navigation actions (#1420)
yuyutaotao Nov 4, 2025
1166529
fix(android): correct orientation handling for displayId screenshots …
Copilot Nov 6, 2025
b386a5e
docs(site): remove unreleased model env names (#1427)
yuyutaotao Nov 7, 2025
0017b20
feat(ios): add WebDriverAgent 5.x-7.x compatibility (#1426)
quanru Nov 7, 2025
03485d6
fix(visualizer): cursor not move in player (#1429)
quanru Nov 7, 2025
8378dae
docs(core): docs for 1.0 (#1423)
yuyutaotao Nov 7, 2025
8d19a22
fix(core): make paramSchema optional for actions without parameters (…
quanru Nov 7, 2025
341bdb8
fix: workflow of planning (#1431)
yuyutaotao Nov 10, 2025
ee40b90
Enhanced report UI with improved element rendering and highlight effe…
quanru Nov 10, 2025
6769784
feat(shared): unify VQA and grounding models into insight model (#1432)
quanru Nov 10, 2025
d8cf126
feat(report): Add comprehensive dark mode support (#1434)
quanru Nov 10, 2025
aa30ba8
feat(report): replace sidebar grid layout with antd Table (#1436)
quanru Nov 10, 2025
1228a7d
feat(core): update sidebar ui (#1437)
yuyutaotao Nov 11, 2025
d1104a0
fix(core): replay scripts (#1440)
yuyutaotao Nov 11, 2025
4a0680b
feat(report): Improve dark mode UI styling (#1438)
quanru Nov 11, 2025
2792369
feat(core): show markup in screenshot panel (#1444)
yuyutaotao Nov 11, 2025
6fcc788
feat(core): redefine scroll param (#1441)
yuyutaotao Nov 11, 2025
225224a
feat(mcp): implement auto-destroy agent after each tool call (#1443)
quanru Nov 11, 2025
43e3316
feat(core): redefine the ai shortcut (#1445)
yuyutaotao Nov 11, 2025
12345da
fix(core): report scripts
yuyutaotao Nov 11, 2025
b88a183
Merge branch '1.0' of https://github.com/web-infra-dev/midscene into 1.0
yuyutaotao Nov 11, 2025
78c9cad
fix(test): fix failing PageAgent RightClick unit tests (#1449)
quanru Nov 13, 2025
a7b5e7f
fix(core): backward compatible for aiScroll (#1447)
yuyutaotao Nov 13, 2025
00bedbc
feat(core): update the 'locate' field of input (#1451)
yuyutaotao Nov 13, 2025
21ef4a5
fix(core): adaptive bbox (#1452)
yuyutaotao Nov 13, 2025
7c111de
fix(visualizer): add null check for action.param in replay scripts (#…
quanru Nov 13, 2025
d79b430
docs(core): update docs for model selection (#1455)
yuyutaotao Nov 14, 2025
52a18df
docs: add remote browser connection guide for Playwright and Puppetee…
quanru Nov 14, 2025
1830bd5
feat(docs): add CDP WebSocket URL guide and integrate into Playwright…
quanru Nov 14, 2025
351ed9e
docs(rspress): upgrade to Rspress V2 new UI (#1458)
SoonIter Nov 17, 2025
9daa219
docs(rspress): upgrade to 2.0.0-rc.0 (#1464)
SoonIter Nov 17, 2025
affe6a1
feat(cli): auto-parse all device options with documentation links (#1…
quanru Nov 17, 2025
182b67a
feat(site): implement custom homepage with i18n support (#1466)
quanru Nov 17, 2025
06c3ce7
docs(core): update api docs (#1468)
yuyutaotao Nov 18, 2025
45b9af6
chore(core): add the missing web API doc
yuyutaotao Nov 18, 2025
543c505
fix(core): fix dead link to doc
yuyutaotao Nov 18, 2025
bb4e120
docs(core): fix all dead links
yuyutaotao Nov 18, 2025
2fbe8be
feat(shared): Introduce MIDSCENE_MODEL_FAMILY for unified model confi…
quanru Nov 18, 2025
cb73bcb
chore(core): fix lint
yuyutaotao Nov 18, 2025
018e501
docs: 1.0 homepage (#1469)
quanru Nov 18, 2025
9639db1
refactor(theme): replace useDark hook with tailwind dark: modifier (#…
quanru Nov 18, 2025
aacc1c4
fix(core): normalize JSON whitespace in LLM responses (#1472)
quanru Nov 18, 2025
a0aedfa
refactor(ui): improve dark mode consistency and detail panel layout (…
quanru Nov 18, 2025
2e4e09e
chore(core): fix model intent (#1474)
yuyutaotao Nov 18, 2025
8aab4e7
chore(core): throw error when failed to locate in qwen (#1478)
yuyutaotao Nov 19, 2025
dd2cfad
feat(shared): unify midscene family env (#1477)
quanru Nov 19, 2025
e421345
docs(site): standardize model configuration parameters (#1475)
quanru Nov 19, 2025
f819778
feat(web): add navigator actions to web action space (#1479)
quanru Nov 19, 2025
a587abd
feat(web): add navigator support for chrome extension (#1482)
quanru Nov 19, 2025
21e011a
feat(web): restore aiAction fixture with deprecation notice (#1484)
quanru Nov 19, 2025
8b2ff8b
feat(report): add timeout status support in report overview (#1483)
quanru Nov 19, 2025
dcd4e47
feat(playground): add device options configuration for Android/iOS (#…
quanru Nov 20, 2025
b24d76f
fix(report): fix screenshot not displaying when recorder is empty (#1…
quanru Nov 20, 2025
96e6bd2
feat(core): add automatic LangSmith and Langfuse integration (#1487)
quanru Nov 20, 2025
4e4a050
feat(report): improve UI display and simplify task output structure (…
quanru Nov 21, 2025
472523a
fix(playwright): fix this binding issue in AI fixture declarative cal…
quanru Nov 21, 2025
c1c4f7c
feat(site): enhance feature sections with updated models and APIs (#1…
quanru Nov 21, 2025
c7c8cd2
feat(report): add per-model token statistics in sidebar (#1493)
quanru Nov 21, 2025
dd06ad6
fix(chrome-extension): add awaitPromise: true to evaluateJavaScript (…
quanru Nov 24, 2025
ab07218
refactor(1.0): expose action space into mcp (#1481)
yuyutaotao Nov 24, 2025
143837c
feat(core): add image history into conversation (#1496)
yuyutaotao Nov 24, 2025
dd5de4d
docs(core): update homepage
yuyutaotao Nov 24, 2025
13b6283
fix(chrome-extension): auto-reattach debugger after cross-origin navi…
quanru Nov 24, 2025
2796307
fix(core): prevent [object Object] in progress descriptions (#1499)
quanru Nov 24, 2025
a13236e
refactor(shared): extract common rspack ignoreWarnings config (#1500)
quanru Nov 25, 2025
9dc8fa1
feat(site): enhance homepage with interactive model cards and layout …
quanru Nov 25, 2025
0a2c594
docs(core): introduce gemini-3 (#1502)
yuyutaotao Nov 25, 2025
6e99353
fix(visualizer): lowercase intent and add planning prefix in model br…
quanru Nov 25, 2025
f897f40
chore(core): upgrade zod from 3.24.3 to 3.25.0 (#1504)
quanru Nov 25, 2025
6385133
refactor(core): replace @langchain/core with native template literals…
quanru Nov 25, 2025
8183650
fix(core): planning cache (#1505)
yuyutaotao Nov 25, 2025
ceefaf3
fix(core): allow retry when having error in plan
yuyutaotao Nov 26, 2025
0e3c2e3
fix(web): fix the drag and drop action (#1509)
dorahappy Nov 26, 2025
a8cfb1a
chore(core): fix history log
yuyutaotao Nov 26, 2025
57a4779
Merge branch 'feat/retry-error' into v1
yuyutaotao Nov 26, 2025
96a78f4
chore(core): export types of agent option
yuyutaotao Nov 26, 2025
081ee4b
fix(core): read cached token usage (#1513)
yuyutaotao Nov 27, 2025
442f11d
Clarify replanning option guidance (#1514)
yuyutaotao Nov 27, 2025
2fc036d
feat(report): add monospace font and dynamic column widths for statis…
quanru Nov 28, 2025
9a3f5d9
fix(core): preserve uiContext and log in _unstableLogContent method (…
quanru Nov 28, 2025
d3273e4
feat(web): add forceChromeSelectRendering option (#1532)
EAGzzyCSL Dec 2, 2025
0671413
docs(core): docs for web and ios (#1533)
yuyutaotao Dec 2, 2025
83219bd
fix(core): validate yamlWorkflow before executing cached aiAction pla…
quanru Dec 2, 2025
a94dd07
feat(cli): add full agent options support to YAML scripts (#1526)
quanru Dec 2, 2025
3526d48
feat(core): add actionContext support to uiTarsPlanning (#1531)
quanru Dec 2, 2025
d1c12a2
feat(web-integration): add chromeArgs support for YAML scripts (#1528)
quanru Dec 2, 2025
f70fab8
docs(core): update docs for command line tools (#1535)
yuyutaotao Dec 2, 2025
6482aa6
refactor(android-playground): refactor getAdbDevices to use getConnec…
lhuanyu Dec 2, 2025
2ff7492
fix error "playwright/package.json" needs an import attribute of type…
EAGzzyCSL Dec 2, 2025
630b308
fix(core): add missing left_double and right_single action handlers f…
quanru Dec 3, 2025
ecb5d82
fix(core): add error handling for xpath fallback to AI locate (#1539)
quanru Dec 3, 2025
8524604
feat(core): add AI API timeout configuration support (#1529)
quanru Dec 3, 2025
5180066
fix(shared): disable chunk splitting for IIFE build to fix window.mid…
quanru Dec 3, 2025
719782e
ci(workflow): update branch reference from 1.0 to v1 (#1544)
quanru Dec 4, 2025
c412ff4
test(shared): add unit tests for IIFE bundle runtime behavior (#1545)
quanru Dec 4, 2025
bd10032
feat(core): _deepThink option in yaml (#1523)
EAGzzyCSL Dec 4, 2025
e4ef0aa
fix(core): print a brief for planning steps (#1542)
yuyutaotao Dec 4, 2025
c0e4537
fix(report): fix timeline screenshot collection to include uiContext …
quanru Dec 4, 2025
8818dbf
docs(site): add midscene-java to awesome midscene lists
stuffJr Nov 28, 2025
a966195
Revert "docs(site): add midscene-java to awesome midscene lists"
quanru Dec 4, 2025
8108ccf
docs(site): add second Java SDK (by @alstafeev) to awesome list (#1547)
quanru Dec 4, 2025
5b4e288
fix(core): fix the assertion in planning (#1548)
yuyutaotao Dec 4, 2025
11596ba
fix(core): error handling for aiAct (#1549)
yuyutaotao Dec 4, 2025
030be90
chore(core): add some sample for planning response
yuyutaotao Dec 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
pull_request:
branches:
- main
- "v1"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
pull_request:
branches:
- main
- "v1"

permissions:
contents: read
Expand Down Expand Up @@ -49,4 +50,3 @@ jobs:

- name: Biome lint
run: npx biome check . --diagnostic-level=warn --no-errors-on-unmatched

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ midscene_run/dump
*.ignore.png
extension_output
.cursor
apps/chrome-extension/web-ext-profile
packages/android-playground/static/
packages/ios-playground/static/
packages/ios/static/
Expand All @@ -121,7 +122,7 @@ CLAUDE.md
.claude
**/.claude
**/CLAUDE.md
AGENTS.md

.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md
.gemini-clipboard
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ To change the AI-related code of this repository, you need to create a '.env 'fi

```
OPENAI_API_KEY="your_token"
MIDSCENE_MODEL_NAME="gpt-4o-2024-08-06"
MIDSCENE_MODEL_NAME="qwen3-vl-plus"
```


Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Read more about [Choose a model](https://midscenejs.com/choose-a-model)
Midscene will automatically plan the steps and execute them. It may be slower and heavily rely on the quality of the AI model.

```javascript
await aiAction('click all the records one by one. If one record contains the text "completed", skip it');
await aiAct('click all the records one by one. If one record contains the text "completed", skip it');
```

### Workflow Style
Expand Down Expand Up @@ -131,6 +131,8 @@ Community projects that extend Midscene.js capabilities:

* [midscene-ios](https://github.com/lhuanyu/midscene-ios) - iOS automation support for Midscene
* [Midscene-Python](https://github.com/Python51888/Midscene-Python) - Python SDK for Midscene automation
* [midscene-java](https://github.com/Master-Frank/midscene-java) by @Master-Frank - Java SDK that brings Midscene automation features to JVM projects
* [midscene-java](https://github.com/alstafeev/midscene-java) by @alstafeev - Java SDK for Midscene automation


## 📝 Credits
Expand Down
4 changes: 3 additions & 1 deletion README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Midscene.js 支持视觉语言模型,例如 `Qwen3-VL`、`Doubao-1.6-vision`
Midscene 会自动规划步骤并执行。它可能较慢,并且深度依赖于 AI 模型的质量。

```javascript
await aiAction('click all the records one by one. If one record contains the text "completed", skip it');
await aiAct('click all the records one by one. If one record contains the text "completed", skip it');
```

### 工作流风格
Expand Down Expand Up @@ -133,6 +133,8 @@ for (const record of recordList) {

* [midscene-ios](https://github.com/lhuanyu/midscene-ios) - iOS 设备自动化工具
* [Midscene-Python](https://github.com/Python51888/Midscene-Python) - Python 版本的 Midscene SDK
* [midscene-java](https://github.com/Master-Frank/midscene-java) by @Master-Frank - Java 版本的 Midscene SDK,便于在 JVM 项目中使用自动化能力
* [midscene-java](https://github.com/alstafeev/midscene-java) by @alstafeev - Java SDK,用于 Midscene 自动化

## 📝 致谢

Expand Down
12 changes: 6 additions & 6 deletions apps/android-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
"socket.io-client": "4.8.1"
},
"devDependencies": {
"@rsbuild/core": "^1.3.22",
"@rsbuild/plugin-less": "^1.2.4",
"@rsbuild/plugin-node-polyfill": "1.3.0",
"@rsbuild/plugin-react": "^1.3.1",
"@rsbuild/plugin-svgr": "^1.1.1",
"@rsbuild/plugin-type-check": "1.2.3",
"@rsbuild/core": "^1.5.17",
"@rsbuild/plugin-less": "^1.5.0",
"@rsbuild/plugin-node-polyfill": "1.4.2",
"@rsbuild/plugin-react": "^1.4.1",
"@rsbuild/plugin-svgr": "^1.2.2",
"@rsbuild/plugin-type-check": "1.2.4",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.1",
"archiver": "^6.0.0",
Expand Down
10 changes: 9 additions & 1 deletion apps/android-playground/rsbuild.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import path from 'node:path';
import { createPlaygroundCopyPlugin } from '@midscene/shared';
import {
commonIgnoreWarnings,
createPlaygroundCopyPlugin,
} from '@midscene/shared';
import { defineConfig } from '@rsbuild/core';
import { pluginLess } from '@rsbuild/plugin-less';
import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill';
Expand All @@ -9,6 +12,11 @@ import { pluginTypeCheck } from '@rsbuild/plugin-type-check';
import { version as playgroundVersion } from '../../packages/playground/package.json';

export default defineConfig({
tools: {
rspack: {
ignoreWarnings: commonIgnoreWarnings,
},
},
environments: {
web: {
source: {
Expand Down
46 changes: 40 additions & 6 deletions apps/android-playground/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import './App.less';
import { SCRCPY_SERVER_PORT } from '@midscene/shared/constants';
import {
PLAYGROUND_SERVER_PORT,
SCRCPY_SERVER_PORT,
} from '@midscene/shared/constants';
import {
ScreenshotViewer,
globalThemeConfig,
safeOverrideAIConfig,
useEnvConfig,
Expand All @@ -17,6 +21,13 @@ import ScrcpyPlayer, {

const { Content } = Layout;

// Helper function to detect if device is remote (IP:Port format)
const isRemoteDevice = (deviceId: string | null): boolean => {
if (!deviceId) return false;
// Remote device format: IP:Port (e.g., 192.168.1.10:5555)
return /^\d+\.\d+\.\d+\.\d+:\d+$/.test(deviceId);
};

export default function App() {
// Device and connection state - now simplified since device is pre-selected
const [selectedDeviceId, setSelectedDeviceId] = useState<string | null>(null);
Expand All @@ -26,6 +37,7 @@ export default function App() {
`http://localhost:${SCRCPY_SERVER_PORT}`,
);
const [isNarrowScreen, setIsNarrowScreen] = useState(false);
const [usePollingMode, setUsePollingMode] = useState(false);

// Configuration state
const { config } = useEnvConfig();
Expand Down Expand Up @@ -125,6 +137,11 @@ export default function App() {
return () => window.removeEventListener('resize', handleResize);
}, []);

// Detect if device is remote and switch to polling mode
useEffect(() => {
setUsePollingMode(isRemoteDevice(selectedDeviceId));
}, [selectedDeviceId]);

return (
<ConfigProvider theme={globalThemeConfig()}>
{contextHolder}
Expand Down Expand Up @@ -157,11 +174,28 @@ export default function App() {
selectedDeviceId={selectedDeviceId}
scrcpyPlayerRef={scrcpyPlayerRef}
/>
<ScrcpyPlayer
ref={scrcpyPlayerRef}
serverUrl={serverUrl}
autoConnect={connectToDevice}
/>
{!usePollingMode ? (
<ScrcpyPlayer
ref={scrcpyPlayerRef}
serverUrl={serverUrl}
autoConnect={connectToDevice}
/>
) : (
<ScreenshotViewer
getScreenshot={() =>
fetch(
`http://localhost:${PLAYGROUND_SERVER_PORT}/screenshot`,
).then((r) => r.json())
}
getInterfaceInfo={() =>
fetch(
`http://localhost:${PLAYGROUND_SERVER_PORT}/interface-info`,
).then((r) => r.json())
}
serverOnline={true}
isUserOperating={false}
/>
)}
</div>
</Panel>
</PanelGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export default function PlaygroundPanel() {
enableScrollToBottom: true,
serverMode: true,
showEnvConfigReminder: true,
deviceType: 'android',
}}
branding={{
title: 'Android Playground',
Expand Down
20 changes: 11 additions & 9 deletions apps/chrome-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"type": "module",
"scripts": {
"build": "rsbuild build && npm run pack-extension",
"dev": "rsbuild dev --open",
"dev": "concurrently -k -n build,run \"rsbuild dev\" \"node scripts/wait-for-build.js && web-ext run --config web-ext-config.cjs --source-dir dist --target chromium\"",
"dev:simple": "rsbuild dev --open",
"preview": "rsbuild preview",
"pack-extension": "node scripts/pack-extension.js"
},
Expand All @@ -18,7 +19,6 @@
"@midscene/shared": "workspace:*",
"@midscene/visualizer": "workspace:*",
"@midscene/web": "workspace:*",

"@types/file-saver": "2.0.7",
"antd": "^5.21.6",
"canvas-confetti": "1.9.3",
Expand All @@ -32,20 +32,22 @@
"zustand": "4.5.2"
},
"devDependencies": {
"@rsbuild/core": "^1.3.22",
"@rsbuild/plugin-less": "^1.2.4",
"@rsbuild/plugin-node-polyfill": "1.3.0",
"@rsbuild/plugin-react": "^1.3.1",
"@rsbuild/plugin-svgr": "^1.1.1",
"@rsbuild/plugin-type-check": "1.2.3",
"@rsbuild/core": "^1.5.17",
"@rsbuild/plugin-less": "^1.5.0",
"@rsbuild/plugin-node-polyfill": "1.4.2",
"@rsbuild/plugin-react": "^1.4.1",
"@rsbuild/plugin-svgr": "^1.2.2",
"@rsbuild/plugin-type-check": "1.2.4",
"@tailwindcss/postcss": "4.1.11",
"@types/chrome": "0.0.279",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.1",
"archiver": "^6.0.0",
"concurrently": "^8.2.0",
"less": "^4.2.0",
"openai": "6.3.0",
"tailwindcss": "4.1.11",
"typescript": "^5.8.3",
"openai": "4.81.0"
"web-ext": "9.0.0"
}
}
11 changes: 10 additions & 1 deletion apps/chrome-extension/rsbuild.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import path from 'node:path';
import { commonIgnoreWarnings } from '@midscene/shared';
import { defineConfig } from '@rsbuild/core';
import { pluginLess } from '@rsbuild/plugin-less';
import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill';
Expand All @@ -11,8 +12,15 @@ export default defineConfig({
tools: {
rspack: {
watchOptions: {
ignored: /\.git/,
ignored: [
'**/.git/**',
'**/web-ext-profile/**',
'**/extension_output/**',
'dist/**', // Only ignore THIS app's dist folder, not workspace packages
'**/node_modules/**',
],
},
ignoreWarnings: commonIgnoreWarnings,
},
},
environments: {
Expand Down Expand Up @@ -48,6 +56,7 @@ export default defineConfig({
},
dev: {
writeToDisk: true,
lazyCompilation: false, // Disable lazy compilation for Chrome extension compatibility
},
output: {
polyfill: 'entry',
Expand Down
59 changes: 59 additions & 0 deletions apps/chrome-extension/scripts/wait-for-build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env node

import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const manifestPath = path.resolve(__dirname, '../dist/manifest.json');
const indexHtmlPath = path.resolve(__dirname, '../dist/index.html');
const indexJsPath = path.resolve(__dirname, '../dist/static/js/index.js');
const popupJsPath = path.resolve(__dirname, '../dist/static/js/popup.js');
const maxWaitTime = 60000; // 60 seconds
const checkInterval = 500; // 500ms
const stabilityWait = 1000; // Wait 1 second after detection to ensure files are stable

let elapsed = 0;

console.log('Waiting for initial build to complete...');

const checkBuildComplete = () => {
const manifestExists = fs.existsSync(manifestPath);
const indexExists = fs.existsSync(indexHtmlPath);
const indexJsExists = fs.existsSync(indexJsPath);
const popupJsExists = fs.existsSync(popupJsPath);

if (manifestExists && indexExists && indexJsExists && popupJsExists) {
// Wait a bit more to ensure all files are written
console.log('Build files detected, waiting for stability...');
setTimeout(() => {
// Double check the files still exist
if (
fs.existsSync(manifestPath) &&
fs.existsSync(indexHtmlPath) &&
fs.existsSync(indexJsPath) &&
fs.existsSync(popupJsPath)
) {
console.log('Build complete! Starting web-ext...');
process.exit(0);
} else {
console.log('Build files disappeared, continuing to wait...');
setTimeout(checkBuildComplete, checkInterval);
}
}, stabilityWait);
return;
}

elapsed += checkInterval;

if (elapsed >= maxWaitTime) {
console.error('Timeout waiting for build to complete');
process.exit(1);
}

setTimeout(checkBuildComplete, checkInterval);
};

checkBuildComplete();
Loading
Loading