@fugood/bricks-project 2.24.0-beta.9 → 2.24.1-beta.0

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 (125) hide show
  1. package/compile/action-name-map.ts +38 -0
  2. package/compile/index.ts +460 -158
  3. package/compile/util.ts +2 -0
  4. package/package.json +8 -3
  5. package/package.json.bak +28 -0
  6. package/skills/{bricks-project → bricks-ctor}/SKILL.md +2 -2
  7. package/skills/{bricks-project → bricks-ctor}/rules/animation.md +1 -1
  8. package/skills/{bricks-project → bricks-ctor}/rules/architecture-patterns.md +7 -0
  9. package/skills/{bricks-project → bricks-ctor}/rules/buttress.md +10 -7
  10. package/skills/{bricks-project → bricks-ctor}/rules/data-calculation.md +3 -2
  11. package/skills/{bricks-project → bricks-ctor}/rules/local-sync.md +2 -2
  12. package/skills/{bricks-project → bricks-ctor}/rules/media-flow.md +3 -3
  13. package/skills/{bricks-project → bricks-ctor}/rules/remote-data-bank.md +6 -6
  14. package/skills/{bricks-project → bricks-ctor}/rules/standby-transition.md +1 -1
  15. package/skills/bricks-design/LICENSE.txt +180 -0
  16. package/skills/bricks-design/SKILL.md +66 -0
  17. package/tools/_git-author.ts +29 -0
  18. package/tools/_shell.ts +173 -0
  19. package/tools/deploy.ts +91 -23
  20. package/tools/icons/fa6pro-meta.json +3669 -26125
  21. package/tools/mcp-server.ts +11 -878
  22. package/tools/mcp-tools/compile.ts +92 -0
  23. package/tools/mcp-tools/huggingface.ts +762 -0
  24. package/tools/mcp-tools/icons.ts +70 -0
  25. package/tools/mcp-tools/lottie.ts +102 -0
  26. package/tools/mcp-tools/media.ts +110 -0
  27. package/tools/postinstall.ts +143 -40
  28. package/tools/preview-main.mjs +135 -2
  29. package/tools/preview.ts +68 -33
  30. package/tools/pull.ts +56 -32
  31. package/tsconfig.json +16 -0
  32. package/types/animation.ts +4 -0
  33. package/types/automation.ts +4 -1
  34. package/types/brick-base.ts +1 -1
  35. package/types/bricks/Camera.ts +47 -12
  36. package/types/bricks/Chart.ts +9 -3
  37. package/types/bricks/GenerativeMedia.ts +29 -13
  38. package/types/bricks/Icon.ts +8 -4
  39. package/types/bricks/Image.ts +9 -5
  40. package/types/bricks/Items.ts +28 -14
  41. package/types/bricks/Lottie.ts +14 -6
  42. package/types/bricks/Maps.ts +15 -7
  43. package/types/bricks/QrCode.ts +8 -4
  44. package/types/bricks/Rect.ts +44 -5
  45. package/types/bricks/RichText.ts +8 -4
  46. package/types/bricks/Rive.ts +20 -10
  47. package/types/bricks/Slideshow.ts +19 -9
  48. package/types/bricks/Svg.ts +7 -3
  49. package/types/bricks/Text.ts +8 -4
  50. package/types/bricks/TextInput.ts +22 -12
  51. package/types/bricks/Video.ts +10 -6
  52. package/types/bricks/VideoStreaming.ts +7 -3
  53. package/types/bricks/WebRtcStream.ts +6 -2
  54. package/types/bricks/WebView.ts +11 -7
  55. package/types/canvas.ts +2 -0
  56. package/types/common.ts +15 -8
  57. package/types/data-calc-command.ts +2 -0
  58. package/types/data-calc.ts +1 -0
  59. package/types/data.ts +2 -0
  60. package/types/generators/AlarmClock.ts +16 -10
  61. package/types/generators/Assistant.ts +68 -17
  62. package/types/generators/BleCentral.ts +30 -10
  63. package/types/generators/BlePeripheral.ts +10 -6
  64. package/types/generators/CanvasMap.ts +9 -5
  65. package/types/generators/CastlesPay.ts +14 -6
  66. package/types/generators/DataBank.ts +43 -8
  67. package/types/generators/File.ts +108 -29
  68. package/types/generators/GraphQl.ts +11 -5
  69. package/types/generators/Http.ts +32 -9
  70. package/types/generators/HttpServer.ts +22 -14
  71. package/types/generators/Information.ts +8 -4
  72. package/types/generators/Intent.ts +14 -4
  73. package/types/generators/Iterator.ts +14 -10
  74. package/types/generators/Keyboard.ts +26 -12
  75. package/types/generators/LlmAnthropicCompat.ts +32 -10
  76. package/types/generators/LlmAppleBuiltin.ts +24 -9
  77. package/types/generators/LlmGgml.ts +139 -30
  78. package/types/generators/LlmMediaTekNeuroPilot.ts +235 -0
  79. package/types/generators/LlmMlx.ts +227 -0
  80. package/types/generators/LlmOnnx.ts +33 -13
  81. package/types/generators/LlmOpenAiCompat.ts +46 -10
  82. package/types/generators/LlmQualcommAiEngine.ts +44 -12
  83. package/types/generators/Mcp.ts +374 -33
  84. package/types/generators/McpServer.ts +57 -18
  85. package/types/generators/MediaFlow.ts +37 -11
  86. package/types/generators/MqttBroker.ts +28 -10
  87. package/types/generators/MqttClient.ts +18 -8
  88. package/types/generators/Question.ts +12 -8
  89. package/types/generators/RealtimeTranscription.ts +107 -18
  90. package/types/generators/RerankerGgml.ts +42 -11
  91. package/types/generators/SerialPort.ts +17 -9
  92. package/types/generators/SoundPlayer.ts +9 -3
  93. package/types/generators/SoundRecorder.ts +23 -8
  94. package/types/generators/SpeechToTextGgml.ts +51 -17
  95. package/types/generators/SpeechToTextOnnx.ts +17 -10
  96. package/types/generators/SpeechToTextPlatform.ts +14 -6
  97. package/types/generators/SqLite.ts +19 -9
  98. package/types/generators/Step.ts +8 -4
  99. package/types/generators/SttAppleBuiltin.ts +21 -8
  100. package/types/generators/Tcp.ts +12 -8
  101. package/types/generators/TcpServer.ts +19 -13
  102. package/types/generators/TextToSpeechAppleBuiltin.ts +20 -7
  103. package/types/generators/TextToSpeechGgml.ts +28 -10
  104. package/types/generators/TextToSpeechOnnx.ts +18 -11
  105. package/types/generators/TextToSpeechOpenAiLike.ts +13 -7
  106. package/types/generators/ThermalPrinter.ts +12 -8
  107. package/types/generators/Tick.ts +10 -6
  108. package/types/generators/Udp.ts +16 -7
  109. package/types/generators/VadGgml.ts +50 -13
  110. package/types/generators/VadOnnx.ts +41 -11
  111. package/types/generators/VadTraditional.ts +27 -12
  112. package/types/generators/VectorStore.ts +32 -11
  113. package/types/generators/Watchdog.ts +18 -9
  114. package/types/generators/WebCrawler.ts +10 -6
  115. package/types/generators/WebRtc.ts +29 -15
  116. package/types/generators/WebSocket.ts +10 -6
  117. package/types/generators/index.ts +2 -0
  118. package/types/subspace.ts +4 -0
  119. package/types/system.ts +1 -1
  120. package/utils/event-props.ts +833 -1022
  121. package/api/index.ts +0 -1
  122. package/api/instance.ts +0 -213
  123. package/types/generators/TextToSpeechApple.ts +0 -113
  124. package/types/generators/TtsAppleBuiltin.ts +0 -105
  125. /package/skills/{bricks-project → bricks-ctor}/rules/automations.md +0 -0
