@fugood/bricks-project 2.25.0-beta.23 → 2.25.0-beta.25
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/compile/index.ts +3 -1
- package/package.json +2 -2
- package/package.json.bak +2 -2
- package/skills/bricks-ctor/rules/automations.md +11 -0
- package/utils/id.ts +78 -27
package/compile/index.ts
CHANGED
|
@@ -1460,5 +1460,7 @@ export const compile = async (app: Application) => {
|
|
|
1460
1460
|
|
|
1461
1461
|
export const checkConfig = async (configPath: string) => {
|
|
1462
1462
|
const { sh } = await import('../tools/_shell')
|
|
1463
|
-
|
|
1463
|
+
// --validate-automation surfaces broken automation_map / test_map refs early,
|
|
1464
|
+
// which catches agent-authored automations that reference deleted bricks.
|
|
1465
|
+
await sh`bricks app check-config --validate-automation ${configPath}`
|
|
1464
1466
|
}
|
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.25",
|
|
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.25",
|
|
11
11
|
"@huggingface/gguf": "^0.3.2",
|
|
12
12
|
"@iarna/toml": "^3.0.0",
|
|
13
13
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
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.25",
|
|
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.25",
|
|
11
11
|
"@huggingface/gguf": "^0.3.2",
|
|
12
12
|
"@iarna/toml": "^3.0.0",
|
|
13
13
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
@@ -118,6 +118,16 @@ const testLoginFlow: AutomationTest = {
|
|
|
118
118
|
| `match_screenshot` | `[name, threshold?, maxRetry?]` | Screenshot compare |
|
|
119
119
|
| `delay` | `[subspace?, property?, defaultValue?]` | Delay execution |
|
|
120
120
|
|
|
121
|
+
In project TypeScript source, pass entity getters for BRICKS entities:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
run: ['brick_press', () => mainSubspace, () => bricks.bSubmitButton]
|
|
125
|
+
run: ['wait_until_canvas_change', () => mainSubspace, () => canvases.cDone, 5000]
|
|
126
|
+
run: ['assert_property', () => mainSubspace, () => data.dStep, 'done']
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The compiler resolves these getters to the current generated IDs.
|
|
130
|
+
|
|
121
131
|
### execute_action Params
|
|
122
132
|
|
|
123
133
|
The `params` object in `execute_action` uses **runtime event property keys** from `event-props.ts`, NOT the action config `input` names from type definitions.
|
|
@@ -208,6 +218,7 @@ Automations work with Modules. Use Manual Run in Preview mode for module testing
|
|
|
208
218
|
|
|
209
219
|
- **Automation map key**: Always use `'AUTOMATION_MAP_DEFAULT'` as the automation map ID (not `makeId()`). The preview test runner reads from `automationMap['AUTOMATION_MAP_DEFAULT']?.map`.
|
|
210
220
|
- **Valid makeId types**: Use `'test'` for AutomationTest, `'test_case'` for TestCase, `'test_var'` for TestVariable. Do NOT use `'automation_test'` or `'automation_test_map'`.
|
|
221
|
+
- **Entity references in run arrays**: Use getter references (`() => subspace`, `() => bricks.bButton`, `() => data.dValue`) in TypeScript source so compile resolves fresh IDs.
|
|
211
222
|
- **handler in execute_action**: Pass the entity's `.id` string (e.g., `bricks.bInput.id`), not a getter function.
|
|
212
223
|
|
|
213
224
|
## Best Practices
|
package/utils/id.ts
CHANGED
|
@@ -1,38 +1,83 @@
|
|
|
1
1
|
import { v4 as uuid } from 'uuid'
|
|
2
|
+
import { createHash } from 'node:crypto'
|
|
3
|
+
import { readFileSync } from 'node:fs'
|
|
4
|
+
import { join } from 'node:path'
|
|
2
5
|
|
|
3
6
|
let count = 0
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
type IdType =
|
|
9
|
+
| 'animation'
|
|
10
|
+
| 'brick'
|
|
11
|
+
| 'canvas'
|
|
12
|
+
| 'generator'
|
|
13
|
+
| 'data'
|
|
14
|
+
| 'switch'
|
|
15
|
+
| 'property_bank_command'
|
|
16
|
+
| 'property_bank_calc'
|
|
17
|
+
| 'dynamic-brick'
|
|
18
|
+
| 'automation_map'
|
|
19
|
+
| 'test'
|
|
20
|
+
| 'test_case'
|
|
21
|
+
| 'test_var'
|
|
22
|
+
| 'subspace'
|
|
23
|
+
|
|
24
|
+
type IdOptions = {
|
|
25
|
+
snapshotMode?: boolean
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const APPLICATION_ID_FALLBACK = 'unknown-application'
|
|
29
|
+
|
|
30
|
+
const usedStableAliases = new Set<string>()
|
|
31
|
+
let applicationIdCache: { cwd: string; id: string } | null = null
|
|
32
|
+
|
|
33
|
+
const readApplicationId = () => {
|
|
34
|
+
const cwd = process.cwd()
|
|
35
|
+
if (applicationIdCache?.cwd === cwd) return applicationIdCache.id
|
|
36
|
+
|
|
37
|
+
let id = APPLICATION_ID_FALLBACK
|
|
38
|
+
try {
|
|
39
|
+
const app = JSON.parse(readFileSync(join(cwd, 'application.json'), 'utf8'))
|
|
40
|
+
if (typeof app.id === 'string' && app.id) id = app.id
|
|
41
|
+
} catch {
|
|
42
|
+
// `makeId` is also used from tests and utilities outside project roots.
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
applicationIdCache = { cwd, id }
|
|
46
|
+
return id
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const hashToRandomBytes = (parts: string[]) => {
|
|
50
|
+
const hash = createHash('sha256').update(JSON.stringify(parts)).digest()
|
|
51
|
+
return new Uint8Array(hash.subarray(0, 16))
|
|
10
52
|
}
|
|
11
53
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
) => {
|
|
54
|
+
const makeStableUuid = (type: string, alias?: string) => {
|
|
55
|
+
const applicationId = readApplicationId()
|
|
56
|
+
const seed = alias ?? String(count)
|
|
57
|
+
if (alias === undefined) count += 1
|
|
58
|
+
|
|
59
|
+
if (alias !== undefined) {
|
|
60
|
+
const aliasKey = JSON.stringify([applicationId, type, alias])
|
|
61
|
+
if (usedStableAliases.has(aliasKey)) {
|
|
62
|
+
throw new Error(`Duplicate makeId alias '${alias}' for type '${type}'`)
|
|
63
|
+
}
|
|
64
|
+
usedStableAliases.add(aliasKey)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return uuid({
|
|
68
|
+
random: hashToRandomBytes([applicationId, type, seed]),
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Make stable ids by default; explicit snapshotMode: false preserves the random escape hatch.
|
|
73
|
+
export const makeId = (type: IdType, aliasOrOpts?: string | IdOptions, opts?: IdOptions) => {
|
|
33
74
|
if (type === 'subspace') {
|
|
34
75
|
throw new Error('Currently subspace is not supported for ID generation, please use a fixed ID')
|
|
35
76
|
}
|
|
77
|
+
|
|
78
|
+
const alias = typeof aliasOrOpts === 'string' ? aliasOrOpts : undefined
|
|
79
|
+
const options = typeof aliasOrOpts === 'string' ? opts : (aliasOrOpts ?? opts)
|
|
80
|
+
|
|
36
81
|
let prefix = ''
|
|
37
82
|
switch (type) {
|
|
38
83
|
case 'animation':
|
|
@@ -76,5 +121,11 @@ export const makeId = (
|
|
|
76
121
|
break
|
|
77
122
|
default:
|
|
78
123
|
}
|
|
79
|
-
|
|
124
|
+
|
|
125
|
+
const useCountFallback = aliasOrOpts === undefined && opts === undefined
|
|
126
|
+
const id =
|
|
127
|
+
alias !== undefined || options?.snapshotMode || useCountFallback
|
|
128
|
+
? makeStableUuid(type, alias)
|
|
129
|
+
: uuid()
|
|
130
|
+
return `${prefix}${id}`
|
|
80
131
|
}
|