@fugood/bricks-ctor 2.25.0-beta.60 → 2.25.0-beta.62

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.
Files changed (192) hide show
  1. package/package.json +4 -28
  2. package/tools/__tests__/legacy-forwarder.test.js +91 -0
  3. package/tools/_forward.ts +26 -0
  4. package/tools/deploy.ts +3 -175
  5. package/tools/mcp-server.ts +3 -35
  6. package/tools/postinstall.ts +3 -291
  7. package/tools/pull.ts +3 -198
  8. package/tools/push-config.ts +3 -113
  9. package/tools/simulator.ts +3 -149
  10. package/compile/__tests__/config-diff.test.js +0 -100
  11. package/compile/__tests__/index.test.js +0 -461
  12. package/compile/__tests__/util.test.js +0 -450
  13. package/compile/action-name-map.ts +0 -1079
  14. package/compile/config-diff.ts +0 -155
  15. package/compile/index.ts +0 -1594
  16. package/compile/util.ts +0 -482
  17. package/index.ts +0 -6
  18. package/skills/bricks-ctor/SKILL.md +0 -38
  19. package/skills/bricks-ctor/references/animation.md +0 -160
  20. package/skills/bricks-ctor/references/architecture-patterns.md +0 -88
  21. package/skills/bricks-ctor/references/automations.md +0 -232
  22. package/skills/bricks-ctor/references/buttress.md +0 -245
  23. package/skills/bricks-ctor/references/data-calculation.md +0 -252
  24. package/skills/bricks-ctor/references/local-sync.md +0 -129
  25. package/skills/bricks-ctor/references/media-flow.md +0 -165
  26. package/skills/bricks-ctor/references/remote-data-bank.md +0 -196
  27. package/skills/bricks-ctor/references/simulator.md +0 -132
  28. package/skills/bricks-ctor/references/source-editing-tools.md +0 -81
  29. package/skills/bricks-ctor/references/standby-transition.md +0 -124
  30. package/skills/bricks-ctor/references/verification-toolchain.md +0 -200
  31. package/skills/bricks-design/SKILL.md +0 -171
  32. package/skills/bricks-design/references/architecture-truths.md +0 -132
  33. package/skills/bricks-design/references/avoiding-complexity.md +0 -91
  34. package/skills/bricks-design/references/design-critique.md +0 -195
  35. package/skills/bricks-design/references/design-languages.md +0 -265
  36. package/skills/bricks-design/references/performance.md +0 -116
  37. package/skills/bricks-design/references/presentation-and-slideshow.md +0 -137
  38. package/skills/bricks-design/references/translating-inputs.md +0 -152
  39. package/skills/bricks-design/references/variations-and-tweaks.md +0 -124
  40. package/skills/bricks-design/references/when-the-brief-is-branded.md +0 -284
  41. package/skills/bricks-design/references/when-the-brief-is-vague.md +0 -85
  42. package/skills/bricks-design/references/workflow.md +0 -134
  43. package/skills/bricks-ux/SKILL.md +0 -114
  44. package/skills/bricks-ux/references/accessibility.md +0 -162
  45. package/skills/bricks-ux/references/flow-states.md +0 -175
  46. package/skills/bricks-ux/references/interaction-archetypes.md +0 -189
  47. package/skills/bricks-ux/references/monitoring-screens.md +0 -153
  48. package/skills/bricks-ux/references/pressable-composition.md +0 -126
  49. package/skills/bricks-ux/references/user-journey.md +0 -168
  50. package/skills/bricks-ux/references/ux-critique.md +0 -256
  51. package/skills/rive-marketplace/SKILL.md +0 -99
  52. package/tools/__tests__/_cli-error.test.ts +0 -35
  53. package/tools/__tests__/_mcp-config.test.ts +0 -67
  54. package/tools/__tests__/pull.test.ts +0 -108
  55. package/tools/_cli-error.ts +0 -17
  56. package/tools/_edits-log.ts +0 -41
  57. package/tools/_git-author.ts +0 -37
  58. package/tools/_last-pushed-commit.ts +0 -28
  59. package/tools/_mcp-config.ts +0 -42
  60. package/tools/_shell.ts +0 -180
  61. package/tools/icons/.gitattributes +0 -1
  62. package/tools/icons/fa6pro-glyphmap.json +0 -4686
  63. package/tools/icons/fa6pro-meta.json +0 -1
  64. package/tools/mcp-env.ts +0 -13
  65. package/tools/mcp-tools/__tests__/data-calc-editing.test.js +0 -516
  66. package/tools/mcp-tools/__tests__/entry-editing.test.js +0 -866
  67. package/tools/mcp-tools/__tests__/huggingface.test.ts +0 -49
  68. package/tools/mcp-tools/__tests__/icons.test.ts +0 -21
  69. package/tools/mcp-tools/__tests__/mcp-env.test.js +0 -19
  70. package/tools/mcp-tools/_editing-helpers.ts +0 -98
  71. package/tools/mcp-tools/_verify.ts +0 -50
  72. package/tools/mcp-tools/compile.ts +0 -104
  73. package/tools/mcp-tools/data-calc-editing.ts +0 -1311
  74. package/tools/mcp-tools/entry-editing.ts +0 -2297
  75. package/tools/mcp-tools/huggingface.ts +0 -772
  76. package/tools/mcp-tools/icons.ts +0 -97
  77. package/tools/mcp-tools/lottie.ts +0 -102
  78. package/tools/mcp-tools/media.ts +0 -113
  79. package/tools/simulator-main.mjs +0 -488
  80. package/tools/simulator-preload.cjs +0 -16
  81. package/types/animation.d.ts +0 -116
  82. package/types/automation.d.ts +0 -231
  83. package/types/brick-base.d.ts +0 -80
  84. package/types/bricks/Camera.d.ts +0 -246
  85. package/types/bricks/Chart.d.ts +0 -372
  86. package/types/bricks/GenerativeMedia.d.ts +0 -290
  87. package/types/bricks/Icon.d.ts +0 -98
  88. package/types/bricks/Image.d.ts +0 -126
  89. package/types/bricks/Items.d.ts +0 -480
  90. package/types/bricks/Lottie.d.ts +0 -168
  91. package/types/bricks/Maps.d.ts +0 -262
  92. package/types/bricks/QrCode.d.ts +0 -117
  93. package/types/bricks/Rect.d.ts +0 -150
  94. package/types/bricks/RichText.d.ts +0 -131
  95. package/types/bricks/Rive.d.ts +0 -220
  96. package/types/bricks/Scene3D.d.ts +0 -676
  97. package/types/bricks/Sketch.d.ts +0 -256
  98. package/types/bricks/Slideshow.d.ts +0 -201
  99. package/types/bricks/Svg.d.ts +0 -99
  100. package/types/bricks/Text.d.ts +0 -148
  101. package/types/bricks/TextInput.d.ts +0 -242
  102. package/types/bricks/Video.d.ts +0 -242
  103. package/types/bricks/VideoStreaming.d.ts +0 -112
  104. package/types/bricks/WebRtcStream.d.ts +0 -65
  105. package/types/bricks/WebView.d.ts +0 -168
  106. package/types/bricks/index.d.ts +0 -23
  107. package/types/canvas.d.ts +0 -82
  108. package/types/common.d.ts +0 -141
  109. package/types/data-calc-command/base.d.ts +0 -57
  110. package/types/data-calc-command/collection.d.ts +0 -418
  111. package/types/data-calc-command/color.d.ts +0 -432
  112. package/types/data-calc-command/constant.d.ts +0 -50
  113. package/types/data-calc-command/datetime.d.ts +0 -147
  114. package/types/data-calc-command/file.d.ts +0 -129
  115. package/types/data-calc-command/index.d.ts +0 -13
  116. package/types/data-calc-command/iteratee.d.ts +0 -23
  117. package/types/data-calc-command/logictype.d.ts +0 -190
  118. package/types/data-calc-command/math.d.ts +0 -275
  119. package/types/data-calc-command/object.d.ts +0 -119
  120. package/types/data-calc-command/sandbox.d.ts +0 -66
  121. package/types/data-calc-command/string.d.ts +0 -407
  122. package/types/data-calc-script.d.ts +0 -21
  123. package/types/data-calc.d.ts +0 -12
  124. package/types/data.d.ts +0 -97
  125. package/types/generators/AlarmClock.d.ts +0 -110
  126. package/types/generators/Assistant.d.ts +0 -640
  127. package/types/generators/BleCentral.d.ts +0 -247
  128. package/types/generators/BlePeripheral.d.ts +0 -208
  129. package/types/generators/CanvasMap.d.ts +0 -74
  130. package/types/generators/CastlesPay.d.ts +0 -87
  131. package/types/generators/DataBank.d.ts +0 -160
  132. package/types/generators/File.d.ts +0 -432
  133. package/types/generators/GraphQl.d.ts +0 -132
  134. package/types/generators/Http.d.ts +0 -222
  135. package/types/generators/HttpServer.d.ts +0 -230
  136. package/types/generators/Information.d.ts +0 -103
  137. package/types/generators/Intent.d.ts +0 -168
  138. package/types/generators/Iterator.d.ts +0 -108
  139. package/types/generators/Keyboard.d.ts +0 -105
  140. package/types/generators/LlmAnthropicCompat.d.ts +0 -212
  141. package/types/generators/LlmAppleBuiltin.d.ts +0 -159
  142. package/types/generators/LlmGgml.d.ts +0 -903
  143. package/types/generators/LlmMediaTekNeuroPilot.d.ts +0 -235
  144. package/types/generators/LlmMlx.d.ts +0 -228
  145. package/types/generators/LlmOnnx.d.ts +0 -213
  146. package/types/generators/LlmOpenAiCompat.d.ts +0 -312
  147. package/types/generators/LlmQualcommAiEngine.d.ts +0 -247
  148. package/types/generators/Mcp.d.ts +0 -637
  149. package/types/generators/McpServer.d.ts +0 -289
  150. package/types/generators/MediaFlow.d.ts +0 -170
  151. package/types/generators/MqttBroker.d.ts +0 -141
  152. package/types/generators/MqttClient.d.ts +0 -141
  153. package/types/generators/Question.d.ts +0 -408
  154. package/types/generators/RealtimeTranscription.d.ts +0 -287
  155. package/types/generators/RerankerGgml.d.ts +0 -195
  156. package/types/generators/SerialPort.d.ts +0 -151
  157. package/types/generators/SoundPlayer.d.ts +0 -94
  158. package/types/generators/SoundRecorder.d.ts +0 -139
  159. package/types/generators/SpeechToTextGgml.d.ts +0 -424
  160. package/types/generators/SpeechToTextOnnx.d.ts +0 -236
  161. package/types/generators/SpeechToTextPlatform.d.ts +0 -85
  162. package/types/generators/SqLite.d.ts +0 -159
  163. package/types/generators/Step.d.ts +0 -107
  164. package/types/generators/SttAppleBuiltin.d.ts +0 -153
  165. package/types/generators/Tcp.d.ts +0 -126
  166. package/types/generators/TcpServer.d.ts +0 -147
  167. package/types/generators/TextToSpeechAppleBuiltin.d.ts +0 -127
  168. package/types/generators/TextToSpeechGgml.d.ts +0 -221
  169. package/types/generators/TextToSpeechOnnx.d.ts +0 -178
  170. package/types/generators/TextToSpeechOpenAiLike.d.ts +0 -121
  171. package/types/generators/ThermalPrinter.d.ts +0 -193
  172. package/types/generators/Tick.d.ts +0 -83
  173. package/types/generators/Udp.d.ts +0 -120
  174. package/types/generators/VadGgml.d.ts +0 -260
  175. package/types/generators/VadOnnx.d.ts +0 -231
  176. package/types/generators/VadTraditional.d.ts +0 -138
  177. package/types/generators/VectorStore.d.ts +0 -257
  178. package/types/generators/Watchdog.d.ts +0 -107
  179. package/types/generators/WebCrawler.d.ts +0 -103
  180. package/types/generators/WebRtc.d.ts +0 -181
  181. package/types/generators/WebSocket.d.ts +0 -148
  182. package/types/generators/index.d.ts +0 -57
  183. package/types/index.d.ts +0 -13
  184. package/types/subspace.d.ts +0 -60
  185. package/types/switch.d.ts +0 -51
  186. package/types/system.d.ts +0 -707
  187. package/utils/__tests__/calc.test.js +0 -25
  188. package/utils/__tests__/id.test.js +0 -154
  189. package/utils/calc.ts +0 -130
  190. package/utils/data.ts +0 -495
  191. package/utils/event-props.ts +0 -912
  192. package/utils/id.ts +0 -133