@@ -0,0 +1,173 @@
1
+ import { spawn, type StdioOptions } from 'node:child_process'
2
+
3
+ // Template-literal shell helper replacing `$` from 'bun'. Only covers the
4
+ // ergonomics actually used in this package (see call sites in tools/*.ts).
5
+ //
6
+ // Usage:
7
+ // await sh`git status` // inherit stdio, throw on nonzero
8
+ // await sh`cd ${cwd} && git status`.quiet().nothrow()
9
+ // const out = await sh`git rev-parse HEAD`.text()
10
+ // await sh`bunx bricks ${args}`.cwd(dir).text()
11
+ //
12
+ // Notes:
13
+ // - Interpolated values are treated as single argv tokens (arrays expand to
14
+ // multiple tokens). Whitespace inside interpolated strings is preserved.
15
+ // - A leading `cd <path> && <cmd...>` in the literal is lifted into the
16
+ // subprocess cwd — no shell is spawned, so no quoting concerns.
17
+ // - Commands that chain with `&&` beyond the `cd` prefix aren't supported;
18
+ // split them into multiple `sh` awaits at the call site.
19
+
20
+ export interface ShResult {
21
+ exitCode: number
22
+ stdout: Buffer
23
+ stderr: Buffer
24
+ }
25
+
26
+ type Mode = 'default' | 'text' | 'quiet'
27
+
28
+ class Sh implements PromiseLike<ShResult> {
29
+ private _cwd: string | undefined
30
+ private _mode: Mode = 'default'
31
+ private _throw = true
32
+ private _promise: Promise<ShResult> | null = null
33
+
34
+ constructor(private readonly args: string[]) {}
35
+
36
+ cwd(dir: string): this {
37
+ this._cwd = dir
38
+ return this
39
+ }
40
+
41
+ quiet(): this {
42
+ this._mode = 'quiet'
43
+ return this
44
+ }
45
+
46
+ nothrow(): this {
47
+ this._throw = false
48
+ return this
49
+ }
50
+
51
+ async text(): Promise<string> {
52
+ // If no explicit quiet was requested, capture stdout/stderr without
53
+ // forwarding them to the parent's streams (matches Bun's `.text()`).
54
+ if (this._mode === 'default') this._mode = 'text'
55
+ const r = await this.run()
56
+ return r.stdout.toString('utf8')
57
+ }
58
+
59
+ then<TResult1 = ShResult, TResult2 = never>(
60
+ onfulfilled?: ((value: ShResult) => TResult1 | PromiseLike<TResult1>) | null,
61
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
62
+ ): Promise<TResult1 | TResult2> {
63
+ return this.run().then(onfulfilled, onrejected)
64
+ }
65
+
66
+ private run(): Promise<ShResult> {
67
+ if (!this._promise) this._promise = this.exec()
68
+ return this._promise
69
+ }
70
+
71
+ private async exec(): Promise<ShResult> {
72
+ const [cmd, ...rest] = this.args
73
+ if (!cmd) throw new Error('sh: empty command')
74
+
75
+ const stdio: StdioOptions =
76
+ this._mode === 'default'
77
+ ? ['inherit', 'pipe', 'pipe']
78
+ : this._mode === 'quiet'
79
+ ? ['ignore', 'pipe', 'pipe']
80
+ : ['inherit', 'pipe', 'pipe']
81
+
82
+ const proc = spawn(cmd, rest, { cwd: this._cwd, stdio })
83
+
84
+ const outChunks: Buffer[] = []
85
+ const errChunks: Buffer[] = []
86
+ proc.stdout?.on('data', (c: Buffer) => {
87
+ outChunks.push(c)
88
+ if (this._mode === 'default') process.stdout.write(c)
89
+ })
90
+ proc.stderr?.on('data', (c: Buffer) => {
91
+ errChunks.push(c)
92
+ if (this._mode === 'default') process.stderr.write(c)
93
+ })
94
+
95
+ const exitCode: number = await new Promise((resolve, reject) => {
96
+ proc.on('error', reject)
97
+ proc.on('close', (code) => resolve(code ?? 0))
98
+ })
99
+
100
+ const stdout = Buffer.concat(outChunks)
101
+ const stderr = Buffer.concat(errChunks)
102
+ const result: ShResult = { exitCode, stdout, stderr }
103
+
104
+ if (exitCode !== 0 && this._throw) {
105
+ const err: any = new Error(`sh: command failed with exit ${exitCode}: ${this.args.join(' ')}`)
106
+ err.exitCode = exitCode
107
+ err.stdout = stdout
108
+ err.stderr = stderr
109
+ throw err
110
+ }
111
+
112
+ return result
113
+ }
114
+ }
115
+
116
+ const WHITESPACE = /\s/
117
+
118
+ function tokenize(
119
+ strings: TemplateStringsArray,
120
+ values: unknown[],
121
+ ): { tokens: string[]; initialCwd?: string } {
122
+ const tokens: string[] = []
123
+ let current = ''
124
+ let inToken = false
125
+
126
+ const commit = () => {
127
+ if (inToken) {
128
+ tokens.push(current)
129
+ current = ''
130
+ inToken = false
131
+ }
132
+ }
133
+
134
+ const append = (s: string) => {
135
+ current += s
136
+ inToken = true
137
+ }
138
+
139
+ const appendValue = (val: unknown) => {
140
+ if (val == null) return
141
+ if (Array.isArray(val)) {
142
+ val.forEach((item, i) => {
143
+ if (i > 0) commit()
144
+ append(String(item))
145
+ })
146
+ return
147
+ }
148
+ append(String(val))
149
+ }
150
+
151
+ strings.forEach((literal, i) => {
152
+ for (let c = 0; c < literal.length; c++) {
153
+ const ch = literal[c]
154
+ if (WHITESPACE.test(ch)) commit()
155
+ else append(ch)
156
+ }
157
+ if (i < values.length) appendValue(values[i])
158
+ })
159
+ commit()
160
+
161
+ // Lift `cd <path> && <cmd...>` prefix into subprocess cwd
162
+ if (tokens.length >= 3 && tokens[0] === 'cd' && tokens[2] === '&&') {
163
+ return { tokens: tokens.slice(3), initialCwd: tokens[1] }
164
+ }
165
+ return { tokens }
166
+ }
167
+
168
+ export function sh(strings: TemplateStringsArray, ...values: unknown[]): Sh {
169
+ const { tokens, initialCwd } = tokenize(strings, values)
170
+ const s = new Sh(tokens)
171
+ if (initialCwd) s.cwd(initialCwd)
172
+ return s
173
+ }
package/tools/deploy.ts CHANGED
@@ -1,58 +1,126 @@
1
- import { $ } from 'bun'
1
+ import { access, readFile, writeFile } from 'node:fs/promises'
2
2
  import { parseArgs } from 'util'
