@fugood/bricks-project 2.25.0-beta.39 → 2.25.0-beta.40
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/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fugood/bricks-project",
|
|
3
|
-
"version": "2.25.0-beta.
|
|
3
|
+
"version": "2.25.0-beta.40",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"typecheck": "tsc --noEmit",
|
|
7
7
|
"build": "bun scripts/build.js"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@fugood/bricks-cli": "^2.25.0-beta.
|
|
10
|
+
"@fugood/bricks-cli": "^2.25.0-beta.40",
|
|
11
11
|
"@huggingface/gguf": "^0.3.2",
|
|
12
12
|
"@iarna/toml": "^3.0.0",
|
|
13
13
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
@@ -24,5 +24,6 @@
|
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"oxfmt": "^0.36.0"
|
|
27
|
-
}
|
|
27
|
+
},
|
|
28
|
+
"gitHead": "4ad8588eed6f0161b0aa66d863a36e6c623c4a83"
|
|
28
29
|
}
|
package/package.json.bak
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fugood/bricks-ctor",
|
|
3
|
-
"version": "2.25.0-beta.
|
|
3
|
+
"version": "2.25.0-beta.40",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"typecheck": "tsc --noEmit",
|
|
7
7
|
"build": "bun scripts/build.js"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@fugood/bricks-cli": "^2.25.0-beta.
|
|
10
|
+
"@fugood/bricks-cli": "^2.25.0-beta.40",
|
|
11
11
|
"@huggingface/gguf": "^0.3.2",
|
|
12
12
|
"@iarna/toml": "^3.0.0",
|
|
13
13
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
@@ -24,5 +24,6 @@
|
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"oxfmt": "^0.36.0"
|
|
27
|
-
}
|
|
27
|
+
},
|
|
28
|
+
"gitHead": "4ad8588eed6f0161b0aa66d863a36e6c623c4a83"
|
|
28
29
|
}
|
|
@@ -9,6 +9,23 @@ What the Simulator can and can't faithfully reproduce — so a passing Simulator
|
|
|
9
9
|
|
|
10
10
|
A Simulator screenshot proves **layout, navigation, Standby Transitions, Data wiring, and generator/Automation wiring**. It does *not* prove anything that depends on real hardware, real models, or capabilities the preview runtime lacks.
|
|
11
11
|
|
|
12
|
+
## Automation screenshots
|
|
13
|
+
|
|
14
|
+
`match_screenshot` stores Simulator automation artifacts at the project level:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
.bricks/automation_screenshots/
|
|
18
|
+
last/
|
|
19
|
+
failed/
|
|
20
|
+
diff/
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
There is no application-id subdirectory; in CTOR the project is the application. Generated project `.gitignore` files exclude this directory.
|
|
24
|
+
|
|
25
|
+
When a `match_screenshot` baseline is missing or updated, the baseline goes under `last/`. When a screenshot mismatch occurs, the current capture goes under `failed/` and the pixel diff goes under `diff/`. File names follow `<screenshotName>+local+<timestamp>.png`.
|
|
26
|
+
|
|
27
|
+
In CTOR Desktop, `simulator_invoke` reports any automation screenshot files created or changed by the invocation in an `Automation screenshots:` section. It still separately reports the ordinary preview capture at `.bricks/simulator-screenshot.jpg`.
|
|
28
|
+
|
|
12
29
|
## What the Simulator can't reproduce
|
|
13
30
|
|
|
14
31
|
Because it runs in a browser-class preview rather than on device hardware, the Simulator cannot exercise these — a green run says nothing about them. Verify on a real device (Path 2):
|
package/tools/simulator-main.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
-
import { app, BrowserWindow } from 'electron'
|
|
3
|
-
import { readFile, writeFile } from 'fs/promises'
|
|
2
|
+
import { app, BrowserWindow, ipcMain } from 'electron'
|
|
3
|
+
import { mkdir, readdir, readFile, rm, writeFile } from 'fs/promises'
|
|
4
4
|
import { watchFile } from 'fs'
|
|
5
5
|
import { createServer } from 'http'
|
|
6
|
+
import path from 'node:path'
|
|
7
|
+
import { fileURLToPath } from 'node:url'
|
|
6
8
|
import { parseArgs } from 'util'
|
|
7
9
|
import * as TOON from '@toon-format/toon'
|
|
8
10
|
|
|
@@ -28,12 +30,70 @@ const { values } = parseArgs({
|
|
|
28
30
|
})
|
|
29
31
|
|
|
30
32
|
const cwd = process.cwd()
|
|
33
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
34
|
+
const AUTOMATION_SCREENSHOT_PROJECT_DIR = path.join('.bricks', 'automation_screenshots')
|
|
31
35
|
const DEFAULT_SIMULATOR_SECURITY_SETTINGS = Object.freeze({
|
|
32
36
|
allowedInsecureHosts: [],
|
|
33
37
|
})
|
|
34
38
|
|
|
35
39
|
const isObject = (value) => !!value && typeof value === 'object' && !Array.isArray(value)
|
|
36
40
|
|
|
41
|
+
const resolveAutomationScreenshotPath = (requestedPath = '') => {
|
|
42
|
+
const baseDir = path.resolve(cwd, AUTOMATION_SCREENSHOT_PROJECT_DIR)
|
|
43
|
+
const raw = String(requestedPath || AUTOMATION_SCREENSHOT_PROJECT_DIR)
|
|
44
|
+
const fromProject = path.resolve(cwd, raw)
|
|
45
|
+
const target =
|
|
46
|
+
fromProject === baseDir || fromProject.startsWith(`${baseDir}${path.sep}`)
|
|
47
|
+
? fromProject
|
|
48
|
+
: path.resolve(baseDir, raw)
|
|
49
|
+
|
|
50
|
+
if (target !== baseDir && !target.startsWith(`${baseDir}${path.sep}`)) {
|
|
51
|
+
throw new Error('Automation screenshot path must stay inside the project screenshot directory.')
|
|
52
|
+
}
|
|
53
|
+
return target
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const normalizeAutomationScreenshotEncoding = (encoding) =>
|
|
57
|
+
encoding === 'base64' ? 'base64' : 'utf8'
|
|
58
|
+
|
|
59
|
+
const registerAutomationScreenshotIpc = () => {
|
|
60
|
+
ipcMain.handle('bricks-automation-screenshots:exists', async (_event, filePath) => {
|
|
61
|
+
try {
|
|
62
|
+
await readFile(resolveAutomationScreenshotPath(filePath))
|
|
63
|
+
return true
|
|
64
|
+
} catch {
|
|
65
|
+
return false
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
ipcMain.handle('bricks-automation-screenshots:readdir', async (_event, dirPath) => {
|
|
69
|
+
try {
|
|
70
|
+
return await readdir(resolveAutomationScreenshotPath(dirPath))
|
|
71
|
+
} catch {
|
|
72
|
+
return []
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
ipcMain.handle('bricks-automation-screenshots:mkdir', async (_event, dirPath) => {
|
|
76
|
+
await mkdir(resolveAutomationScreenshotPath(dirPath), { recursive: true })
|
|
77
|
+
})
|
|
78
|
+
ipcMain.handle('bricks-automation-screenshots:unlink', async (_event, filePath) => {
|
|
79
|
+
await rm(resolveAutomationScreenshotPath(filePath), { recursive: true, force: true })
|
|
80
|
+
})
|
|
81
|
+
ipcMain.handle('bricks-automation-screenshots:read-file', async (_event, filePath, encoding) =>
|
|
82
|
+
readFile(
|
|
83
|
+
resolveAutomationScreenshotPath(filePath),
|
|
84
|
+
normalizeAutomationScreenshotEncoding(encoding),
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
ipcMain.handle(
|
|
88
|
+
'bricks-automation-screenshots:write-file',
|
|
89
|
+
async (_event, filePath, contents, encoding) => {
|
|
90
|
+
const target = resolveAutomationScreenshotPath(filePath)
|
|
91
|
+
await mkdir(path.dirname(target), { recursive: true })
|
|
92
|
+
await writeFile(target, contents, normalizeAutomationScreenshotEncoding(encoding))
|
|
93
|
+
},
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
37
97
|
const normalizeSimulatorSecuritySettings = (settings = {}) => {
|
|
38
98
|
const source = isObject(settings) ? settings : {}
|
|
39
99
|
const allowedHosts = Array.isArray(source.allowedInsecureHosts)
|
|
@@ -289,6 +349,7 @@ const startCdpServer = async (mainWindow, port) => {
|
|
|
289
349
|
}
|
|
290
350
|
|
|
291
351
|
app.on('ready', () => {
|
|
352
|
+
registerAutomationScreenshotIpc()
|
|
292
353
|
let show = true
|
|
293
354
|
if (takeScreenshotConfig && !takeScreenshotConfig.noHeadless) show = false
|
|
294
355
|
const mainWindow = new BrowserWindow({
|
|
@@ -296,6 +357,11 @@ app.on('ready', () => {
|
|
|
296
357
|
height: takeScreenshotConfig?.height || 768,
|
|
297
358
|
frame: !takeScreenshotConfig,
|
|
298
359
|
show,
|
|
360
|
+
webPreferences: {
|
|
361
|
+
preload: path.join(__dirname, 'simulator-preload.cjs'),
|
|
362
|
+
contextIsolation: true,
|
|
363
|
+
nodeIntegration: false,
|
|
364
|
+
},
|
|
299
365
|
})
|
|
300
366
|
mainWindow.setBackgroundColor('#333')
|
|
301
367
|
mainWindow.webContents.session.webRequest.onBeforeRequest(
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const { contextBridge, ipcRenderer } = require('electron')
|
|
2
|
+
|
|
3
|
+
const AUTOMATION_SCREENSHOT_ROOT = '.bricks/automation_screenshots'
|
|
4
|
+
|
|
5
|
+
contextBridge.exposeInMainWorld('BRICKS_AUTOMATION_SCREENSHOTS', {
|
|
6
|
+
rootDir: AUTOMATION_SCREENSHOT_ROOT,
|
|
7
|
+
exists: (filePath) => ipcRenderer.invoke('bricks-automation-screenshots:exists', filePath),
|
|
8
|
+
readdir: (dirPath) => ipcRenderer.invoke('bricks-automation-screenshots:readdir', dirPath),
|
|
9
|
+
readDir: (dirPath) => ipcRenderer.invoke('bricks-automation-screenshots:readdir', dirPath),
|
|
10
|
+
mkdir: (dirPath) => ipcRenderer.invoke('bricks-automation-screenshots:mkdir', dirPath),
|
|
11
|
+
unlink: (filePath) => ipcRenderer.invoke('bricks-automation-screenshots:unlink', filePath),
|
|
12
|
+
readFile: (filePath, encoding) =>
|
|
13
|
+
ipcRenderer.invoke('bricks-automation-screenshots:read-file', filePath, encoding),
|
|
14
|
+
writeFile: (filePath, contents, encoding) =>
|
|
15
|
+
ipcRenderer.invoke('bricks-automation-screenshots:write-file', filePath, contents, encoding),
|
|
16
|
+
})
|