@fugood/bricks-project 2.23.0-beta.3 → 2.23.0-beta.31

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 (91) hide show
  1. package/compile/action-name-map.ts +59 -0
  2. package/compile/index.ts +52 -60
  3. package/package.json +4 -4
  4. package/tools/mcp-server.ts +3 -3
  5. package/tools/postinstall.ts +2 -5
  6. package/tools/preview.ts +1 -1
  7. package/tools/pull.ts +1 -1
  8. package/types/brick-base.ts +1 -0
  9. package/types/bricks/Camera.ts +1 -0
  10. package/types/bricks/Chart.ts +1 -0
  11. package/types/bricks/GenerativeMedia.ts +21 -3
  12. package/types/bricks/Icon.ts +1 -0
  13. package/types/bricks/Image.ts +1 -0
  14. package/types/bricks/Items.ts +1 -0
  15. package/types/bricks/Lottie.ts +1 -0
  16. package/types/bricks/QrCode.ts +1 -0
  17. package/types/bricks/Rect.ts +1 -0
  18. package/types/bricks/RichText.ts +1 -0
  19. package/types/bricks/Rive.ts +1 -0
  20. package/types/bricks/Slideshow.ts +38 -2
  21. package/types/bricks/Svg.ts +1 -0
  22. package/types/bricks/Text.ts +1 -0
  23. package/types/bricks/TextInput.ts +1 -0
  24. package/types/bricks/Video.ts +1 -0
  25. package/types/bricks/VideoStreaming.ts +1 -0
  26. package/types/bricks/WebRtcStream.ts +1 -0
  27. package/types/bricks/WebView.ts +1 -0
  28. package/types/bricks/index.ts +1 -0
  29. package/types/canvas.ts +1 -0
  30. package/types/data-calc.ts +44 -0
  31. package/types/data.ts +1 -0
  32. package/types/generators/AlarmClock.ts +1 -0
  33. package/types/generators/Assistant.ts +11 -1
  34. package/types/generators/BleCentral.ts +1 -0
  35. package/types/generators/BlePeripheral.ts +1 -0
  36. package/types/generators/CanvasMap.ts +15 -3
  37. package/types/generators/CastlesPay.ts +1 -0
  38. package/types/generators/DataBank.ts +1 -0
  39. package/types/generators/File.ts +1 -0
  40. package/types/generators/GraphQl.ts +1 -0
  41. package/types/generators/Http.ts +75 -1
  42. package/types/generators/HttpServer.ts +1 -0
  43. package/types/generators/Information.ts +1 -0
  44. package/types/generators/Intent.ts +50 -0
  45. package/types/generators/Iterator.ts +10 -2
  46. package/types/generators/Keyboard.ts +1 -0
  47. package/types/generators/LlmAnthropicCompat.ts +1 -0
  48. package/types/generators/LlmAppleBuiltin.ts +143 -0
  49. package/types/generators/LlmGgml.ts +23 -5
  50. package/types/generators/LlmOnnx.ts +8 -0
  51. package/types/generators/LlmOpenAiCompat.ts +1 -0
  52. package/types/generators/LlmQualcommAiEngine.ts +1 -0
  53. package/types/generators/Mcp.ts +1 -0
  54. package/types/generators/McpServer.ts +1 -0
  55. package/types/generators/MediaFlow.ts +1 -0
  56. package/types/generators/MqttBroker.ts +1 -0
  57. package/types/generators/MqttClient.ts +1 -0
  58. package/types/generators/Question.ts +8 -0
  59. package/types/generators/RealtimeTranscription.ts +1 -0
  60. package/types/generators/RerankerGgml.ts +22 -16
  61. package/types/generators/SerialPort.ts +1 -0
  62. package/types/generators/SoundPlayer.ts +1 -0
  63. package/types/generators/SoundRecorder.ts +1 -0
  64. package/types/generators/SpeechToTextGgml.ts +13 -4
  65. package/types/generators/SpeechToTextOnnx.ts +1 -0
  66. package/types/generators/SpeechToTextPlatform.ts +1 -0
  67. package/types/generators/SqLite.ts +31 -1
  68. package/types/generators/Step.ts +1 -0
  69. package/types/generators/SttAppleBuiltin.ts +116 -0
  70. package/types/generators/Tcp.ts +1 -0
  71. package/types/generators/TcpServer.ts +1 -0
  72. package/types/generators/TextToSpeechApple.ts +113 -0
  73. package/types/generators/TextToSpeechAppleBuiltin.ts +113 -0
  74. package/types/generators/TextToSpeechGgml.ts +23 -3
  75. package/types/generators/TextToSpeechOnnx.ts +1 -0
  76. package/types/generators/TextToSpeechOpenAiLike.ts +1 -0
  77. package/types/generators/ThermalPrinter.ts +1 -0
  78. package/types/generators/Tick.ts +4 -1
  79. package/types/generators/TtsAppleBuiltin.ts +105 -0
  80. package/types/generators/Udp.ts +1 -0
  81. package/types/generators/VadGgml.ts +3 -2
  82. package/types/generators/VectorStore.ts +14 -2
  83. package/types/generators/Watchdog.ts +1 -0
  84. package/types/generators/WebCrawler.ts +1 -0
  85. package/types/generators/WebRtc.ts +1 -0
  86. package/types/generators/WebSocket.ts +1 -0
  87. package/types/generators/index.ts +3 -0
  88. package/types/system.ts +1 -0
  89. package/utils/data.ts +1 -0
  90. package/utils/event-props.ts +72 -3
  91. package/utils/id.ts +3 -1
