@fugood/bricks-project 2.25.0-beta.40 → 2.25.0-beta.42
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/action-name-map.ts +1 -0
- package/package.json +2 -2
- package/package.json.bak +2 -2
- package/skills/bricks-ctor/SKILL.md +1 -1
- package/skills/bricks-ctor/references/data-calculation.md +141 -111
- package/skills/bricks-ctor/references/simulator.md +17 -1
- package/skills/bricks-design/SKILL.md +14 -24
- package/skills/bricks-ux/SKILL.md +14 -20
- package/types/bricks/Scene3D.d.ts +83 -3
- package/types/data-calc-command/sandbox.d.ts +10 -2
|
@@ -371,6 +371,7 @@ export const templateActionNameMap = {
|
|
|
371
371
|
objectScale: 'BRICK_SCENE_3D_OBJECT_SCALE',
|
|
372
372
|
objectVisible: 'BRICK_SCENE_3D_OBJECT_VISIBLE',
|
|
373
373
|
objectColor: 'BRICK_SCENE_3D_OBJECT_COLOR',
|
|
374
|
+
objectNodes: 'BRICK_SCENE_3D_OBJECT_NODES',
|
|
374
375
|
},
|
|
375
376
|
BRICK_SCENE_3D_SET_CAMERA: {
|
|
376
377
|
cameraPosition: 'BRICK_SCENE_3D_CAMERA_POSITION',
|
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.42",
|
|
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.42",
|
|
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.42",
|
|
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.42",
|
|
11
11
|
"@huggingface/gguf": "^0.3.2",
|
|
12
12
|
"@iarna/toml": "^3.0.0",
|
|
13
13
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
@@ -15,7 +15,7 @@ This skill covers advanced BRICKS features not in the main project instructions.
|
|
|
15
15
|
| [Animation](references/animation.md) | Animation system for brick transforms and opacity |
|
|
16
16
|
| [Standby Transition](references/standby-transition.md) | Canvas enter/exit animations |
|
|
17
17
|
| [Automations](references/automations.md) | E2E testing and scheduled tasks |
|
|
18
|
-
| [Data Calculation](references/data-calculation.md) | JS sandbox
|
|
18
|
+
| [Data Calculation](references/data-calculation.md) | Wiring contract, trigger semantics, JS sandbox (25+ libraries) |
|
|
19
19
|
| [Local Sync](references/local-sync.md) | LAN device synchronization |
|
|
20
20
|
| [Remote Data Bank](references/remote-data-bank.md) | Cloud data sync and API access |
|
|
21
21
|
| [Media Flow](references/media-flow.md) | Media asset management |
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
# Data Calculation (JS Sandbox)
|
|
2
2
|
|
|
3
|
-
Transform and compute Data Bank values using JavaScript scripts.
|
|
3
|
+
Transform and compute Data Bank values using JavaScript scripts. Calcs are for **pure data transformation only** — see [Architecture Patterns](architecture-patterns.md) for the pattern selection guide.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
| If you need to... | Use instead |
|
|
6
|
+
|---|---|
|
|
7
|
+
| Call an LLM / AI model | Generator (Assistant, LLM, HTTP) |
|
|
8
|
+
| Sequence multiple actions | Event Action Chain |
|
|
9
|
+
| Set a data value directly | PROPERTY_BANK system action |
|
|
10
|
+
| Compute a simple expression | PROPERTY_BANK_EXPRESSION |
|
|
11
|
+
| Transform/format/parse data | Data Calculation (correct use) |
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
## Authoring Contract
|
|
8
14
|
|
|
9
15
|
```typescript
|
|
10
16
|
import { makeId } from 'bricks-ctor'
|
|
17
|
+
import { readFile } from 'node:fs/promises'
|
|
11
18
|
|
|
12
19
|
const calculation: DataCalculationScript = {
|
|
13
20
|
__typename: 'DataCalculationScript',
|
|
@@ -15,9 +22,9 @@ const calculation: DataCalculationScript = {
|
|
|
15
22
|
title: 'Format Price',
|
|
16
23
|
description: 'Formats price with currency symbol',
|
|
17
24
|
note: '',
|
|
18
|
-
triggerMode: 'auto', // 'auto' | 'manual'
|
|
25
|
+
triggerMode: 'auto', // 'auto' (default) | 'manual'
|
|
19
26
|
enableAsync: false,
|
|
20
|
-
// Inline code
|
|
27
|
+
// Inline code for short scripts...
|
|
21
28
|
code: `
|
|
22
29
|
const price = inputs.price || 0
|
|
23
30
|
const currency = inputs.currency || 'USD'
|
|
@@ -26,118 +33,82 @@ const calculation: DataCalculationScript = {
|
|
|
26
33
|
currency,
|
|
27
34
|
}).format(price)
|
|
28
35
|
`,
|
|
29
|
-
//
|
|
30
|
-
// import { readFile } from 'node:fs/promises'
|
|
36
|
+
// ...or load from a file (preferred for longer scripts):
|
|
31
37
|
// code: await readFile(new URL('./format-price.sandbox.js', import.meta.url), 'utf8'),
|
|
32
38
|
inputs: [
|
|
33
39
|
{ key: 'price', data: () => priceData, trigger: true },
|
|
34
40
|
{ key: 'currency', data: () => currencyData, trigger: false },
|
|
35
41
|
],
|
|
36
42
|
output: () => formattedPriceData,
|
|
37
|
-
outputs: [], // Additional named outputs
|
|
43
|
+
outputs: [], // Additional named outputs (see Multiple Outputs)
|
|
38
44
|
error: null, // or () => errorData for error handling
|
|
39
45
|
}
|
|
40
46
|
```
|
|
41
47
|
|
|
48
|
+
### Field Rules (defaults and constraints)
|
|
49
|
+
|
|
50
|
+
- `trigger` **defaults to `false` when omitted** — always set it explicitly. A calc whose inputs are all non-trigger never auto-runs.
|
|
51
|
+
- `triggerMode` defaults to `'auto'` when omitted.
|
|
52
|
+
- `output` receives the **whole return value**. `outputs` entries extract fields by key from a returned object — `key` is a lodash-get path, so deep paths like `'user.name'` work. `output`, `outputs`, and `error` can be combined.
|
|
53
|
+
- `error` receives the error **message string** when the script throws. Both extraction steps run on every execution: a success overwrites the error Data, a failure overwrites the output Data(s) — don't expect stale values to persist.
|
|
54
|
+
- **Auto mode rejects the same Data in both `inputs` and `output`/`outputs`/`error`** — compile fails with `Not allow duplicate set property id between inputs / outputs / output / error`. Manual mode allows the overlap (self-referential updates, see Recipes).
|
|
55
|
+
- `.sandbox.js` files use an `export function main() { ... }` wrapper — compile unwraps it. Raw statements also work, but the wrapper keeps linters happy since script bodies use top-level `return`.
|
|
56
|
+
|
|
42
57
|
## Trigger Modes
|
|
43
58
|
|
|
44
59
|
| Mode | Description |
|
|
45
60
|
|------|-------------|
|
|
46
|
-
| `auto` | Run
|
|
47
|
-
| `manual` |
|
|
61
|
+
| `auto` | Run on every write to a `trigger: true` input (even if the value is unchanged) |
|
|
62
|
+
| `manual` | Never auto-runs; only via `PROPERTY_BANK_COMMAND` action. Allows the same Data as both input and output |
|
|
63
|
+
|
|
64
|
+
Use `manual` to prevent circular dependencies, for explicit control, or when an output must feed back into an input.
|
|
65
|
+
|
|
66
|
+
## Triggering via PROPERTY_BANK_COMMAND
|
|
67
|
+
|
|
68
|
+
`input` references a Data that is an input of the target calc — the system runs the calc(s) that data feeds into. It does NOT reference the DataCalculation itself.
|
|
69
|
+
|
|
70
|
+
- **Manual calc**: ANY input works — `trigger` flags are ignored for manual-mode calcs.
|
|
71
|
+
- **Auto calc**: only `trigger: true` inputs work; commanding a `trigger: false` input is a silent no-op.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
const triggerCalc: EventAction = {
|
|
75
|
+
handler: 'system',
|
|
76
|
+
action: {
|
|
77
|
+
__actionName: 'PROPERTY_BANK_COMMAND',
|
|
78
|
+
parent: 'System',
|
|
79
|
+
dataParams: [
|
|
80
|
+
{ input: () => priceData }, // Reference to an input Data of the calc
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
```
|
|
48
85
|
|
|
49
|
-
|
|
86
|
+
- When the same chain **writes a calc input first** (e.g. `PROPERTY_BANK` setting `dLastButton`) then issues `PROPERTY_BANK_COMMAND`, set `waitAsync: true` on the write so the calc reads the new value rather than the pre-chain snapshot. See [Event Action Chains](architecture-patterns.md#event-action-chains-priority-2).
|
|
87
|
+
- When a **later action reads the calc's outputs**, set `waitAsync: true` on the `PROPERTY_BANK_COMMAND` action itself — it awaits the full calc chain including output writes.
|
|
88
|
+
- A dataParam's `value` acts as an execution gate: `{ input: () => d, value: false }` skips that trigger (combine with `mapping` for conditional runs).
|
|
50
89
|
|
|
51
|
-
## Script Sandbox
|
|
90
|
+
## Script Sandbox
|
|
52
91
|
|
|
53
|
-
Scripts run in `use strict` mode
|
|
92
|
+
Scripts run in `use strict` mode as a function body — top-level `return` returns the calc result. No `fetch`, `XMLHttpRequest`, or `require` in any mode: I/O belongs to Generators.
|
|
54
93
|
|
|
55
94
|
### Built-in Globals
|
|
56
95
|
|
|
57
96
|
| Global | Description |
|
|
58
97
|
|--------|-------------|
|
|
59
|
-
| `inputs` | Object with input values |
|
|
60
|
-
| `console` | `{ log, error, warn, info }`
|
|
98
|
+
| `inputs` | Object with input values (keyed by input `key`) |
|
|
99
|
+
| `console` | `{ log, error, warn, info }` — output is only visible in DevTools debug sessions; production is a no-op |
|
|
61
100
|
| `Platform` | `{ OS, isTV, isPad, isVision, isElectron }` |
|
|
62
101
|
| `TextEncoder`, `TextDecoder` | Text encoding/decoding |
|
|
63
|
-
| `Buffer` | Node.js Buffer (without `allocUnsafe`) |
|
|
102
|
+
| `Buffer` | Node.js Buffer (without `allocUnsafe`/`allocUnsafeSlow`) |
|
|
64
103
|
| `btoa`, `atob` | Base64 encoding/decoding |
|
|
65
104
|
|
|
66
|
-
### Available Libraries
|
|
67
|
-
|
|
68
|
-
**Utility**
|
|
69
|
-
| Library | Global | Description |
|
|
70
|
-
|---------|--------|-------------|
|
|
71
|
-
| [lodash](https://lodash.com) | `_`, `lodash` | Utility (sync: no debounce/delay/defer) |
|
|
72
|
-
| [voca](https://vocajs.com) | `voca` | String manipulation |
|
|
73
|
-
| [invariant](https://github.com/zertosh/invariant) | `invariant` | Assertions |
|
|
74
|
-
|
|
75
|
-
**Data & Encoding**
|
|
76
|
-
| Library | Global | Description |
|
|
77
|
-
|---------|--------|-------------|
|
|
78
|
-
| [json5](https://github.com/json5/json5) | `json5` | JSON5 parsing |
|
|
79
|
-
| [qs](https://github.com/ljharb/qs) | `qs` | Query string parsing |
|
|
80
|
-
| [url](https://github.com/defunctzombie/node-url) | `url` | URL parsing |
|
|
81
|
-
| [bytes](https://github.com/visionmedia/bytes.js) | `bytes` | Byte parsing/formatting |
|
|
82
|
-
| [ms](https://github.com/vercel/ms) | `ms` | Millisecond conversion |
|
|
83
|
-
| [base45](https://github.com/irony/base45) | `base45` | Base45 encoding |
|
|
84
|
-
| [iconv-lite](https://github.com/ashtuchkin/iconv-lite) | `iconv` | Character encoding |
|
|
85
|
-
|
|
86
|
-
**Math & Color**
|
|
87
|
-
| Library | Global | Description |
|
|
88
|
-
|---------|--------|-------------|
|
|
89
|
-
| [mathjs](https://mathjs.org) | `math`, `mathjs` | Math library |
|
|
90
|
-
| [chroma-js](https://gka.github.io/chroma.js) | `chroma` | Color manipulation |
|
|
91
|
-
|
|
92
|
-
**Date/Time**
|
|
93
|
-
| Library | Global | Description |
|
|
94
|
-
|---------|--------|-------------|
|
|
95
|
-
| [moment](https://momentjs.com) | `moment` | Date/time (auto parseFormat) |
|
|
96
|
-
|
|
97
|
-
**ID & Hash**
|
|
98
|
-
| Library | Global | Description |
|
|
99
|
-
|---------|--------|-------------|
|
|
100
|
-
| [nanoid](https://github.com/ai/nanoid) | `nanoid` | Unique ID generation |
|
|
101
|
-
| [md5](https://github.com/pvorb/node-md5) | `md5` | MD5 hashing |
|
|
102
|
-
|
|
103
|
-
**Crypto**
|
|
104
|
-
| Library | Global | Description |
|
|
105
|
-
|---------|--------|-------------|
|
|
106
|
-
| [crypto-browserify](https://github.com/crypto-browserify/crypto-browserify) | `crypto` | Crypto functions |
|
|
107
|
-
| [jsrsasign](https://github.com/kjur/jsrsasign) | `kjurJWS` | JWT/JWS signing |
|
|
108
|
-
| [cose-js](https://github.com/erdtman/COSE-JS) | `coseVerify` | COSE verification (sync) |
|
|
109
|
-
|
|
110
|
-
**Compression**
|
|
111
|
-
| Library | Global | Description |
|
|
112
|
-
|---------|--------|-------------|
|
|
113
|
-
| [fflate](https://github.com/101arrowz/fflate) | `fflate` | `{ zlibSync, unzlibSync, gzipSync, gunzipSync, compressSync, decompressSync, strFromU8 }` |
|
|
114
|
-
| [cbor](https://github.com/hildjj/node-cbor) | `cbor` | `{ encode, decode, decodeFirstSync, decodeAllSync }` |
|
|
115
|
-
|
|
116
|
-
**File & Document**
|
|
117
|
-
| Library | Global | Description |
|
|
118
|
-
|---------|--------|-------------|
|
|
119
|
-
| fs | `fs` | File system (limited, no download/upload) |
|
|
120
|
-
| [officeparser](https://github.com/nicktang) | `parseDocument` | Office document parsing (async) |
|
|
121
|
-
| [turndown](https://github.com/mixmark-io/turndown) | `TurndownService` | HTML to Markdown |
|
|
122
|
-
| [opencc-js](https://github.com/nk2028/opencc-js) | `OpenCC` | Chinese conversion `{ Converter, ConverterFactory, CustomConverter, Locale }` |
|
|
123
|
-
| [toon-format](https://github.com/nicktang) | `TOON` | TOON format parsing |
|
|
124
|
-
|
|
125
|
-
### Runtime Environment
|
|
126
|
-
|
|
127
|
-
| Platform | Engine |
|
|
128
|
-
|----------|--------|
|
|
129
|
-
| Android | Hermes engine sandbox |
|
|
130
|
-
| iOS | JavaScriptCore sandbox |
|
|
131
|
-
|
|
132
105
|
### Async Mode
|
|
133
106
|
|
|
134
|
-
Enable `enableAsync: true` to unlock
|
|
107
|
+
Sync mode (default) has **no `Promise`, timers, or `await`**. Enable `enableAsync: true` to unlock:
|
|
135
108
|
|
|
136
|
-
|
|
137
|
-
-
|
|
138
|
-
- `
|
|
139
|
-
- `requestAnimationFrame`
|
|
140
|
-
- Full lodash (including `debounce`, `delay`, `defer`)
|
|
109
|
+
- `Promise`, `setTimeout`, `setInterval`, `setImmediate`, `clearTimeout`, `clearInterval`, `clearImmediate`, `requestAnimationFrame`
|
|
110
|
+
- Full lodash (sync mode omits `debounce`, `delay`, `defer`)
|
|
111
|
+
- `await` at the top level of the script
|
|
141
112
|
|
|
142
113
|
```typescript
|
|
143
114
|
code: `
|
|
@@ -149,14 +120,63 @@ code: `
|
|
|
149
120
|
enableAsync: true,
|
|
150
121
|
```
|
|
151
122
|
|
|
123
|
+
### Runtime Environment
|
|
124
|
+
|
|
125
|
+
| Platform | Engine |
|
|
126
|
+
|----------|--------|
|
|
127
|
+
| Android | Hermes engine sandbox |
|
|
128
|
+
| iOS | JavaScriptCore sandbox |
|
|
129
|
+
| Electron desktop | Web Worker (V8) |
|
|
130
|
+
| Web preview / Simulator | Web Worker (V8) |
|
|
131
|
+
|
|
132
|
+
Simulator (Path 1) runs scripts on V8 while devices run Hermes/JSC — engine-sensitive code (date parsing, Intl, regex features) can pass in the Simulator and fail on device.
|
|
133
|
+
|
|
134
|
+
### Available Libraries
|
|
135
|
+
|
|
136
|
+
All exposed as globals. No network/file-download capability in any of them.
|
|
137
|
+
|
|
138
|
+
| Global | Library | Notes |
|
|
139
|
+
|--------|---------|-------|
|
|
140
|
+
| `_`, `lodash` | lodash | Sync mode omits `debounce`/`delay`/`defer` |
|
|
141
|
+
| `voca` | voca | String manipulation |
|
|
142
|
+
| `invariant` | invariant | Assertions |
|
|
143
|
+
| `json5` | json5 | JSON5 parsing |
|
|
144
|
+
| `qs` | qs | Query string parsing |
|
|
145
|
+
| `url` | node-url | URL parsing |
|
|
146
|
+
| `bytes` | bytes | Byte parsing/formatting |
|
|
147
|
+
| `ms` | ms | Millisecond conversion |
|
|
148
|
+
| `base45` | base45 | Base45 encoding |
|
|
149
|
+
| `iconv` | iconv-lite | Character encoding |
|
|
150
|
+
| `math`, `mathjs` | mathjs | Math library |
|
|
151
|
+
| `chroma` | chroma-js | Color manipulation |
|
|
152
|
+
| `moment` | moment | Date/time; auto parseFormat for string args |
|
|
153
|
+
| `nanoid` | nanoid | Unique ID generation |
|
|
154
|
+
| `md5` | md5 | MD5 hashing |
|
|
155
|
+
| `crypto` | crypto-browserify | Crypto functions |
|
|
156
|
+
| `kjurJWS` | jsrsasign | JWT/JWS signing (`KJUR.jws.JWS`) |
|
|
157
|
+
| `coseVerify` | cose-js | COSE verification (sync) |
|
|
158
|
+
| `fflate` | fflate | `{ zlibSync, unzlibSync, gzipSync, gunzipSync, compressSync, decompressSync, strFromU8 }` |
|
|
159
|
+
| `cbor` | cbor | `{ encode, decode, decodeFirstSync, decodeAllSync, addSemanticType }` |
|
|
160
|
+
| `fs` | (in-repo fs-compat) | File system; no download/upload methods |
|
|
161
|
+
| `parseDocument` | officeparser (in-repo fork) | Office document parsing (async) |
|
|
162
|
+
| `TurndownService` | turndown | HTML to Markdown |
|
|
163
|
+
| `OpenCC` | opencc-js | Chinese conversion `{ Converter, ConverterFactory, CustomConverter, Locale }` |
|
|
164
|
+
| `TOON` | @toon-format/toon | TOON format parsing |
|
|
165
|
+
|
|
166
|
+
## Recipes
|
|
167
|
+
|
|
152
168
|
### Multiple Outputs
|
|
153
169
|
|
|
170
|
+
Return an object; each `outputs` entry extracts its `key`:
|
|
171
|
+
|
|
154
172
|
```typescript
|
|
155
173
|
outputs: [
|
|
156
174
|
{ key: 'total', data: () => totalData },
|
|
157
175
|
{ key: 'tax', data: () => taxData },
|
|
158
176
|
{ key: 'subtotal', data: () => subtotalData },
|
|
159
177
|
],
|
|
178
|
+
output: null,
|
|
179
|
+
error: null,
|
|
160
180
|
code: `
|
|
161
181
|
const subtotal = inputs.price * inputs.quantity
|
|
162
182
|
const tax = subtotal * 0.1
|
|
@@ -165,31 +185,51 @@ code: `
|
|
|
165
185
|
`,
|
|
166
186
|
```
|
|
167
187
|
|
|
168
|
-
|
|
188
|
+
### Manual Self-Referential Update
|
|
169
189
|
|
|
170
|
-
|
|
190
|
+
When an update is too complex for `PROPERTY_BANK_EXPRESSION` and must read its own previous value — manual mode allows the same Data as input and output:
|
|
171
191
|
|
|
172
192
|
```typescript
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
]
|
|
181
|
-
|
|
193
|
+
const appendHistory: DataCalculationScript = {
|
|
194
|
+
__typename: 'DataCalculationScript',
|
|
195
|
+
id: makeId('property_bank_calc'),
|
|
196
|
+
title: 'Append History Entry',
|
|
197
|
+
triggerMode: 'manual',
|
|
198
|
+
enableAsync: false,
|
|
199
|
+
code: `
|
|
200
|
+
const history = Array.isArray(inputs.history) ? inputs.history : []
|
|
201
|
+
return [...history, { entry: inputs.entry, at: moment().toISOString() }].slice(-50)
|
|
202
|
+
`,
|
|
203
|
+
inputs: [
|
|
204
|
+
{ key: 'history', data: () => historyData, trigger: true },
|
|
205
|
+
{ key: 'entry', data: () => entryData, trigger: true },
|
|
206
|
+
],
|
|
207
|
+
output: () => historyData, // same Data as input — manual mode only
|
|
208
|
+
outputs: [],
|
|
209
|
+
error: null,
|
|
182
210
|
}
|
|
211
|
+
// Run it from an event chain: PROPERTY_BANK writes entryData (waitAsync: true),
|
|
212
|
+
// then PROPERTY_BANK_COMMAND with input: () => entryData.
|
|
183
213
|
```
|
|
184
214
|
|
|
185
|
-
|
|
215
|
+
## Failure Modes
|
|
216
|
+
|
|
217
|
+
| Symptom | Cause | Fix |
|
|
218
|
+
|---------|-------|-----|
|
|
219
|
+
| Calc never auto-runs | `trigger` omitted on inputs (defaults to `false`) | Set `trigger: true` explicitly |
|
|
220
|
+
| `PROPERTY_BANK_COMMAND` does nothing | Auto calc + `trigger: false` input, or `input` doesn't reference an input Data of the calc | Command a `trigger: true` input (auto) or any input (manual) |
|
|
221
|
+
| Compile error `Not allow duplicate set property id...` | Auto mode with same Data as input and output | Use `triggerMode: 'manual'`, or split into separate Data |
|
|
222
|
+
| Calc reads stale value written earlier in the same chain | Missing `waitAsync: true` on the preceding write | Set `waitAsync: true` on the write action |
|
|
223
|
+
| Works in Simulator, fails on device | V8 vs Hermes/JSC engine difference | Verify on device (Path 2); avoid engine-sensitive parsing |
|
|
224
|
+
| `console.log` shows nothing | Console only emits during DevTools debug sessions | Attach DevTools, or write debug values to an output Data |
|
|
225
|
+
| `Promise`/`setTimeout` undefined, or `Async mode is required` error | `enableAsync: false` | Set `enableAsync: true` |
|
|
186
226
|
|
|
187
227
|
## Best Practices
|
|
188
228
|
|
|
189
229
|
1. **Avoid circular deps**: Set non-triggering inputs (`trigger: false`) or use `manual` mode
|
|
190
230
|
2. **Error handling**: Always set `error` output for scripts that might fail
|
|
191
231
|
3. **Keep scripts pure**: Avoid side effects, return computed values
|
|
192
|
-
4. **Debounce rapid updates**: Use `manual` mode + timer for high-frequency inputs
|
|
232
|
+
4. **Debounce rapid updates**: Use `manual` mode + timer for high-frequency inputs (auto calcs re-run on every write, even unchanged)
|
|
193
233
|
|
|
194
234
|
## Anti-Patterns (AVOID)
|
|
195
235
|
|
|
@@ -197,13 +237,3 @@ See [Architecture Patterns](architecture-patterns.md) for the full pattern selec
|
|
|
197
237
|
|
|
198
238
|
### Using Data Calc as an orchestrator
|
|
199
239
|
Scripts that manage state machines, control UI flow, or coordinate multi-step processes belong in Event Action Chains. Symptoms: if/else on "what happens next", mirror `dFooResult` outputs that copy back to `dFoo` via `valueChange`, or a `dLastInput` field set-then-cleared to force an auto calc. See the "user-driven state machine" recipe in [Architecture Patterns](architecture-patterns.md).
|
|
200
|
-
|
|
201
|
-
### Quick reference
|
|
202
|
-
|
|
203
|
-
| If you need to... | Use instead |
|
|
204
|
-
|---|---|
|
|
205
|
-
| Call an LLM / AI model | Generator (Assistant, LLM, HTTP) |
|
|
206
|
-
| Sequence multiple actions | Event Action Chain |
|
|
207
|
-
| Set a data value directly | PROPERTY_BANK system action |
|
|
208
|
-
| Compute a simple expression | PROPERTY_BANK_EXPRESSION |
|
|
209
|
-
| Transform/format/parse data | Data Calculation (correct use) |
|
|
@@ -89,7 +89,7 @@ So that camera and AI features are usable without device permissions, multi-giga
|
|
|
89
89
|
| Brick / Generator | In the Simulator | Does NOT prove |
|
|
90
90
|
|-------------------|------------------|----------------|
|
|
91
91
|
| Camera (`BRICK_CAMERA`) | A 3D mock canvas, no camera permission prompt. `takePicture` snapshots the canvas; recording produces a placeholder clip | Real camera feed, focus, recording, permission flow |
|
|
92
|
-
| Thermal Printer (`GENERATOR_THERMAL_PRINTER`) | A simulated printer — `init` / `checkStatus` / `scan` fake per-driver status and discovered devices (ESC/POS, Star, TSC, Castles); `print` renders an approximate on-screen receipt. A bottom-left bubble shows live status with a fault toggle to exercise error wiring | Real device connection, actual paper output, exact native driver status codes |
|
|
92
|
+
| Thermal Printer (`GENERATOR_THERMAL_PRINTER`) | A simulated printer — `init` / `checkStatus` / `scan` fake per-driver status and discovered devices (ESC/POS, Star, TSC, Castles); `print` renders an approximate on-screen receipt. A bottom-left bubble shows live status with a fault toggle to exercise error wiring. Print results can be exported as PNG via `bricks-cli` (see below) | Real device connection, actual paper output, exact native driver status codes |
|
|
93
93
|
| LLM (`GENERATOR_LLM`) | Swapped to a tiny local stand-in model | Output quality / latency of your real model |
|
|
94
94
|
| Reranker — GGML (`GENERATOR_RERANKER`) | Swapped to a small local multilingual reranker model | Ranking quality / latency of your real model |
|
|
95
95
|
| Speech-to-Text — GGML (`GENERATOR_SPEECH_INFERENCE`) | Swapped to a tiny local model | Accuracy / latency of your real model |
|
|
@@ -101,6 +101,22 @@ So that camera and AI features are usable without device permissions, multi-giga
|
|
|
101
101
|
|
|
102
102
|
These swaps make the AI generators runnable in the Simulator for wiring checks — validate real models, quality, and latency on a device (Path 2).
|
|
103
103
|
|
|
104
|
+
### Inspecting simulated thermal printer print results
|
|
105
|
+
|
|
106
|
+
With the Simulator running (CDP at `localhost:19852`, see [Verification Toolchain](verification-toolchain.md)), `bricks-cli` can read the simulated printers and export a print result as a PNG image — no need to open the bubble popover or screenshot the whole window:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Printers + print history (newest first; shows the --index value per result)
|
|
110
|
+
bricks devtools simulator thermal-printer list -p 19852
|
|
111
|
+
bricks devtools simulator thermal-printer list -p 19852 -j --commands # full print payloads as JSON
|
|
112
|
+
|
|
113
|
+
# Render one print result to PNG (defaults: the only printer, --index 0 = latest)
|
|
114
|
+
bricks devtools simulator thermal-printer print-result -p 19852 -o receipt.png
|
|
115
|
+
bricks devtools simulator thermal-printer print-result -p 19852 --index 1 --scale 2 -o older.png
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The PNG is the same approximate receipt the on-screen preview shows (rendered from the print payload). It proves the payload wiring — content, ordering, alignment, barcode/QR/image presence — not pixel-exact native raster output. Print history is in-memory (up to 10 per printer) and clears on preview reload.
|
|
119
|
+
|
|
104
120
|
### Running the real implementation instead
|
|
105
121
|
|
|
106
122
|
Each substituted brick/generator can be switched back to its real implementation per item: open the **gear (Simulator settings)** in the editor's preview toolbar, uncheck the item, and **Apply**. Apply persists the choice and reloads the preview so it takes effect (a plain refresh won't). Use this to, e.g., point a Vector Store at a real API key in the preview. The browser limits above still apply, and **Buttress stays disabled regardless** — there's no backend for it here.
|
|
@@ -1,30 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bricks-design
|
|
3
3
|
description: >-
|
|
4
|
-
Visual design discipline for Applications and Subspaces — type,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
pure usability / flow / journey / affordance / feedback / recovery
|
|
19
|
-
/ accessibility / multilingual audits — those go to bricks-ux. SKIP
|
|
20
|
-
for single-Brick or Generator template work
|
|
21
|
-
(create-brick-or-generator), debugging or refactoring with no
|
|
22
|
-
design intent, or non-display deliverables (CLI, server, tooling).
|
|
23
|
-
Encodes architecture truths, performance and complexity guardrails,
|
|
24
|
-
input-translation rules, visual languages library, Direction
|
|
25
|
-
Advisor for vague briefs, Media Flow protocol for branded work.
|
|
26
|
-
Verification toolchain (compile, preview tool selection, on-device DevTools,
|
|
27
|
-
Path 1/2/3) lives in the bricks-ctor skill.
|
|
4
|
+
Visual design discipline for Applications and Subspaces — type, palette, asset
|
|
5
|
+
acquisition, design language, system commitment, visual rhythm, brand. TRIGGER
|
|
6
|
+
for visual / aesthetic / system / style / brand-asset work even when named in
|
|
7
|
+
product terms — slideshow, pitch deck, explainer, kiosk, signage, menu board,
|
|
8
|
+
lobby, wayfinding, retail, museum, transit; translate or rebuild from Figma /
|
|
9
|
+
HTML / screenshot / website / PDF / brand book; vague creative briefs; branded
|
|
10
|
+
scenes; rework or audit of an existing Subspace's type / palette / motion /
|
|
11
|
+
rhythm. For end-to-end briefs invoke in parallel with bricks-ux (interaction /
|
|
12
|
+
flow layer). SKIP for pure usability / flow / accessibility audits (bricks-
|
|
13
|
+
ux), single-Brick or Generator template work (create-brick-or-generator),
|
|
14
|
+
debugging without design intent, or non-display deliverables. Encodes
|
|
15
|
+
architecture truths, performance guardrails, input-translation rules, visual
|
|
16
|
+
languages, Direction Advisor, Media Flow protocol; verification toolchain
|
|
17
|
+
lives in bricks-ctor.
|
|
28
18
|
---
|
|
29
19
|
|
|
30
20
|
# BRICKS Design
|
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bricks-ux
|
|
3
3
|
description: >-
|
|
4
|
-
Interaction design and end-user experience for any Application or
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
are visual design, not interaction design. Encodes a universal
|
|
19
|
-
user-journey spine, interaction archetypes, pressable composition,
|
|
20
|
-
monitoring-screen discipline, designed flow states, accessibility,
|
|
21
|
-
and a tiered UX critique. Hardware floors are deployment-relative;
|
|
22
|
-
web habits (hover affordances, modal-as-default, scroll, page-submit
|
|
23
|
-
forms) do not transfer.
|
|
4
|
+
Interaction design and end-user experience for any Application or Subspace
|
|
5
|
+
built on Canvases, Bricks, Generators, Data, DataCalculation. TRIGGER on
|
|
6
|
+
usability / flow / interaction / journey / state / affordance / feedback /
|
|
7
|
+
recovery / accessibility audits and design work — "audit this flow", "improve
|
|
8
|
+
usability", "design the wait state", "make the kiosk usable", "design the
|
|
9
|
+
payment flow", "design idle and attractor states", "design for multilingual /
|
|
10
|
+
low vision". Also triggers in parallel with visual-design work for end-to-end
|
|
11
|
+
deliverables (kiosk, signage, dashboard, interactive screen, pitch deck) where
|
|
12
|
+
interaction shape matters as much as look. SKIP for purely visual / aesthetic
|
|
13
|
+
/ style / brand-asset / typography / palette work — that is bricks-design.
|
|
14
|
+
Encodes a universal user-journey spine, interaction archetypes, pressable
|
|
15
|
+
composition, monitoring-screen discipline, designed flow states,
|
|
16
|
+
accessibility, tiered UX critique; hardware floors are deployment-relative and
|
|
17
|
+
web habits do not transfer.
|
|
24
18
|
---
|
|
25
19
|
|
|
26
20
|
# BRICKS UX
|
|
@@ -120,6 +120,11 @@ export type BrickScene3DActionUpdateObject = ActionWithParams & {
|
|
|
120
120
|
value?: string | DataLink | EventProperty
|
|
121
121
|
mapping?: string
|
|
122
122
|
}
|
|
123
|
+
| {
|
|
124
|
+
input: 'objectNodes'
|
|
125
|
+
value?: any | EventProperty
|
|
126
|
+
mapping?: string
|
|
127
|
+
}
|
|
123
128
|
>
|
|
124
129
|
}
|
|
125
130
|
|
|
@@ -279,6 +284,8 @@ Default property:
|
|
|
279
284
|
"alpha": false,
|
|
280
285
|
"shadows": false,
|
|
281
286
|
"toneMapping": "aces",
|
|
287
|
+
"exposure": 1,
|
|
288
|
+
"pixelRatio": 0,
|
|
282
289
|
"colorSpace": "srgb",
|
|
283
290
|
"powerPreference": "default",
|
|
284
291
|
"frameLoop": "always",
|
|
@@ -304,13 +311,24 @@ Default property:
|
|
|
304
311
|
"minDistance": 0.5,
|
|
305
312
|
"maxDistance": 50,
|
|
306
313
|
"minPolarAngle": 0,
|
|
314
|
+
"backgroundBlur": 0,
|
|
315
|
+
"backgroundIntensity": 1,
|
|
307
316
|
"envMapProjection": "equirect",
|
|
317
|
+
"envIntensity": 1,
|
|
318
|
+
"envRotation": 0,
|
|
319
|
+
"groundEnabled": false,
|
|
320
|
+
"groundColor": "",
|
|
321
|
+
"groundOpacity": 0.5,
|
|
322
|
+
"groundY": 0,
|
|
323
|
+
"groundSize": 100,
|
|
308
324
|
"ambientColor": "#ffffff",
|
|
309
325
|
"ambientIntensity": 0.4,
|
|
310
326
|
"lights": [],
|
|
311
327
|
"objects": [],
|
|
312
328
|
"bloom": false,
|
|
313
329
|
"bloomStrength": 0.6,
|
|
330
|
+
"bloomThreshold": 1,
|
|
331
|
+
"bloomRadius": 0.4,
|
|
314
332
|
"fxaa": false,
|
|
315
333
|
"ssao": false,
|
|
316
334
|
"frameRuntime": "ui",
|
|
@@ -335,6 +353,10 @@ Default property:
|
|
|
335
353
|
shadows?: boolean | DataLink
|
|
336
354
|
/* Tone mapping curve */
|
|
337
355
|
toneMapping?: 'none' | 'linear' | 'reinhard' | 'cineon' | 'aces' | 'agx' | DataLink
|
|
356
|
+
/* Tone mapping exposure */
|
|
357
|
+
exposure?: number | DataLink
|
|
358
|
+
/* Render pixel ratio. `0` follows the device pixel ratio (capped at 2 on web; native renders at 1) */
|
|
359
|
+
pixelRatio?: number | DataLink
|
|
338
360
|
/* Output color space */
|
|
339
361
|
colorSpace?: 'srgb' | 'srgb-linear' | DataLink
|
|
340
362
|
/* GPU power preference */
|
|
@@ -385,16 +407,34 @@ Default property:
|
|
|
385
407
|
maxPolarAngle?: number | DataLink
|
|
386
408
|
/* Background solid color (used when no background image is set) */
|
|
387
409
|
backgroundColor?: string | DataLink
|
|
388
|
-
/*
|
|
410
|
+
/* Equirect environment image URL (HDR/EXR/LDR). Used for PBR image-based lighting; also shown as the scene background unless `backgroundColor` is set */
|
|
389
411
|
backgroundImage?: string | DataLink
|
|
390
|
-
/*
|
|
412
|
+
/* Background image blurriness (0–1, only when the environment image is shown as background) */
|
|
413
|
+
backgroundBlur?: number | DataLink
|
|
414
|
+
/* Background image intensity multiplier */
|
|
415
|
+
backgroundIntensity?: number | DataLink
|
|
416
|
+
/* Environment map projection. `none` disables environment lighting from the background image */
|
|
391
417
|
envMapProjection?: 'equirect' | 'cube' | 'none' | DataLink
|
|
418
|
+
/* Environment lighting intensity multiplier */
|
|
419
|
+
envIntensity?: number | DataLink
|
|
420
|
+
/* Environment rotation around the Y axis (radians, also rotates the background) */
|
|
421
|
+
envRotation?: number | DataLink
|
|
392
422
|
/* Fog color */
|
|
393
423
|
fogColor?: string | DataLink
|
|
394
424
|
/* Fog near distance */
|
|
395
425
|
fogNear?: number | DataLink
|
|
396
426
|
/* Fog far distance */
|
|
397
427
|
fogFar?: number | DataLink
|
|
428
|
+
/* Show a ground plane that catches shadows (enable `shadows` and a `castShadow` light for the shadow itself) */
|
|
429
|
+
groundEnabled?: boolean | DataLink
|
|
430
|
+
/* Ground color. Empty renders a shadow-only (invisible) catcher */
|
|
431
|
+
groundColor?: string | DataLink
|
|
432
|
+
/* Shadow opacity for the shadow-only ground (0–1) */
|
|
433
|
+
groundOpacity?: number | DataLink
|
|
434
|
+
/* Ground plane height (Y position) */
|
|
435
|
+
groundY?: number | DataLink
|
|
436
|
+
/* Ground plane size (width and depth) */
|
|
437
|
+
groundSize?: number | DataLink
|
|
398
438
|
/* Ambient light color */
|
|
399
439
|
ambientColor?: string | DataLink
|
|
400
440
|
/* Ambient light intensity */
|
|
@@ -430,7 +470,7 @@ Default property:
|
|
|
430
470
|
}
|
|
431
471
|
>
|
|
432
472
|
| DataLink
|
|
433
|
-
/* Scene objects. Each entry: `{ id, type, url?, md5?, position, rotation, scale, color?, animation?, visible }` */
|
|
473
|
+
/* Scene objects. Each entry: `{ id, type, url?, md5?, position, rotation, scale, color?, animation?, visible, nodes? }`. `nodes` overrides named nodes inside a loaded model: `[{ name, visible?, position?, rotation?, scale?, color?, emissive?, emissiveIntensity?, metalness?, roughness?, opacity? }]` */
|
|
434
474
|
objects?:
|
|
435
475
|
| Array<
|
|
436
476
|
| DataLink
|
|
@@ -477,6 +517,42 @@ Default property:
|
|
|
477
517
|
visible?: boolean | DataLink
|
|
478
518
|
castShadow?: boolean | DataLink
|
|
479
519
|
receiveShadow?: boolean | DataLink
|
|
520
|
+
nodes?:
|
|
521
|
+
| Array<
|
|
522
|
+
| DataLink
|
|
523
|
+
| {
|
|
524
|
+
name?: string | DataLink
|
|
525
|
+
visible?: boolean | DataLink
|
|
526
|
+
position?:
|
|
527
|
+
| DataLink
|
|
528
|
+
| {
|
|
529
|
+
x?: number | DataLink
|
|
530
|
+
y?: number | DataLink
|
|
531
|
+
z?: number | DataLink
|
|
532
|
+
}
|
|
533
|
+
rotation?:
|
|
534
|
+
| DataLink
|
|
535
|
+
| {
|
|
536
|
+
x?: number | DataLink
|
|
537
|
+
y?: number | DataLink
|
|
538
|
+
z?: number | DataLink
|
|
539
|
+
}
|
|
540
|
+
scale?:
|
|
541
|
+
| DataLink
|
|
542
|
+
| {
|
|
543
|
+
x?: number | DataLink
|
|
544
|
+
y?: number | DataLink
|
|
545
|
+
z?: number | DataLink
|
|
546
|
+
}
|
|
547
|
+
color?: string | DataLink
|
|
548
|
+
emissive?: string | DataLink
|
|
549
|
+
emissiveIntensity?: number | DataLink
|
|
550
|
+
metalness?: number | DataLink
|
|
551
|
+
roughness?: number | DataLink
|
|
552
|
+
opacity?: number | DataLink
|
|
553
|
+
}
|
|
554
|
+
>
|
|
555
|
+
| DataLink
|
|
480
556
|
}
|
|
481
557
|
>
|
|
482
558
|
| DataLink
|
|
@@ -484,6 +560,10 @@ Default property:
|
|
|
484
560
|
bloom?: boolean | DataLink
|
|
485
561
|
/* Bloom intensity */
|
|
486
562
|
bloomStrength?: number | DataLink
|
|
563
|
+
/* Bloom luminance threshold. The chain is HDR — values ≥ 1 keep bloom on highlights only */
|
|
564
|
+
bloomThreshold?: number | DataLink
|
|
565
|
+
/* Bloom radius (glow spread) */
|
|
566
|
+
bloomRadius?: number | DataLink
|
|
487
567
|
/* Enable FXAA antialiasing post-effect */
|
|
488
568
|
fxaa?: boolean | DataLink
|
|
489
569
|
/* Enable screen-space ambient occlusion (SSAO) */
|
|
@@ -18,7 +18,9 @@ export type DataCommandSandboxGetReturnValue = DataCommand & {
|
|
|
18
18
|
/* Run JS — Run JavaScript code
|
|
19
19
|
|
|
20
20
|
- Default `use strict`
|
|
21
|
-
- Global functions fetch, XMLHttpRequest
|
|
21
|
+
- Global functions fetch, XMLHttpRequest are not available.
|
|
22
|
+
- setTimeout, setInterval, Promise... require Enable Async.
|
|
23
|
+
- Built-in globals: Platform, Buffer, btoa/atob, TextEncoder/TextDecoder
|
|
22
24
|
|
|
23
25
|
##### Available libraries (global)
|
|
24
26
|
|
|
@@ -43,10 +45,16 @@ export type DataCommandSandboxGetReturnValue = DataCommand & {
|
|
|
43
45
|
- fflate (Not support async, callback and stream)
|
|
44
46
|
- iconv (Use iconv-lite)
|
|
45
47
|
- OpenCC (Use opencc-js)
|
|
48
|
+
- fs (Limited, no download/upload)
|
|
49
|
+
- parseDocument (Use officeparser, requires Enable Async)
|
|
50
|
+
- TurndownService (Use turndown, HTML to Markdown)
|
|
51
|
+
- TOON (Use toon-format/toon)
|
|
46
52
|
|
|
47
53
|
Android: Running on the sandbox of Hermes engine
|
|
48
54
|
|
|
49
|
-
iOS: Running on the sandbox of iOS built-in JavaScriptCore
|
|
55
|
+
iOS: Running on the sandbox of iOS built-in JavaScriptCore
|
|
56
|
+
|
|
57
|
+
Desktop / Web: Running on the sandbox of a Web Worker */
|
|
50
58
|
export type DataCommandSandboxRunJavascript = DataCommand & {
|
|
51
59
|
__commandName: 'SANDBOX_RUN_JAVASCRIPT'
|
|
52
60
|
inputs?: Array<
|