@fugood/bricks-project 2.25.0-beta.22 → 2.25.0-beta.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/compile/index.ts CHANGED
@@ -1194,7 +1194,7 @@ export const compile = async (app: Application) => {
1194
1194
  ...compileRemoteUpdate(data.remoteUpdate),
1195
1195
  routing: data.routing,
1196
1196
  schema: data.schema,
1197
- type: data.type,
1197
+ type: data.type === 'boolean' ? 'bool' : data.type,
1198
1198
  ...compileKind(data.kind),
1199
1199
  value: compileProperty(data.value, `(data: ${dataId}, subspace ${subspaceId})`),
1200
1200
  event_map: compileEvents('PROPERTY_BANK', data.events || {}, {
@@ -1460,5 +1460,7 @@ export const compile = async (app: Application) => {
1460
1460
 
1461
1461
  export const checkConfig = async (configPath: string) => {
1462
1462
  const { sh } = await import('../tools/_shell')
1463
- await sh`bricks app check-config ${configPath}`
1463
+ // --validate-automation surfaces broken automation_map / test_map refs early,
1464
+ // which catches agent-authored automations that reference deleted bricks.
1465
+ await sh`bricks app check-config --validate-automation ${configPath}`
1464
1466
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@fugood/bricks-project",
3
- "version": "2.25.0-beta.22",
3
+ "version": "2.25.0-beta.24",
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.21",
10
+ "@fugood/bricks-cli": "^2.25.0-beta.24",
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.22",
3
+ "version": "2.25.0-beta.24",
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.21",
10
+ "@fugood/bricks-cli": "^2.25.0-beta.24",
11
11
  "@huggingface/gguf": "^0.3.2",
12
12
  "@iarna/toml": "^3.0.0",
13
13
  "@modelcontextprotocol/sdk": "^1.15.0",
@@ -118,6 +118,16 @@ const testLoginFlow: AutomationTest = {
118
118
  | `match_screenshot` | `[name, threshold?, maxRetry?]` | Screenshot compare |
119
119
  | `delay` | `[subspace?, property?, defaultValue?]` | Delay execution |
120
120
 
121
+ In project TypeScript source, pass entity getters for BRICKS entities:
122
+
123
+ ```typescript
124
+ run: ['brick_press', () => mainSubspace, () => bricks.bSubmitButton]
125
+ run: ['wait_until_canvas_change', () => mainSubspace, () => canvases.cDone, 5000]
126
+ run: ['assert_property', () => mainSubspace, () => data.dStep, 'done']
127
+ ```
128
+
129
+ The compiler resolves these getters to the current generated IDs.
130
+
121
131
  ### execute_action Params
122
132
 
123
133
  The `params` object in `execute_action` uses **runtime event property keys** from `event-props.ts`, NOT the action config `input` names from type definitions.
@@ -208,6 +218,7 @@ Automations work with Modules. Use Manual Run in Preview mode for module testing
208
218
 
209
219
  - **Automation map key**: Always use `'AUTOMATION_MAP_DEFAULT'` as the automation map ID (not `makeId()`). The preview test runner reads from `automationMap['AUTOMATION_MAP_DEFAULT']?.map`.
210
220
  - **Valid makeId types**: Use `'test'` for AutomationTest, `'test_case'` for TestCase, `'test_var'` for TestVariable. Do NOT use `'automation_test'` or `'automation_test_map'`.
221
+ - **Entity references in run arrays**: Use getter references (`() => subspace`, `() => bricks.bButton`, `() => data.dValue`) in TypeScript source so compile resolves fresh IDs.
211
222
  - **handler in execute_action**: Pass the entity's `.id` string (e.g., `bricks.bInput.id`), not a getter function.
212
223
 
213
224
  ## Best Practices
@@ -182,6 +182,8 @@ const triggerCalc: EventAction = {
182
182
  }
183
183
  ```
184
184
 
185
+ When the same chain writes a calc input (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).
186
+
185
187
  ## Best Practices
186
188
 
187
189
  1. **Avoid circular deps**: Set non-triggering inputs (`trigger: false`) or use `manual` mode
package/tools/_shell.ts CHANGED
@@ -29,6 +29,7 @@ class Sh implements PromiseLike<ShResult> {
29
29
  private _cwd: string | undefined
30
30
  private _mode: Mode = 'default'
31
31
  private _throw = true
32
+ private _env: NodeJS.ProcessEnv | undefined
32
33
  private _promise: Promise<ShResult> | null = null
33
34
 
34
35
  constructor(private readonly args: string[]) {}
@@ -48,6 +49,11 @@ class Sh implements PromiseLike<ShResult> {
48
49
  return this
49
50
  }
50
51
 
52
+ env(extra: NodeJS.ProcessEnv): this {
53
+ this._env = { ...this._env, ...extra }
54
+ return this
55
+ }
56
+
51
57
  async text(): Promise<string> {
52
58
  // If no explicit quiet was requested, capture stdout/stderr without
53
59
  // forwarding them to the parent's streams (matches Bun's `.text()`).
@@ -79,7 +85,8 @@ class Sh implements PromiseLike<ShResult> {
79
85
  ? ['ignore', 'pipe', 'pipe']
80
86
  : ['inherit', 'pipe', 'pipe']
81
87
 
82
- const proc = spawn(cmd, rest, { cwd: this._cwd, stdio })
88
+ const env = this._env ? { ...process.env, ...this._env } : undefined
89
+ const proc = spawn(cmd, rest, { cwd: this._cwd, stdio, env })
83
90
 
84
91
  const outChunks: Buffer[] = []
85
92
  const errChunks: Buffer[] = []
@@ -3,16 +3,21 @@ import { readFile } from 'node:fs/promises'
3
3
  import { z } from 'zod'
4
4
  import { sh } from '../_shell'
5
5
 
6
+ // Disable ANSI color codes from spawned tools so MCP text output stays readable
7
+ // (the host renders raw text; escape sequences leak into the result otherwise).
8
+ const noColorEnv = { FORCE_COLOR: '0', NO_COLOR: '1' }
9
+
6
10
  export function register(server: McpServer, projectDir: string) {
7
11
  const { dirname } = import.meta
8
12
 
9
13
  server.tool('compile', {}, async () => {
10
- let log = ''
14
+ let log = 'Type checking & Compiling...\n'
11
15
  try {
12
- log += 'Type checking & Compiling...'
13
- log += await sh`bun compile`.cwd(projectDir).text()
14
- } catch (err) {
15
- log += `${err.stdout.toString()}\n${err.stderr.toString()}`
16
+ log += await sh`bun compile`.cwd(projectDir).env(noColorEnv).text()
17
+ } catch (err: any) {
18
+ const stdout = err.stdout?.toString() ?? ''
19
+ const stderr = err.stderr?.toString() ?? ''
20
+ log += [stdout, stderr].filter(Boolean).join('\n')
16
21
  }
17
22
  return {
18
23
  content: [{ type: 'text', text: log }],
@@ -65,9 +70,12 @@ export function register(server: McpServer, projectDir: string) {
65
70
  if (testTitleLike) args.push('--test-title-like', testTitleLike)
66
71
  log = await sh`bunx --bun electron ${toolsDir}/preview-main.mjs ${args}`
67
72
  .cwd(projectDir)
73
+ .env(noColorEnv)
68
74
  .text()
69
- } catch (err) {
70
- log = `${err.stdout.toString()}\n${err.stderr.toString()}`
75
+ } catch (err: any) {
76
+ const stdout = err.stdout?.toString() ?? ''
77
+ const stderr = err.stderr?.toString() ?? ''
78
+ log = [stdout, stderr].filter(Boolean).join('\n')
71
79
  error = true
72
80
  }
73
81
  let screenshotBase64: string | null = null
@@ -2,9 +2,12 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
2
2
  import { z } from 'zod'
3
3
  import { sh } from '../_shell'
4
4
 
5
+ // MCP results are rendered as raw text — disable ANSI colors from the child.
6
+ const noColorEnv = { FORCE_COLOR: '0', NO_COLOR: '1' }
7
+
5
8
  const runBricks = async (projectDir: string, ...args: string[]) => {
6
9
  try {
7
- return await sh`bunx bricks ${args}`.cwd(projectDir).text()
10
+ return await sh`bunx bricks ${args}`.cwd(projectDir).env(noColorEnv).text()
8
11
  } catch (err: any) {
9
12
  throw new Error(err.stderr?.toString() || err.message)
10
13
  }
package/types/common.ts CHANGED
@@ -12,7 +12,7 @@ export interface Brick {
12
12
  description?: string
13
13
  hideShortRef?: boolean
14
14
  property?: {}
15
- events: {}
15
+ events?: {}
16
16
  outlets?: {}
17
17
  animation?: {}
18
18
  switches?: Array<SwitchDef>
@@ -33,7 +33,7 @@ export interface Generator {
33
33
  hideShortRef?: boolean
34
34
  localSyncRunMode?: LocalSyncStrategy
35
35
  property?: {}
36
- events: {}
36
+ events?: {}
37
37
  outlets?: {}
38
38
  switches?: Array<SwitchDef>
39
39
  }
@@ -0,0 +1,57 @@
1
+ /* Auto generated by build script */
2
+ import type { Data } from '../data'
3
+ import type { DataCalculation } from '../data-calc'
4
+
5
+ // Shared helpers — every generated DataCommand{Name} reuses these to describe
6
+ // its narrowed inputs/outputs, so the per-command files stay short.
7
+ export type DataCalcInput<K extends string = string, T = any> = {
8
+ key: K
9
+ source: (() => DataCalculationData | DataCommand) | T
10
+ sourceKey: string
11
+ trigger?: boolean
12
+ }
13
+
14
+ export type DataCalcOutput<K extends string = string> = {
15
+ key: K
16
+ target: () => DataCalculationData | DataCommand
17
+ targetKey: string
18
+ }
19
+
20
+ export interface DataCalculationData {
21
+ __typename: 'DataCalculationData'
22
+ title?: string
23
+ description?: string
24
+ hideShortRef?: boolean
25
+ data: () => Data
26
+ // 'change' is the only valid input port on a data node; the source must be
27
+ // another node (no inline literals), hence `never` for the second type arg.
28
+ inputs: Array<DataCalcInput<'change', never>>
29
+ outputs: Array<DataCalcOutput<'value'>>
30
+ }
31
+
32
+ export interface DataCommand {
33
+ __typename: 'DataCommand'
34
+ __commandName: string
35
+ id: string
36
+ title?: string
37
+ description?: string
38
+ hideShortRef?: boolean
39
+ inputs: Array<DataCalcInput>
40
+ outputs: Array<DataCalcOutput>
41
+ }
42
+
43
+ export type DataCalculationMap = DataCalculation & {
44
+ __typename: 'DataCalculationMap'
45
+ nodes: Array<DataCalculationData | DataCommand>
46
+ editorInfo: Array<{
47
+ node: DataCalculationData | DataCommand
48
+ position: { x: number; y: number }
49
+ points: Array<{
50
+ source: DataCalculationData | DataCommand
51
+ sourceOutputKey: string
52
+ target: DataCalculationData | DataCommand
53
+ targetInputKey: string
54
+ positions: Array<{ x: number; y: number }>
55
+ }>
56
+ }>
57
+ }