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

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 (190) hide show
  1. package/package.json +4 -28
  2. package/tools/deploy.ts +19 -176
  3. package/tools/mcp-server.ts +16 -33
  4. package/tools/postinstall.ts +21 -292
  5. package/tools/pull.ts +15 -195
  6. package/tools/push-config.ts +18 -113
  7. package/tools/simulator.ts +19 -148
  8. package/compile/__tests__/config-diff.test.js +0 -100
  9. package/compile/__tests__/index.test.js +0 -461
  10. package/compile/__tests__/util.test.js +0 -450
  11. package/compile/action-name-map.ts +0 -1079
  12. package/compile/config-diff.ts +0 -155
  13. package/compile/index.ts +0 -1594
  14. package/compile/util.ts +0 -482
  15. package/index.ts +0 -6
  16. package/skills/bricks-ctor/SKILL.md +0 -38
  17. package/skills/bricks-ctor/references/animation.md +0 -160
  18. package/skills/bricks-ctor/references/architecture-patterns.md +0 -88
  19. package/skills/bricks-ctor/references/automations.md +0 -232
  20. package/skills/bricks-ctor/references/buttress.md +0 -245
  21. package/skills/bricks-ctor/references/data-calculation.md +0 -252
  22. package/skills/bricks-ctor/references/local-sync.md +0 -129
  23. package/skills/bricks-ctor/references/media-flow.md +0 -165
  24. package/skills/bricks-ctor/references/remote-data-bank.md +0 -196
  25. package/skills/bricks-ctor/references/simulator.md +0 -132
  26. package/skills/bricks-ctor/references/source-editing-tools.md +0 -81
  27. package/skills/bricks-ctor/references/standby-transition.md +0 -124
  28. package/skills/bricks-ctor/references/verification-toolchain.md +0 -200
  29. package/skills/bricks-design/SKILL.md +0 -171
  30. package/skills/bricks-design/references/architecture-truths.md +0 -132
  31. package/skills/bricks-design/references/avoiding-complexity.md +0 -91
  32. package/skills/bricks-design/references/design-critique.md +0 -195
  33. package/skills/bricks-design/references/design-languages.md +0 -265
  34. package/skills/bricks-design/references/performance.md +0 -116
  35. package/skills/bricks-design/references/presentation-and-slideshow.md +0 -137
  36. package/skills/bricks-design/references/translating-inputs.md +0 -152
  37. package/skills/bricks-design/references/variations-and-tweaks.md +0 -124
  38. package/skills/bricks-design/references/when-the-brief-is-branded.md +0 -284
  39. package/skills/bricks-design/references/when-the-brief-is-vague.md +0 -85
  40. package/skills/bricks-design/references/workflow.md +0 -134
  41. package/skills/bricks-ux/SKILL.md +0 -114
  42. package/skills/bricks-ux/references/accessibility.md +0 -162
  43. package/skills/bricks-ux/references/flow-states.md +0 -175
  44. package/skills/bricks-ux/references/interaction-archetypes.md +0 -189
  45. package/skills/bricks-ux/references/monitoring-screens.md +0 -153
  46. package/skills/bricks-ux/references/pressable-composition.md +0 -126
  47. package/skills/bricks-ux/references/user-journey.md +0 -168
  48. package/skills/bricks-ux/references/ux-critique.md +0 -256
  49. package/skills/rive-marketplace/SKILL.md +0 -99
  50. package/tools/__tests__/_cli-error.test.ts +0 -35
  51. package/tools/__tests__/_mcp-config.test.ts +0 -67
  52. package/tools/__tests__/pull.test.ts +0 -108
  53. package/tools/_cli-error.ts +0 -17
  54. package/tools/_edits-log.ts +0 -41
  55. package/tools/_git-author.ts +0 -37
  56. package/tools/_last-pushed-commit.ts +0 -28
  57. package/tools/_mcp-config.ts +0 -42
  58. package/tools/_shell.ts +0 -180
  59. package/tools/icons/.gitattributes +0 -1
  60. package/tools/icons/fa6pro-glyphmap.json +0 -4686
  61. package/tools/icons/fa6pro-meta.json +0 -1
  62. package/tools/mcp-env.ts +0 -13
  63. package/tools/mcp-tools/__tests__/data-calc-editing.test.js +0 -516
  64. package/tools/mcp-tools/__tests__/entry-editing.test.js +0 -866
  65. package/tools/mcp-tools/__tests__/huggingface.test.ts +0 -49
  66. package/tools/mcp-tools/__tests__/icons.test.ts +0 -21
  67. package/tools/mcp-tools/__tests__/mcp-env.test.js +0 -19
  68. package/tools/mcp-tools/_editing-helpers.ts +0 -98
  69. package/tools/mcp-tools/_verify.ts +0 -50
  70. package/tools/mcp-tools/compile.ts +0 -104
  71. package/tools/mcp-tools/data-calc-editing.ts +0 -1311
  72. package/tools/mcp-tools/entry-editing.ts +0 -2297
  73. package/tools/mcp-tools/huggingface.ts +0 -772
  74. package/tools/mcp-tools/icons.ts +0 -97
  75. package/tools/mcp-tools/lottie.ts +0 -102
  76. package/tools/mcp-tools/media.ts +0 -113
  77. package/tools/simulator-main.mjs +0 -488
  78. package/tools/simulator-preload.cjs +0 -16
  79. package/types/animation.d.ts +0 -116
  80. package/types/automation.d.ts +0 -231
  81. package/types/brick-base.d.ts +0 -80
  82. package/types/bricks/Camera.d.ts +0 -246
  83. package/types/bricks/Chart.d.ts +0 -372
  84. package/types/bricks/GenerativeMedia.d.ts +0 -290
  85. package/types/bricks/Icon.d.ts +0 -98
  86. package/types/bricks/Image.d.ts +0 -126
  87. package/types/bricks/Items.d.ts +0 -480
  88. package/types/bricks/Lottie.d.ts +0 -168
  89. package/types/bricks/Maps.d.ts +0 -262
  90. package/types/bricks/QrCode.d.ts +0 -117
  91. package/types/bricks/Rect.d.ts +0 -150
  92. package/types/bricks/RichText.d.ts +0 -131
  93. package/types/bricks/Rive.d.ts +0 -220
  94. package/types/bricks/Scene3D.d.ts +0 -676
  95. package/types/bricks/Sketch.d.ts +0 -256
  96. package/types/bricks/Slideshow.d.ts +0 -201
  97. package/types/bricks/Svg.d.ts +0 -99
  98. package/types/bricks/Text.d.ts +0 -148
  99. package/types/bricks/TextInput.d.ts +0 -242
  100. package/types/bricks/Video.d.ts +0 -242
  101. package/types/bricks/VideoStreaming.d.ts +0 -112
  102. package/types/bricks/WebRtcStream.d.ts +0 -65
  103. package/types/bricks/WebView.d.ts +0 -168
  104. package/types/bricks/index.d.ts +0 -23
  105. package/types/canvas.d.ts +0 -82
  106. package/types/common.d.ts +0 -141
  107. package/types/data-calc-command/base.d.ts +0 -57
  108. package/types/data-calc-command/collection.d.ts +0 -418
  109. package/types/data-calc-command/color.d.ts +0 -432
  110. package/types/data-calc-command/constant.d.ts +0 -50
  111. package/types/data-calc-command/datetime.d.ts +0 -147
  112. package/types/data-calc-command/file.d.ts +0 -129
  113. package/types/data-calc-command/index.d.ts +0 -13
  114. package/types/data-calc-command/iteratee.d.ts +0 -23
  115. package/types/data-calc-command/logictype.d.ts +0 -190
  116. package/types/data-calc-command/math.d.ts +0 -275
  117. package/types/data-calc-command/object.d.ts +0 -119
  118. package/types/data-calc-command/sandbox.d.ts +0 -66
  119. package/types/data-calc-command/string.d.ts +0 -407
  120. package/types/data-calc-script.d.ts +0 -21
  121. package/types/data-calc.d.ts +0 -12
  122. package/types/data.d.ts +0 -97
  123. package/types/generators/AlarmClock.d.ts +0 -110
  124. package/types/generators/Assistant.d.ts +0 -640
  125. package/types/generators/BleCentral.d.ts +0 -247
  126. package/types/generators/BlePeripheral.d.ts +0 -208
  127. package/types/generators/CanvasMap.d.ts +0 -74
  128. package/types/generators/CastlesPay.d.ts +0 -87
  129. package/types/generators/DataBank.d.ts +0 -160
  130. package/types/generators/File.d.ts +0 -432
  131. package/types/generators/GraphQl.d.ts +0 -132
  132. package/types/generators/Http.d.ts +0 -222
  133. package/types/generators/HttpServer.d.ts +0 -230
  134. package/types/generators/Information.d.ts +0 -103
  135. package/types/generators/Intent.d.ts +0 -168
  136. package/types/generators/Iterator.d.ts +0 -108
  137. package/types/generators/Keyboard.d.ts +0 -105
  138. package/types/generators/LlmAnthropicCompat.d.ts +0 -212
  139. package/types/generators/LlmAppleBuiltin.d.ts +0 -159
  140. package/types/generators/LlmGgml.d.ts +0 -903
  141. package/types/generators/LlmMediaTekNeuroPilot.d.ts +0 -235
  142. package/types/generators/LlmMlx.d.ts +0 -228
  143. package/types/generators/LlmOnnx.d.ts +0 -213
  144. package/types/generators/LlmOpenAiCompat.d.ts +0 -312
  145. package/types/generators/LlmQualcommAiEngine.d.ts +0 -247
  146. package/types/generators/Mcp.d.ts +0 -637
  147. package/types/generators/McpServer.d.ts +0 -289
  148. package/types/generators/MediaFlow.d.ts +0 -170
  149. package/types/generators/MqttBroker.d.ts +0 -141
  150. package/types/generators/MqttClient.d.ts +0 -141
  151. package/types/generators/Question.d.ts +0 -408
  152. package/types/generators/RealtimeTranscription.d.ts +0 -287
  153. package/types/generators/RerankerGgml.d.ts +0 -195
  154. package/types/generators/SerialPort.d.ts +0 -151
  155. package/types/generators/SoundPlayer.d.ts +0 -94
  156. package/types/generators/SoundRecorder.d.ts +0 -139
  157. package/types/generators/SpeechToTextGgml.d.ts +0 -424
  158. package/types/generators/SpeechToTextOnnx.d.ts +0 -236
  159. package/types/generators/SpeechToTextPlatform.d.ts +0 -85
  160. package/types/generators/SqLite.d.ts +0 -159
  161. package/types/generators/Step.d.ts +0 -107
  162. package/types/generators/SttAppleBuiltin.d.ts +0 -153
  163. package/types/generators/Tcp.d.ts +0 -126
  164. package/types/generators/TcpServer.d.ts +0 -147
  165. package/types/generators/TextToSpeechAppleBuiltin.d.ts +0 -127
  166. package/types/generators/TextToSpeechGgml.d.ts +0 -221
  167. package/types/generators/TextToSpeechOnnx.d.ts +0 -178
  168. package/types/generators/TextToSpeechOpenAiLike.d.ts +0 -121
  169. package/types/generators/ThermalPrinter.d.ts +0 -193
  170. package/types/generators/Tick.d.ts +0 -83
  171. package/types/generators/Udp.d.ts +0 -120
  172. package/types/generators/VadGgml.d.ts +0 -260
  173. package/types/generators/VadOnnx.d.ts +0 -231
  174. package/types/generators/VadTraditional.d.ts +0 -138
  175. package/types/generators/VectorStore.d.ts +0 -257
  176. package/types/generators/Watchdog.d.ts +0 -107
  177. package/types/generators/WebCrawler.d.ts +0 -103
  178. package/types/generators/WebRtc.d.ts +0 -181
  179. package/types/generators/WebSocket.d.ts +0 -148
  180. package/types/generators/index.d.ts +0 -57
  181. package/types/index.d.ts +0 -13
  182. package/types/subspace.d.ts +0 -60
  183. package/types/switch.d.ts +0 -51
  184. package/types/system.d.ts +0 -707
  185. package/utils/__tests__/calc.test.js +0 -25
  186. package/utils/__tests__/id.test.js +0 -154
  187. package/utils/calc.ts +0 -130
  188. package/utils/data.ts +0 -495
  189. package/utils/event-props.ts +0 -912
  190. 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