@@ -1,3 +1,5 @@
1
+ /* Auto generated by build script */
2
+
1
3
  // NOTE: The action parameter name convertion is not 1:1 mapping case conversion, so we need to define the mapping here
2
4
  // This may be improved in the future
3
5
  export const templateActionNameMap = {
@@ -357,6 +359,22 @@ export const templateActionNameMap = {
357
359
  variables: 'GENERATOR_GRAPHQL_VARIABLES',
358
360
  },
359
361
  },
362
+ GENERATOR_HTTP: {
363
+ GENERATOR_HTTP_RUN_REQUEST: {
364
+ url: 'GENERATOR_HTTP_URL',
365
+ method: 'GENERATOR_HTTP_METHOD',
366
+ headers: 'GENERATOR_HTTP_HEADERS',
367
+ body: 'GENERATOR_HTTP_BODY',
368
+ timeout: 'GENERATOR_HTTP_TIMEOUT',
369
+ mode: 'GENERATOR_HTTP_MODE',
370
+ credentials: 'GENERATOR_HTTP_CREDENTIALS',
371
+ redirect: 'GENERATOR_HTTP_REDIRECT',
372
+ referrer: 'GENERATOR_HTTP_REFERRER',
373
+ resType: 'GENERATOR_HTTP_RES_TYPE',
374
+ eventStream: 'GENERATOR_HTTP_EVENT_STREAM',
375
+ eventName: 'GENERATOR_HTTP_EVENT_NAME',
376
+ },
377
+ },
360
378
 