3
+ import { sh } from './_shell'
4
+ import { buildCommitArgs } from './_git-author'
3
5
 
4
6
  const cwd = process.cwd()
5
7
 
8
+ const exists = async (p: string) => {
9
+ try {
10
+ await access(p)
11
+ return true
12
+ } catch {
13
+ return false
14
+ }
15
+ }
16
+
17
+ const readJson = async (p: string) => JSON.parse(await readFile(p, 'utf8'))
18
+
6
19
  const {
7
- values: { changelogs: changelogsArg, 'changelogs-file': changelogsFile, yes },
20
+ values: {
21
+ changelogs: changelogsArg,
22
+ 'changelogs-file': changelogsFile,
23
+ 'auto-commit': autoCommit,
24
+ 'auto-version': autoVersion,
25
+ version: versionArg,
26
+ yes,
27
+ help,
28
+ },
8
29
  } = parseArgs({
9
- args: Bun.argv.slice(2),
30
+ args: process.argv.slice(2),
10
31
  options: {
11
32
  changelogs: { type: 'string' },
12
33
  'changelogs-file': { type: 'string' },
34
+ 'auto-commit': { type: 'boolean' },
35
+ 'auto-version': { type: 'boolean' },
36
+ version: { type: 'string' },
13
37
  yes: { type: 'boolean', short: 'y' },
38
+ help: { type: 'boolean', short: 'h' },
14
39
  },
15
40
  allowPositionals: true,
16
41
  })