@@ -1,88 +0,0 @@
1
- # Architecture Patterns
2
-
3
- How to decompose complex flows into the right combination of BRICKS patterns.
4
-
5
- ## Pattern Selection Priority
6
-
7
- Prefer higher-priority patterns; only fall to lower when they genuinely can't solve the sub-problem:
8
-
9
- | Priority | Pattern | Use For |
10
- |----------|---------|---------|
11
- | 1 | Generator + Events | I/O, AI inference, external data |
12
- | 2 | Event Action Chains | Orchestration, sequential steps |
13
- | 3 | System Actions | State changes, navigation, UI triggers |
14
- | 4 | Data Calculation | Pure data transformation ONLY |
15
-
16
- ### Generators (Priority 1)
17
- For all external I/O and AI inference. Each generator emits events that naturally chain into actions.
18
- - **GeneratorAssistant**: multi-turn LLM conversations, function calling, built-in message history
19
- - **GeneratorLLM**: single-shot local inference (GGML)
20
- - **GeneratorHttp**: REST API calls
21
- - **GeneratorMqtt / GeneratorWebSocket**: real-time messaging
22
-
23
- ### Event Action Chains (Priority 2)
24
- The primary way to orchestrate multi-step flows. A single event can contain an array of EventActions executed sequentially.
25
- - Use `waitAsync: true` to await async actions before the next step
26
- - Use `dataParams` + `mapping` to pass event data downstream
27
- - This is the "glue" that wires generators, state, and UI together
28
- - For Generator result UI: await Generator, write done/version Data; route/current Data stays identity.
29
-
30
- Sequential `PROPERTY_BANK` / `PROPERTY_BANK_EXPRESSION` actions in one chain read the data values that existed when the chain started. If a later action needs to read what an earlier action wrote, set `waitAsync: true` on the earlier action.
31
-
32
- ### System Actions (Priority 3)
33
- Built-in commands for direct state and UI changes.
34
- - **PROPERTY_BANK**: set data value
35
- - **PROPERTY_BANK_EXPRESSION**: inline JS expression for simple compute
36
- - The expression engine folds statements into a single expression: only expression
37
- statements, simple `const`/`let` declarations, and a final return/expression are
38
- supported — **no `if`/`for`/`while`/`switch`** (use ternaries). The same limit
39
- applies inside a zero-arg IIFE body. Unsupported statements fail at runtime with
40
- the error visible only in a DevTools session, so prefer ternary chains or move the
41
- logic to a DataCalculationScript.
42
- - **CHANGE_CANVAS**: navigate to another canvas
43
- - **DYNAMIC_ANIMATION**: trigger animation
44
- - **ALERT / MESSAGE**: system feedback
45
-
46
- ### Data Calculation (Priority 4)
47
- ONLY for deriving, formatting, or aggregating values from other data. Not for orchestration, side effects, or flow control.
48
-
49
- ## Entity Aliases
50
-
51
- Set `alias` on entities to give them a stable, human-readable name:
52
- - Code generation uses alias as the variable name (e.g., `alias: 'submitBtn'` → `export const submitBtn`)
53
- - At runtime, devtools MCP tools accept alias instead of short ID and selectors can match by alias. Note: bricks-ctor does not directly interact with devtools MCP — aliases here primarily affect code generation
54
- - Aliases must be unique across the application — duplicates are excluded from resolution
55
-
56
- ## Flow Decomposition
57
-
58
- When the user describes a complex flow, decompose it BEFORE writing code:
59
-
60
- ### Step 1: Extract I/O boundaries
61
- Every external interaction maps to a Generator:
62
- - "call LLM" → GeneratorAssistant or GeneratorLLM
63
- - "fetch API" → GeneratorHttp
64
- - "speech to text" → GeneratorSpeechInference
65
-
66
- ### Step 2: Extract state transitions
67
- Every UI change maps to a System Action in an event chain:
68
- - "show loading" → PROPERTY_BANK on a boolean data
69
- - "go to result screen" → CHANGE_CANVAS
70
- - "animate in" → DYNAMIC_ANIMATION
71
-
72
- ### Step 3: Extract pure transformations
73
- Only actual data derivation maps to Data Calculation:
74
- - "format the response" → DataCalculationScript
75
- - "compute a score" → DataCalculationScript or DataCalculationMap
76
-
77
- ### Step 4: Wire with Event Action Chains
78
- Connect the pieces through events on generators and bricks.
79
-
80
- ## Recipe: user-driven state machine (calculator, form wizard, picker)
81
-
82
- A brief like "state vars X, Y, Z; button A updates X from X+Y; button B resets" is a state machine. The shape:
83
-
84
- - Each state variable is its own `Data` entity. Displays read it via `linkData(() => data.dFoo)`.
85
- - Each button's `onPress` is an Event Action Chain. For every state var that changes, append one `PROPERTY_BANK_EXPRESSION` whose `expression` reads the current state and returns the new value.
86
- - Use `Data Calculation` only for reusable pure derivations referenced as inputs to those expressions.
87
-
88
- A 10-button calculator with 4 state vars is ~10 small chains of 1–4 inline expressions. If you find yourself writing a single auto-mode `DataCalculationScript` that consumes all state vars and emits all-new state through mirror `dFooResult` data — or pinging a `dLastInput` field to force an auto calc to re-run — the chain shape was the right answer.
@@ -1,232 +0,0 @@
1
- # Automations
2
-
3
- E2E testing and scheduled execution for BRICKS applications. Simulates user behavior and validates application state.
4
-
5
- ## Automation Types
6
-
7
- | Type | Description |
8
- | --------- | ---------------------------------------------------------- |
9
- | `launch` | Run on application launch (restarts app when run manually) |
10
- | `anytime` | Execute anytime via manual trigger |
11
- | `cron` | Scheduled execution using crontab expressions |
12
-
13
- ## Simulation Actions
14
-
15
- Automations can simulate:
16
-
17
- - **Brick Press**: Tap/click on bricks
18
- - **Key Events**: Key up/down for keyboard input
19
- - **HTTP Request**: API calls
20
- - **Execute Action**: Trigger system or generator actions
21
-
22
- ## Assertions
23
-
24
- Automations can validate:
25
-
26
- - **Brick Exists**: Check if brick is rendered
27
- - **Event Triggered**: Verify event from Brick/Generator/Canvas
28
- - **Canvas Changed**: Confirm canvas navigation
29
- - **Property Assert**: Check Data Bank values
30
- - **Property Updated**: Wait for property change
31
- - **Match Screenshot**: Visual regression testing
32
-
33
- ## TypeScript Example
34
-
35
- ```typescript
36
- const testLoginFlow: AutomationTest = {
37
- __typename: 'AutomationTest',
38
- id: makeId('test'),
39
- title: 'Test Login Flow',
40
- timeout: 30000,
41
- trigger_type: 'launch',
42
- cases: [
43
- {
44
- __typename: 'TestCase',
45
- id: makeId('test_case'),
46
- name: 'Wait for login canvas',
47
- run: ['wait_until_canvas_change', () => mainSubspace, () => loginCanvas, 5000],
48
- exit_on_failed: true,
49
- commented: false,
50
- pre_delay: 0,
51
- post_delay: 0,
52
- jump_cond: [],
53
- },
54
- {
55
- __typename: 'TestCase',
56
- id: makeId('test_case'),
57
- name: 'Press username input',
58
- run: ['brick_press', () => mainSubspace, () => usernameInput],
59
- exit_on_failed: true,
60
- commented: false,
61
- pre_delay: 0,
62
- post_delay: 100,
63
- jump_cond: [],
64
- },
65
- {
66
- __typename: 'TestCase',
67
- id: makeId('test_case'),
68
- name: 'Assert username value',
69
- run: ['assert_property', () => mainSubspace, () => usernameData, 'testuser'],
70
- exit_on_failed: true,
71
- commented: false,
72
- pre_delay: 0,
73
- post_delay: 0,
74
- jump_cond: [],
75
- },
76
- {
77
- __typename: 'TestCase',
78
- id: makeId('test_case'),
79
- name: 'Press login button',
80
- run: ['brick_press', () => mainSubspace, () => loginButton],
81
- exit_on_failed: true,
82
- commented: false,
83
- pre_delay: 0,
84
- post_delay: 0,
85
- jump_cond: [],
86
- },
87
- {
88
- __typename: 'TestCase',
89
- id: makeId('test_case'),
90
- name: 'Wait for dashboard',
91
- run: ['wait_until_canvas_change', () => mainSubspace, () => dashboardCanvas, 10000],
92
- exit_on_failed: true,
93
- commented: false,
94
- pre_delay: 0,
95
- post_delay: 0,
96
- jump_cond: [],
97
- },
98
- ],
99
- variables: [],
100
- }
101
- ```
102
-
103
- ## Test Methods
104
-
105
- | Method | Signature | Description |
106
- | ---------------------------- | ------------------------------------------------ | -------------------- |
107
- | `brick_press` | `[subspace, brick, options?]` | Simulate brick press |
108
- | `brick_exists` | `[subspace, brick, frame?]` | Check brick exists |
109
- | `wait_until_brick_exists` | `[subspace, brick, timeout?, frame?]` | Wait for brick |
110
- | `wait_until_event_trigger` | `[subspace, sender, eventKey, timeout?]` | Wait for event |
111
- | `wait_until_canvas_change` | `[subspace, canvas, timeout?]` | Wait for canvas |
112
- | `keydown` | `[keyCode, pressedKey?, flags?]` | Key down event |
113
- | `keyup` | `[keyCode, pressedKey?, flags?]` | Key up event |
114
- | `http_request` | `[url, options?]` | HTTP request |
115
- | `assert_property` | `[subspace, property, value]` | Assert data value |
116
- | `wait_until_property_change` | `[subspace, property, value, timeout?]` | Wait for value |
117
- | `execute_action` | `[subspace, handler, action, params?, options?]` | Execute action |
118
- | `match_screenshot` | `[name, threshold?, maxRetry?]` | Screenshot compare |
119
- | `delay` | `[subspace?, property?, defaultValue?]` | Delay execution |
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
-
131
- ### execute_action Params
132
-
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.
134
-
135
- ```typescript
136
- // CORRECT — use runtime event property key
137
- run: ['execute_action', () => subspace0, bricks.bInput.id, 'BRICK_TEXT_INPUT_SET_TEXT',
138
- { BRICK_TEXT_INPUT_TEXT: 'hello' }]
139
-
140
- // WRONG — action config input name doesn't work in automation
141
- run: ['execute_action', () => subspace0, bricks.bInput.id, 'BRICK_TEXT_INPUT_SET_TEXT',
142
- { text: 'hello' }]
143
- ```
144
-
145
- Reference `event-props.ts` for the correct runtime keys (e.g., `BRICK_TEXT_INPUT_TEXT`, `GENERATOR_MQTT_PAYLOAD`).
146
-
147
- ### Prefer UI Interactions Over Direct Generator Calls
148
-
149
- For realistic E2E testing, prefer simulating user actions (set text input + press button) over calling generator actions directly:
150
-
151
- ```typescript
152
- // GOOD — simulates real user behavior
153
- { run: ['execute_action', () => sub, bricks.bInput.id, 'BRICK_TEXT_INPUT_SET_TEXT',
154
- { BRICK_TEXT_INPUT_TEXT: 'hello' }] },
155
- { run: ['brick_press', () => sub, () => bricks.bSendBtn] },
156
- { run: ['wait_until_property_change', () => sub, () => data.dPayload, 'hello', 10000] },
157
-
158
- // AVOID — bypasses UI, doesn't test the full flow
159
- { run: ['execute_action', () => sub, generators.gClient.id, 'GENERATOR_MQTT_PUBLISH',
160
- { topic: 'test', payload: 'hello', qos: '0' }] },
161
- ```
162
-
163
- ## Recording Automations
164
-
165
- In BRICKS Editor Preview mode:
166
-
167
- 1. Perform operations normally
168
- 2. Open menu (right-bottom corner)
169
- 3. Select "Record Events as Automation"
170
- 4. Generated automation appears in Automations list
171
-
172
- ## Running Automations
173
-
174
- ### Manual Run
175
-
176
- `Menu` → `Automations` → Select automation → `Run`
177
-
178
- ### On Launch
179
-
180
- `Bind Device` → `Select Automation` (only `launch` or `cron` types)
181
-
182
- ### Scheduled (Cron)
183
-
184
- `Bind Device` → `Cron Automation` (allows multi-select)
185
-
186
- Use [crontab.guru](https://crontab.guru) to build cron expressions.
187
-
188
- ## Screenshot Testing
189
-
190
- Visual regression testing with screenshot comparison:
191
-
192
- ```typescript
193
- {
194
- __typename: 'TestCase',
195
- id: makeId('test_case'),
196
- name: 'Match dashboard screenshot',
197
- run: ['match_screenshot', 'dashboard-initial-state', 0.01, 3],
198
- exit_on_failed: true,
199
- commented: false,
200
- pre_delay: 500, // Wait for UI to settle
201
- post_delay: 0,
202
- jump_cond: [],
203
- }
204
- ```
205
-
206
- Screenshots can be stored:
207
-
208
- - Local file system
209
- - Media Flow workspace
210
-
211
- First run captures baseline. Use "Run with Update" to update baseline.
212
-
213
- ## Module Support
214
-
215
- Automations work with Modules. Use Manual Run in Preview mode for module testing.
216
-
217
- ## Important Notes
218
-
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`.
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.
222
- - **handler in execute_action**: Pass the entity's `.id` string (e.g., `bricks.bInput.id`), not a getter function.
223
-
224
- ## Best Practices
225
-
226
- 1. **Test culture**: Create automations for every significant flow
227
- 2. **CI/CD integration**: Use `launch` automations for deployment validation
228
- 3. **Incremental waits**: Use `wait_until_property_change` with appropriate timeouts
229
- 4. **Visual testing**: Add screenshot comparisons for critical UI states
230
- 5. **Cron monitoring**: Schedule health checks for production displays
231
- 6. **Isolation**: Each automation should be independent and idempotent
232
- 7. **UI-first testing**: Simulate real user interactions (text input, button press) rather than calling generators directly
@@ -1,245 +0,0 @@
1
- # Buttress (Remote Inference)
2
-
3
- Backend system for offloading compute-intensive AI generator tasks from BRICKS devices to more powerful machines.
4
-
5
- ## Purpose
6
-
7
- When mobile devices or embedded systems lack hardware for local AI inference (LLM, speech-to-text), Buttress transparently delegates work to a server with appropriate resources (GPU).
8
-
9
- ## How It Works
10
-
11
- 1. **Capability Exchange**: Client and server share hardware capabilities
12
- 2. **Strategy Selection**: System decides local vs. remote execution
13
- 3. **Transparent Offloading**: Generator operates same way, execution happens remotely
14
-
15
- ## Supported Generators
16
-
17
- - LLM (GGML) (LlmMlx.ts) - Local Large Language Model inference with GGML
18
- - LLM (MLX) (LlmGgml.ts) - Local Large Language Model inference with MLX
19
- - Speech-to-Text (GGML) (SpeechToTextGgml.ts) - Local Speech-to-Text inference with GGML
20
-
21
- ## Client Configuration
22
-
23
- In generator properties, configure `buttressConnectionSettings`:
24
-
25
- | Setting | Description |
26
- |---------|-------------|
27
- | `enabled` | Toggle Buttress offloading |
28
- | `autoDiscoverType` | `auto` (LAN auto-discovery, recommended) or `manual` (typed URL) |
29
- | `url` | Server URL (`manual` mode only — leave empty for `auto`) |
30
- | `fallbackType` | If Buttress is unreachable: `use-local` runs locally, `no-op` blocks the load |
31
- | `strategy` | Execution preference (see below) |
32
-
33
- The launcher provides the access token automatically — there is **no user-facing access-token setting**. In `auto` mode the launcher discovers servers bound to the device's workspace and uses its workspace-scoped JWT; in `manual` mode it sends the same JWT only when the typed URL belongs to a server bound to the same workspace (verified against the server's `/buttress/info`).
34
-
35
- ### `autoDiscoverType` options
36
-
37
- | Mode | When to use | What the device does |
38
- |------|-------------|----------------------|
39
- | `auto` | LAN deployment with a workspace-bound buttress-server | Listens for UDP announcements and picks the strongest server bound to its workspace; reconnects automatically when the workspace flips |
40
- | `manual` | Internet-reachable server, mixed networks, or a public/unbound server | Connects to the typed `url` directly; sends a token only when the server is bound to the same workspace |
41
-
42
- ### Strategy options
43
-
44
- | Strategy | Description |
45
- |----------|-------------|
46
- | `prefer-local` | Use local if capable, fallback to Buttress |
47
- | `prefer-buttress` | Use Buttress if available, fallback to local |
48
- | `prefer-best` | Auto-select based on capability comparison |
49
-
50
- ## Generator Configuration Examples
51
-
52
- ### Auto-discovery (recommended)
53
-
54
- Workspace-bound launcher + workspace-bound buttress-server on the same LAN. No URL needed — discovery picks the highest-scoring server that runs the requested backend.
55
-
56
- ```typescript
57
- import { makeId } from 'bricks-ctor'
58
-
59
- const llmGenerator: GeneratorLLM = {
60
- __typename: 'Generator',
61
- templateKey: 'GENERATOR_LLM',
62
- id: makeId('generator'),
63
- title: 'Chat LLM',
64
- description: '',
65
- property: {
66
- modelUrl: 'https://huggingface.co/ggml-org/gemma-3-12b-it-qat-GGUF/resolve/main/gemma-3-12b-it-qat-q4_0.gguf',
67
- contextSize: 8192,
68
- buttressConnectionSettings: {
69
- enabled: true,
70
- autoDiscoverType: 'auto',
71
- fallbackType: 'use-local',
72
- strategy: 'prefer-best',
73
- },
74
- },
75
- events: {},
76
- switches: [],
77
- }
78
- ```
79
-
80
- ### Manual URL
81
-
82
- Use when the server isn't on the launcher's broadcast domain (cross-subnet, internet, behind a reverse proxy) or you want to point at a specific public/unbound server.
83
-
84
- ```typescript
85
- buttressConnectionSettings: {
86
- enabled: true,
87
- autoDiscoverType: 'manual',
88
- url: 'http://192.168.1.100:2080',
89
- fallbackType: 'use-local',
90
- strategy: 'prefer-best',
91
- }
92
- ```
93
-
94
- > ⚠️ With `fallbackType: 'no-op'` the generator refuses to load locally if Buttress is unreachable. Use `'use-local'` whenever the device can also run the model standalone.
95
-
96
- ## Integrating a discovered buttress-server
97
-
98
- The ctor-desktop "Local Devices" panel (and the `bricks buttress scan` CLI) can hand you a server's identity, workspace, and announced generator caps. When the user asks to integrate one:
99
-
100
- 1. **Confirm workspace match.** The discovery message says whether the server's workspace matches this project's. If it doesn't, do NOT add the integration — instruct the user to run `bricks buttress unbind && bricks buttress bind` from this workspace's owner CLI on the server host. The launcher won't trust a cross-workspace server.
101
-
102
- 2. **Map announced types to generator templates.** For each `generators[].type` in the announce, target the matching templateKey (create the generator if absent):
103
-
104
- | Announced type | templateKey | Default model |
105
- |----------------|------------------------------|---------------|
106
- | `ggml-llm` | `GENERATOR_LLM` | `ggml-org/gemma-3-12b-it-qat-GGUF` (≥20 GB usable) or `ggml-org/gpt-oss-20b-GGUF` (~12 GB usable) |
107
- | `mlx-llm` | `GENERATOR_MLX_LLM` | `mlx-community/Qwen3-4B-4bit` (or a larger 4-bit quant if `usableBytes` allows) |
108
- | `ggml-stt` | `GENERATOR_SPEECH_INFERENCE` | `BricksDisplay/whisper-ggml` (filename `ggml-small-q8_0.bin`) |
109
-
110
- Pick a model that fits the announced `usableBytes`. Set `contextSize` to match.
111
-
112
- 3. **Use the canonical auto-discovery config** from "Auto-discovery (recommended)" above. Don't switch to manual mode just because the server is on the LAN — auto mode picks the workspace-bound server automatically and rebinds when the device's workspace flips.
113
-
114
- ### Real-device caveat
115
-
116
- Buttress LAN auto-discovery uses native UDP via `react-native-jsi-udp`. The iOS Simulator silently fails to bind UDP, so auto mode is a no-op there. With `fallbackType: 'use-local'` the generator falls back to local inference in the simulator — dev/test stays functional. **Validate the buttress path itself only when deploying to a real Foundation device; don't gate the build on simulator validation.**
117
-
118
- ## Server Setup
119
-
120
- ### Requirements
121
- - [Bun](https://bun.sh) v1.3+
122
- - GPU recommended for LLM/STT
123
-
124
- ### Installation
125
-
126
- ```bash
127
- bun add -g @fugood/buttress-server
128
- ```
129
-
130
- ### Start Server
131
-
132
- ```bash
133
- bricks-buttress
134
- # or with config
135
- bricks-buttress --config ./config.toml
136
- ```
137
-
138
- ### CLI Options
139
-
140
- | Option | Description |
141
- |--------|-------------|
142
- | `-p, --port` | Port (default: 2080) |
143
- | `-c, --config` | TOML config file path |
144
- | `-v, --version` | Show version |
145
- | `-h, --help` | Show help |
146
-
147
- ### Environment Variables
148
-
149
- | Variable | Description |
150
- |----------|-------------|
151
- | `HF_TOKEN` | Hugging Face token for model downloads |
152
- | `ENABLE_OPENAI_COMPAT_ENDPOINT` | Set to `1` for OpenAI-compatible API |
153
- | `BRICKS_BUTTRESS_STATE_DIR` | Override the workspace state directory (default `~/.bricks-cli/buttress`) |
154
-
155
- ## Bind the Server to a Workspace
156
-
157
- To use `autoDiscoverType: 'auto'` — and to require workspace-scoped JWT auth — pair the buttress-server with a BRICKS workspace using the `bricks buttress` CLI commands. An unbound server stays in legacy public mode and accepts any LAN client.
158
-
159
- ### One-time bind
160
-
161
- ```bash
162
- # Log into the cloud bricks-server with the workspace owner's account
163
- bricks auth login
164
-
165
- # Pair the buttress-server running on this machine with the active workspace
166
- bricks buttress bind
167
-
168
- # Restart bricks-buttress so it picks up the new state.json
169
- ```
170
-
171
- `bricks buttress bind` writes `~/.bricks-cli/buttress/state.json` containing the workspace id, the issuer's Ed25519 public key, and a stable `serverId` (defaults to `buttress-<machineId>`). Override location with `--state-dir` or `$BRICKS_BUTTRESS_STATE_DIR`. For headless setups, use `bricks buttress bind --print` to emit state.json to stdout.
172
-
173
- ### Verify and manage
174
-
175
- ```bash
176
- # Show local binding + workspace-side bound list
177
- bricks buttress status
178
-
179
- # Discover buttress-servers on the LAN (with version, auth state, generator caps)
180
- bricks buttress scan
181
-
182
- # Issue a long-lived workspace access token (CI / ctor agents that already hold a workspace token)
183
- bricks buttress issue-token --ttl 86400
184
-
185
- # Detach this server from the workspace
186
- bricks buttress unbind
187
- ```
188
-
189
- After binding, launchers in the same workspace will auto-discover this server; manual-mode generators will only send their access token if the server's reported workspace matches their own.
190
-
191
- ## Server Configuration (TOML)
192
-
193
- ```toml
194
- [server]
195
- port = 2080
196
-
197
- [runtime]
198
- cache_dir = "./.buttress-cache"
199
- n_threads = 6
200
- flash_attn_type = "on"
201
- cache_type_k = "q8_0"
202
- cache_type_v = "q8_0"
203
-
204
- # LLM Generator
205
- [[generators]]
206
- type = "ggml-llm"
207
- [generators.backend]
208
- variant_preference = ["cuda", "vulkan", "default"]
209
- gpu_memory_fraction = 0.95
210
- [generators.model]
211
- repo_id = "ggml-org/gemma-3-12b-it-qat-GGUF"
212
- download = true
213
- n_ctx = 8192
214
-
215
- # STT Generator
216
- [[generators]]
217
- type = "ggml-stt"
218
- [generators.backend]
219
- variant_preference = ["cuda", "vulkan", "default"]
220
- [generators.model]
221
- repo_id = "BricksDisplay/whisper-ggml"
222
- filename = "ggml-small-q8_0.bin"
223
- download = true
224
- use_gpu = true
225
- ```
226
-
227
- ## Use Cases
228
-
229
- ### Resource-Constrained Devices
230
- Digital signage with basic hardware offloads LLM to powerful server.
231
-
232
- ### Shared GPU Resources
233
- Multiple devices share single GPU server for inference.
234
-
235
- ### Development Testing
236
- Test AI features on lightweight dev machines by connecting to beefy server.
237
-
238
- ## Best Practices
239
-
240
- 1. **Network reliability**: Ensure stable LAN connection to Buttress server
241
- 2. **Fallback strategy**: Configure appropriate fallback for critical features
242
- 3. **Server monitoring**: Monitor Buttress server resource usage
243
- 4. **Model consistency**: Ensure client and server use compatible models
244
- 5. **Security**: Run Buttress on private network, not public internet
245
- 6. **Latency awareness**: Account for network latency in UX design