361
379
  GENERATOR_WEB_SOCKET: {
362
380
  GENERATOR_WEB_SOCKET_EMIT: {
@@ -484,6 +502,16 @@ export const templateActionNameMap = {
484
502
  packageName: 'GENERATOR_INTENT_PACKAGE_NAME',
485
503
  category: 'GENERATOR_INTENT_CATEGORY',
486
504
  },
505
+ GENERATOR_INTENT_START_SERVICE: {
506
+ action: 'GENERATOR_INTENT_ACTION',
507
+ data: 'GENERATOR_INTENT_DATA',
508
+ type: 'GENERATOR_INTENT_TYPE',
509
+ extra: 'GENERATOR_INTENT_EXTRA',
510
+ className: 'GENERATOR_INTENT_CLASS_NAME',
511
+ packageName: 'GENERATOR_INTENT_PACKAGE_NAME',
512
+ category: 'GENERATOR_INTENT_CATEGORY',
513
+ foreground: 'GENERATOR_INTENT_FOREGROUND',
514
+ },
487
515
  },
488
516
  GENERATOR_CASTLES_PAY: {
489
517
  GENERATOR_CASTLES_PAY_SALE: {
@@ -512,6 +540,13 @@ export const templateActionNameMap = {
512
540
  params: 'GENERATOR_SQLITE_PARAMS',
513
541
  paramsString: 'GENERATOR_SQLITE_PARAMS_STRING',
514
542
  },
543
+ GENERATOR_SQLITE_TRANSACTION: {
544
+ statements: 'GENERATOR_SQLITE_STATEMENTS',
545
+ },
546
+ GENERATOR_SQLITE_BATCH_EXECUTE: {
547
+ sql: 'GENERATOR_SQLITE_SQL',
548
+ batchParams: 'GENERATOR_SQLITE_BATCH_PARAMS',
549
+ },
515
550
  },
516
551
 
517
552
  GENERATOR_MCP: {
@@ -553,6 +588,7 @@ export const templateActionNameMap = {
553
588
  prompt: 'GENERATOR_ONNX_LLM_PROMPT',
554
589
  chat: 'GENERATOR_ONNX_LLM_CHAT',
555
590
  images: 'GENERATOR_ONNX_LLM_IMAGES',
591
+ audios: 'GENERATOR_ONNX_LLM_AUDIOS',
556
592
  tools: 'GENERATOR_ONNX_LLM_TOOLS',
557
593
  toolChoice: 'GENERATOR_ONNX_LLM_TOOL_CHOICE',
558
594
  },
@@ -746,6 +782,29 @@ export const templateActionNameMap = {
746
782
  toolChoice: 'GENERATOR_ANTHROPIC_LLM_TOOL_CHOICE',
747
783
  },
748
784
  },
785
+ GENERATOR_APPLE_LLM: {
786
+ GENERATOR_APPLE_LLM_COMPLETION: {
787
+ messages: 'GENERATOR_APPLE_LLM_MESSAGES',
788
+ maxTokens: 'GENERATOR_APPLE_LLM_MAX_TOKENS',
789
+ temperature: 'GENERATOR_APPLE_LLM_TEMPERATURE',
790
+ topP: 'GENERATOR_APPLE_LLM_TOP_P',
791
+ },
792
+ },
793
+ GENERATOR_APPLE_STT: {
794
+ GENERATOR_APPLE_STT_TRANSCRIBE_FILE: {
795
+ fileUrl: 'GENERATOR_APPLE_STT_FILE_URL',
796
+ language: 'GENERATOR_APPLE_STT_LANGUAGE',
797
+ },
798
+ GENERATOR_APPLE_STT_TRANSCRIBE_DATA: {
799
+ data: 'GENERATOR_APPLE_STT_DATA',
800
+ language: 'GENERATOR_APPLE_STT_LANGUAGE',
801
+ },
802
+ },
803
+ GENERATOR_APPLE_TTS: {
804
+ GENERATOR_APPLE_TTS_GENERATE: {
805
+ text: 'GENERATOR_APPLE_TTS_TEXT',
806
+ },
807
+ },
749
808
  GENERATOR_ASSISTANT: {
750
809
  GENERATOR_ASSISTANT_ADD_MESSAGE: {
751
810
  role: 'GENERATOR_ASSISTANT_ROLE',
package/compile/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-underscore-dangle -- Uses __typename, __actionName, etc. for type system */
1
2
  import _ from 'lodash'
2
3
  import { parse as parseAST } from 'acorn'
3
4
  import type { ExportNamedDeclaration, FunctionDeclaration } from 'acorn'
@@ -12,7 +13,6 @@ import type {
12
13
  Animation,
13
14
  AnimationDef,
14
15
  AnimationComposeDef,
15
- EventAction,
16
16
  ActionWithDataParams,
17
17
  ActionWithParams,
18
18
  BrickItems,
@@ -24,10 +24,8 @@ import type {
24
24
  DataCalculationData,
25
25
  DataCommand,
26
26
  Brick,
27
- Generator,
28
27
  Canvas,
29
28
  Subspace,
30
- EventActionForItem,
31
29
  } from '../types'
32
30
 
33
31
  const compileProperty = (property, errorReference: string, result = {}) => {
@@ -66,25 +64,22 @@ const compileEventActionValue = (templateKey, eventKey, value, errorReference) =
66
64
  return compileProperty(value, errorReference)
67
65
  }
68
66
 
69
- const convertOutletKey = (templateKey: string, key: string) => {
70
- return `${templateKey}_${_.snakeCase(key).toUpperCase()}`
71
- }
67
+ const convertOutletKey = (templateKey: string, key: string) =>
68
+ `${templateKey}_${_.snakeCase(key).toUpperCase()}`
72
69
 
73
70
  const compileOutlets = (
74
71
  templateKey: string,
75
72
  outlets: { [key: string]: () => Data },
76
73
  errorReference: string,
77
- ) => {
78
- return Object.entries(outlets).reduce((acc, [key, data]) => {
74
+ ) =>
75
+ Object.entries(outlets).reduce((acc, [key, data]) => {
79
76
  if (!data()?.id) throw new Error(`Invalid data reference ${errorReference}`)
80
77
  acc[convertOutletKey(templateKey, key)] = data().id
81
78
  return acc
82
79
  }, {})
83
- }
84
80
 
85
- const convertEventKey = (templateKey: string, key: string) => {
86
- return `${templateKey ? `${templateKey}_` : ''}${_.snakeCase(key).toUpperCase()}`
87
- }
81
+ const convertEventKey = (templateKey: string, key: string) =>
82
+ `${templateKey ? `${templateKey}_` : ''}${_.snakeCase(key).toUpperCase()}`
88
83
 
89
84
  const basicAnimationEvents = ['show', 'standby', 'breatheStart']
90
85
 
@@ -92,14 +87,13 @@ const compileAnimations = (
92
87
  templateKey: string,
93
88
  animations: { [key: string]: Animation },
94
89
  errorReference: string,
95
- ) => {
96
- return Object.entries(animations).reduce((acc, [key, animation]) => {
90
+ ) =>
91
+ Object.entries(animations).reduce((acc, [key, animation]) => {
97
92
  if (!animation?.id) throw new Error(`Invalid animation reference ${errorReference}`)
98
93
  acc[convertEventKey(basicAnimationEvents.includes(key) ? 'BRICK' : templateKey, key)] =
99
94
  `ANIMATION#${animation.id}`
100
95
  return acc
101
96
  }, {})
102
- }
103
97
 
104
98
  const compileActionParam = (templateKey: string, actionName: string, paramName: string) =>
105
99
  templateActionNameMap[templateKey]?.[actionName]?.[paramName] || paramName
@@ -190,7 +184,7 @@ const compileSwitchConds = (templateKey, conds, errorReference) =>
190
184
  result.key = cond.data().id
191
185
  result.value = cond.value
192
186
  } else if (item.cond.__typename === 'SwitchCondInnerStateOutlet') {
193
- const cond = item.cond
187
+ const { cond } = item
194
188
  result.type = 'inner_state'
195
189
  result.key = convertOutletKey(templateKey, cond.outlet)
196
190
  result.value = cond.value
@@ -205,35 +199,33 @@ const compileSwitchConds = (templateKey, conds, errorReference) =>
205
199
  return result
206
200
  })
207
201
 
208
- const compileApplicationSettings = (settings: Application['settings']) => {
209
- return {
210
- internet_reachability_url: settings?.internetReachabilityUrl,
211
- enable_data_lock: settings?.enableDataLock,
212
- show_deprecated_features: settings?.showDeprecatedFeatures,
213
- enable_unstable_bricks: settings?.enableUnstableFeatures,
214
- runtime_cache_options: settings?.runtimeCacheOptions
215
- ? {
216
- disabled: settings.runtimeCacheOptions.disabled,
217
- behavior: settings.runtimeCacheOptions.behavior,
218
- retry_attempt_for_failure: settings.runtimeCacheOptions.retryAttemptForFailure,
219
- }
220
- : undefined,
221
- tv_options: settings?.tvOptions
222
- ? {
223
- disabled_selectable: settings.tvOptions.disabledSelectable,
224
- selectable_color: settings.tvOptions.selectableColor,
225
- selectable_border: settings.tvOptions.selectableBorder,
226
- }
227
- : undefined,
228
- ai: settings?.ai
229
- ? {
230
- use_anthropic_api_key_system_data: settings.ai.useAnthropicApiKeySystemData,
231
- use_openai_api_key_system_data: settings.ai.useOpenAiApiKeySystemData,
232
- use_gemini_api_key_system_data: settings.ai.useGeminiApiKeySystemData,
233
- }
234
- : undefined,
235
- }
236
- }
202
+ const compileApplicationSettings = (settings: Application['settings']) => ({
203
+ internet_reachability_url: settings?.internetReachabilityUrl,
204
+ enable_data_lock: settings?.enableDataLock,
205
+ show_deprecated_features: settings?.showDeprecatedFeatures,
206
+ enable_unstable_bricks: settings?.enableUnstableFeatures,
207
+ runtime_cache_options: settings?.runtimeCacheOptions
208
+ ? {
209
+ disabled: settings.runtimeCacheOptions.disabled,
210
+ behavior: settings.runtimeCacheOptions.behavior,
211
+ retry_attempt_for_failure: settings.runtimeCacheOptions.retryAttemptForFailure,
212
+ }
213
+ : undefined,
214
+ tv_options: settings?.tvOptions
215
+ ? {
216
+ disabled_selectable: settings.tvOptions.disabledSelectable,
217
+ selectable_color: settings.tvOptions.selectableColor,
218
+ selectable_border: settings.tvOptions.selectableBorder,
219
+ }
220
+ : undefined,
221
+ ai: settings?.ai
222
+ ? {
223
+ use_anthropic_api_key_system_data: settings.ai.useAnthropicApiKeySystemData,
224
+ use_openai_api_key_system_data: settings.ai.useOpenAiApiKeySystemData,
225
+ use_gemini_api_key_system_data: settings.ai.useGeminiApiKeySystemData,
226
+ }
227
+ : undefined,
228
+ })
237
229
 
238
230
  const animationTypeMap = {
239
231
  AnimationTimingConfig: 'timing',
@@ -338,7 +330,7 @@ export const compile = async (app: Application) => {
338
330
  brick: !subspace.unexpanded.brick,
339
331
  generator: !subspace.unexpanded.generator,
340
332
  canvas: subspace.unexpanded.canvas?.reduce((acc, canvas) => {
341
- acc[canvas.id] = canvas?.id ? false : true
333
+ acc[canvas.id] = !canvas?.id
342
334
  return acc
343
335
  }, {}),
344
336
  property_bank: !subspace.unexpanded.data,
@@ -377,12 +369,12 @@ export const compile = async (app: Application) => {
377
369
  animationRunType: animationDef.runType,
378
370
  compose_type: animationDef.composeType,
379
371
  item_list: animationDef.items.map((item, index) => {
380
- const animation = item()
381
- if (!animation?.id)
372
+ const innerAnimation = item()
373
+ if (!innerAnimation?.id)
382
374
  throw new Error(
383
- `Invalid animation index: ${index} (animation: ${animation.id}, subspace ${subspace.id})`,
375
+ `Invalid animation index: ${index} (animation: ${innerAnimation.id}, subspace ${subspace.id})`,
384
376
  )
385
- return { animation_id: animation.id }
377
+ return { animation_id: innerAnimation.id }
386
378
  }),
387
379
  }
388
380
  }
@@ -461,7 +453,7 @@ export const compile = async (app: Application) => {
461
453
  property.brickList = brickList
462
454
  } else {
463
455
  // Not supported Data for brickList
464
- throw new Error('Not supported Data for brickList directly')
456
+ throw new TypeError('Not supported Data for brickList directly')
465
457
  }
466
458
  if (Array.isArray(brickItems.brickDetails)) {
467
459
  const brickDetails = (brickItems.brickDetails || []).map((item, index) =>
@@ -470,7 +462,7 @@ export const compile = async (app: Application) => {
470
462
  property.brickDetails = brickDetails
471
463
  } else {
472
464
  // Not supported Data for brickList
473
- throw new Error('Not supported Data for brickList directly')
465
+ throw new TypeError('Not supported Data for brickList directly')
474
466
  }
475
467
  }
476
468
  map[brick.id] = {
@@ -694,7 +686,7 @@ export const compile = async (app: Application) => {
694
686
  if (!acc[port.key]) acc[port.key] = null
695
687
 
696
688
  let sourceId
697
- let sourceNode = port.source()
689
+ const sourceNode = port.source()
698
690
  if (sourceNode?.__typename === 'DataCalculationData')
699
691
  sourceId = (sourceNode as DataCalculationData).data().id
700
692
  if (sourceNode?.__typename === 'DataCommand') sourceId = sourceNode.id
@@ -715,7 +707,7 @@ export const compile = async (app: Application) => {
715
707
  if (!acc[port.key]) acc[port.key] = null
716
708
 
717
709
  let targetId
718
- let targetNode = port.target()
710
+ const targetNode = port.target()
719
711
  if (targetNode?.__typename === 'DataCalculationData')
720
712
  targetId = (targetNode as DataCalculationData).data().id
721
713
  if (targetNode?.__typename === 'DataCommand') targetId = targetNode.id
@@ -770,9 +762,9 @@ export const compile = async (app: Application) => {
770
762
  type: `command-node-${type}`,
771
763
  properties: {
772
764
  command: commandNode.__commandName,
773
- args: args.reduce((acc, input) => {
774
- acc[input.key] = input.source
775
- return acc
765
+ args: args.reduce((argsAcc, input) => {
766
+ argsAcc[input.key] = input.source
767
+ return argsAcc
776
768
  }, {}),
777
769
  },
778
770
  in: generateInputPorts(inputs),
@@ -784,12 +776,12 @@ export const compile = async (app: Application) => {
784
776
  calc.editor_info = mapCalc.editorInfo.reduce((acc, editorInfo) => {
785
777
  acc[getNodeId(editorInfo.node)] = {
786
778
  position: editorInfo.position,
787
- points: editorInfo.points.reduce((acc, point) => {
779
+ points: editorInfo.points.reduce((pointsAcc, point) => {
788
780
  const sourceId = getNodeId(point.source)
789
781
  const targetId = getNodeId(point.target)
790
782
  const key = `${sourceId}-${point.sourceOutputKey}-${targetId}-${point.targetInputKey}`
791
- acc[key] = point.positions
792
- return acc
783
+ pointsAcc[key] = point.positions
784
+ return pointsAcc
793
785
  }, {}),
794
786
  }
795
787
  return acc
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@fugood/bricks-project",
3
- "version": "2.23.0-beta.3",
3
+ "version": "2.23.0-beta.31",
4
4
  "main": "index.ts",
5
5
  "scripts": {
6
- "build": "node scripts/build.js"
6
+ "build": "bun scripts/build.js"
7
7
  },
8
8
  "dependencies": {
9
9
  "@modelcontextprotocol/sdk": "^1.15.0",
10
10
  "@types/escodegen": "^0.0.10",
11
11
  "@types/lodash": "^4.17.12",
12
12
  "acorn": "^8.13.0",
13
- "escodegen": "^2.1.0",
13
+ "escodegen": "2.1.0",
14
14
  "lodash": "^4.17.4",
15
15
  "uuid": "^8.3.1"
16
16
  },
17
- "gitHead": "dc9fcb1792c91cb150ffc976017fd8fcaf8c32a7"
17
+ "gitHead": "c0cfcde7d913f7393bf60db376925d3eaa4c1d61"
18
18
  }
@@ -8,7 +8,7 @@ const server = new McpServer({
8
8
  version: '1.0.0',
9
9
  })
10
10
 
11
- const dirname = import.meta.dirname
11
+ const { dirname } = import.meta
12
12
  const projectDir = String(dirname).split('/node_modules/')[0]
13
13
 
14
14
  server.tool('compile', {}, async () => {
@@ -16,7 +16,7 @@ server.tool('compile', {}, async () => {
16
16
  try {
17
17
  log = await $`bun compile`.cwd(projectDir).text()
18
18
  } catch (err) {
19
- log = err.stdout.toString() + '\n' + err.stderr.toString()
19
+ log = `${err.stdout.toString()}\n${err.stderr.toString()}`
20
20
  }
21
21
  return {
22
22
  content: [{ type: 'text', text: log || 'Compiled successfully' }],
@@ -61,7 +61,7 @@ server.tool(
61
61
  ]
62
62
  log = await $`bunx --bun electron ${dirname}/preview-main.mjs ${args}`.cwd(projectDir).text()
63
63
  } catch (err) {
64
- log = err.stdout.toString() + '\n' + err.stderr.toString()
64
+ log = `${err.stdout.toString()}\n${err.stderr.toString()}`
65
65
  error = true
66
66
  }
67
67
  let screenshotBase64: any = null
@@ -17,13 +17,10 @@ const skipCopyProject = process.argv.includes('--skip-copy-project')
17
17
  if (skipCopyProject) {
18
18
  console.log('Skipping copy of files to project/')
19
19
  } else {
20
-
21
20
  const libFiles = ['types', 'utils', 'index.ts']
22
-
21
+
23
22
  await $`mkdir -p ${cwd}/project`
24
- for (const file of libFiles) {
25
- await $`cp -r ${__dirname}/../${file} ${cwd}/project`
26
- }
23
+ await Promise.all(libFiles.map((file) => $`cp -r ${__dirname}/../${file} ${cwd}/project`))
27
24
  console.log('Copied files to project/')
28
25
  }
29
26
 
package/tools/preview.ts CHANGED
@@ -25,7 +25,7 @@ const cwd = process.cwd()
25
25
 
26
26
  const app = await Bun.file(`${cwd}/application.json`).json()
27
27
 
28
- let args: string[] = []
28
+ const args: string[] = []
29
29
  if (values['clear-cache']) args.push('--clear-cache')
30
30
 
31
31
  let needWatcher = true
package/tools/pull.ts CHANGED
@@ -24,7 +24,7 @@ let useMain = false
24
24
  if (isGitRepo) {
25
25
  const found = (await $`cd ${cwd} && git rev-list -1 ${lastCommitId}`.nothrow().text())
26
26
  .trim()
27
- .match(/^[a-f0-9]{40}$/)
27
+ .match(/^[\da-f]{40}$/)
28
28
 
29
29
  const commitId = (await $`cd ${cwd} && git rev-parse HEAD`.text()).trim()
30
30
 
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from './switch'
2
3
  import type { Data, DataLink } from './data'
3
4
  import type { Animation, AnimationBasicEvents } from './animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -20,7 +21,10 @@ Default property:
20
21
  "type": "image",
21
22
  "resizeMode": "cover",
22
23
  "provider": "openai",
23
- "freepikClassicImageSize": "square_1_1"
24
+ "freepikClassicImageSize": "square_1_1",
25
+ "geminiVeoModel": "veo-3.1-generate-preview",
26
+ "geminiVeoResolution": "720p",
27
+ "geminiVeoDuration": 8
24
28
  }
25
29
  */
26
30
  property?: BrickBasicProperty & {
@@ -44,8 +48,8 @@ Default property:
44
48
  resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat' | DataLink
45
49
  /* The API key for the generative media service */
46
50
  apiKey?: string | DataLink
47
- /* The AI provider to use for generation (openai, freepik, or deepai) */
48
- provider?: 'openai' | 'freepik-classic' | 'deepai' | DataLink
51
+ /* The AI provider to use for generation (openai, freepik-classic, deepai, or gemini) */
52
+ provider?: 'openai' | 'freepik-classic' | 'deepai' | 'gemini' | DataLink
49
53
  /* OpenAI image size (256x256, 512x512, 1024x1024, etc) */
50
54
  openaiSize?: '1024x1024' | '1024x1792' | '1792x1024' | DataLink
51
55
  /* OpenAI image style (vivid or natural) */
@@ -158,6 +162,20 @@ Default property:
158
162
  deepaiWidth?: number | DataLink
159
163
  /* DeepAI output image height */
160
164
  deepaiHeight?: number | DataLink
165
+ /* Gemini aspect ratio (1:1, 16:9, 9:16, 3:2, 2:3) */
166
+ geminiAspectRatio?: '1:1' | '16:9' | '9:16' | '3:2' | '2:3' | DataLink
167
+ /* Gemini model to use for image generation */
168
+ geminiModel?: 'gemini-2.5-flash-image' | 'gemini-3-pro-image-preview' | DataLink
169
+ /* Gemini Veo model to use for video generation */
170
+ geminiVeoModel?: 'veo-3.1-generate-preview' | 'veo-3.1-fast-generate-preview' | DataLink
171
+ /* Gemini Veo video resolution (720p or 1080p) */
172
+ geminiVeoResolution?: '720p' | '1080p' | DataLink
173
+ /* Gemini Veo video duration in seconds (4, 6, 8) */
174
+ geminiVeoDuration?: 4 | 6 | 8 | DataLink
175
+ /* Gemini Veo negative prompt (attributes to avoid) */
176
+ geminiVeoNegativePrompt?: string | DataLink
177
+ /* Gemini Veo person generation control */
178
+ geminiVeoPersonGeneration?: 'allow_all' | 'allow_adult' | DataLink
161
179
  }
162
180
  events?: BrickBasicEvents & {
163
181
  /* Event of the brick press */
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -34,6 +35,26 @@ export type BrickSlideshowActionJumpToIndex = ActionWithParams & {
34
35
  >
35
36
  }
36
37
 
38
+ /* Play the slideshow (resume if paused) */
39
+ export type BrickSlideshowActionPlay = Action & {
40
+ __actionName: 'BRICK_SLIDESHOW_PLAY'
41
+ }
42
+
43
+ /* Pause the slideshow */
44
+ export type BrickSlideshowActionPause = Action & {
45
+ __actionName: 'BRICK_SLIDESHOW_PAUSE'
46
+ }
47
+
48
+ /* Go to next slide */
49
+ export type BrickSlideshowActionNext = Action & {
50
+ __actionName: 'BRICK_SLIDESHOW_NEXT'
51
+ }
52
+
53
+ /* Go to previous slide */
54
+ export type BrickSlideshowActionPrev = Action & {
55
+ __actionName: 'BRICK_SLIDESHOW_PREV'
56
+ }
57
+
37
58
  interface BrickSlideshowDef {
38
59
  /*
39
60
  Default property:
@@ -41,17 +62,28 @@ Default property:
41
62
  "countdown": 2000,
42
63
  "loop": true,
43
64
  "shuffle": false,
65
+ "photoResizeMode": "contain",
66
+ "photoLoadSystemIos": "auto",
67
+ "photoLoadSystemAndroid": "auto",
68
+ "videoResizeMode": "contain",
69
+ "videoAutoAspectRatio": false,
44
70
  "videoVolume": 100,
71
+ "videoMuted": false,
72
+ "videoRenderMode": "auto",
73
+ "fadeDuration": 0,
45
74
  "emptyViewText": "no available image item to show",
46
75
  "emptyViewTextSize": 44,
47
76
  "emptyViewTextColor": "#fff",
77
+ "enableBlurBackground": false,
48
78
  "blurBackgroundRadius": 8
49
79
  }
50
80
  */
51
81
  property?: BrickBasicProperty & {
52
82
  /* The time interval of show for each photo */
53
83
  countdown?: number | DataLink
54
- /* The slideshow media path list (File, URL) */
84
+ /* The slideshow media path list (File, URL)
85
+ Each path object can override global photo/video settings.
86
+ Item-level properties take precedence over brick-level properties. */
55
87
  paths?:
56
88
  | Array<
57
89
  | DataLink
@@ -70,7 +102,8 @@ Default property:
70
102
  }
71
103
  >
72
104
  | DataLink
73
- /* Multiple slideshow media path lists to combine (Array of path arrays) */
105
+ /* Multiple slideshow media path lists to combine (Array of path arrays).
106
+ All arrays are flattened and combined: [...paths, ...pathsList[0], ...pathsList[1], ...] */
74
107
  pathsList?: Array<Array<any> | DataLink | DataLink> | DataLink
75
108
  /* Loop the slideshow */
76
109
  loop?: boolean | DataLink
@@ -122,6 +155,8 @@ Default property:
122
155
  roundEnd?: Array<EventAction>
123
156
  /* Event of the slideshow on load */
124
157
  mediaOnLoad?: Array<EventAction>
158
+ /* Event of the slideshow media loading error */
159
+ mediaOnError?: Array<EventAction>
125
160
  }
126
161
  animation?: AnimationBasicEvents & {
127
162
  changeStart?: Animation
@@ -129,6 +164,7 @@ Default property:
129
164
  contentChange?: Animation
130
165
  roundEnd?: Animation
131
166
  mediaOnLoad?: Animation
167
+ mediaOnError?: Animation
132
168
  }
133
169
  }
134
170
 
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'
@@ -1,3 +1,4 @@
1
+ /* Auto generated by build script */
1
2
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
2
3
  import type { Data, DataLink } from '../data'
3
4
  import type { Animation, AnimationBasicEvents } from '../animation'