17
42
 
43
+ if (help) {
44
+ console.log(`Options:
45
+ --changelogs <text> Changelogs text for the release
46
+ --changelogs-file <path> Read changelogs from a file
47
+ --auto-commit Auto-commit unstaged changes before deploying
48
+ --auto-version Auto-bump patch version before deploying
49
+ --version <version> Set explicit version for the release
50
+ -y, --yes Skip all prompts
51
+ -h, --help Show this help message`)
52
+ process.exit(0)
53
+ }
54
+
18
55
  // Check git status
19
- const { exitCode } = await $`cd ${cwd} && git status`.nothrow()
56
+ const { exitCode } = await sh`cd ${cwd} && git status`.quiet().nothrow()
20
57
  const isGitRepo = exitCode === 0
21
58
 
22
- let commitId = ''
23
- if (isGitRepo) {
24
- const unstagedChanges = await $`cd ${cwd} && git diff --name-only --diff-filter=ACMR`.text()
25
- if (unstagedChanges)
26
- throw new Error('Unstaged changes found, please commit or stash your changes before deploying')
27
-
28
- commitId = (await $`cd ${cwd} && git rev-parse HEAD`.text()).trim()
29
- } else if (!yes) {
59
+ if (!isGitRepo && !yes) {
30
60
  const confirmContinue = prompt('No git repository found, continue? (y/n)')
31
61
  if (confirmContinue !== 'y') throw new Error('Deployment cancelled')
32
62
  }
33
63
 
34
64
  // Read application.json
35
- const app = await Bun.file(`${cwd}/application.json`).json()
36
- const config = await Bun.file(`${cwd}/.bricks/build/application-config.json`).json()
37
-
38
- // Get version from project's package.json
39
- const pkgFile = Bun.file(`${cwd}/package.json`)
40
- const version = (await pkgFile.exists()) ? (await pkgFile.json()).version : undefined
65
+ const app = await readJson(`${cwd}/application.json`)
66
+ const config = await readJson(`${cwd}/.bricks/build/application-config.json`)
67
+
68
+ // Resolve version: explicit flag > auto-bump > package.json
69
+ const pkgPath = `${cwd}/package.json`
70
+ const pkgExists = await exists(pkgPath)
71
+ let version: string | undefined
72
+
73
+ if (versionArg) {
74
+ version = versionArg
75
+ if (pkgExists) {
76
+ const pkg = await readJson(pkgPath)
77
+ pkg.version = version
78
+ await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
79
+ }
80
+ } else if (autoVersion && pkgExists) {
81
+ const pkg = await readJson(pkgPath)
82
+ const parts = (pkg.version || '0.0.0').split('.')
83
+ parts[2] = String(Number(parts[2] || 0) + 1)
84
+ version = parts.join('.')
85
+ pkg.version = version
86
+ await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
87
+ } else {
88
+ version = pkgExists ? (await readJson(pkgPath)).version : undefined
89
+ }
41
90
 
42
91
  // Get changelog from flag or file
43
92
  let changelogs = ''
44
93
  if (changelogsArg) {
45
94
  changelogs = changelogsArg
46
95
  } else if (changelogsFile) {
47
- const file = Bun.file(changelogsFile)
48
- if (!(await file.exists())) {
96
+ if (!(await exists(changelogsFile))) {
49
97
  throw new Error(`Changelogs file not found: ${changelogsFile}`)
50
98
  }
51
- changelogs = await file.text()
99
+ changelogs = await readFile(changelogsFile, 'utf8')
52
100
  } else if (!yes) {
53
101
  changelogs = prompt('Enter changelogs (optional, press Enter to skip):') || ''
54
102
  }
55
103
 
104
+ // Handle unstaged changes
105
+ let commitId = ''
106
+ if (isGitRepo) {
107
+ const unstagedChanges = await sh`cd ${cwd} && git diff --name-only --diff-filter=ACMR`.text()
108
+ if (unstagedChanges) {
109
+ if (autoCommit) {
110
+ const commitMsg = `chore: release ${version || 'new version'}`
111
+ const commitBody = changelogs || '[no changelogs]'
112
+ await sh`cd ${cwd} && git add -A`
113
+ const commitArgs = await buildCommitArgs(cwd, [commitMsg, commitBody])
114
+ await sh`cd ${cwd} && git ${commitArgs}`
115
+ } else {
116
+ throw new Error(
117
+ 'Unstaged changes found, please commit or stash your changes before deploying',
118
+ )
119
+ }
120
+ }
121
+ commitId = (await sh`cd ${cwd} && git rev-parse HEAD`.text()).trim()
122
+ }
123
+
56
124
  // Ask for confirmation
57
125
  if (!yes) {
58
126
  const confirm = prompt('Are you sure you want to deploy? (y/n)')
@@ -69,7 +137,7 @@ const releaseConfig = {
69
137
  bricks_project_last_commit_id: commitId || undefined,
70
138
  }
71
139
  const configPath = `${cwd}/.bricks/build/release-config.json`
72
- await Bun.write(configPath, JSON.stringify(releaseConfig))
140
+ await writeFile(configPath, JSON.stringify(releaseConfig))
73
141
 
74
142
  const args = ['bricks', command, 'release', app.id, '-c', configPath, '--json']
75
143
 
@@ -81,7 +149,7 @@ if (changelogs) {
81
149
  args.push('--changelogs', changelogs)
82
150
  }
83
151
 
84
- const result = await $`${args}`.quiet().nothrow()
152
+ const result = await sh`${args}`.quiet().nothrow()
85
153
 
86
154
  if (result.exitCode !== 0) {
87
155
  const output = result.stderr.toString() || result.stdout.toString()