@fugood/bricks-project 2.22.0-beta.2 → 2.22.0-beta.22

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.
@@ -100,6 +100,9 @@ export const templateActionNameMap = {
100
100
  payloadType: 'CHANNEL_PUBLISH_PAYLOAD_TYPE',
101
101
  payload: 'CHANNEL_PUBLISH_PAYLOAD',
102
102
  },
103
+ DELAY: {
104
+ time: 'DELAY_TIME',
105
+ },
103
106
  USE_SHARE_APPLICATION: {
104
107
  applicationId: 'APPLICATION_ID',
105
108
  releaseVersion: 'RELEASE_VERSION',
@@ -126,6 +129,12 @@ export const templateActionNameMap = {
126
129
  behavior: 'BEHAVIOR',
127
130
  exceptionMessage: 'EXCEPTION_MESSAGE',
128
131
  },
132
+ TRIGGER_APPLICATION_FILTER: {
133
+ name: 'NAME',
134
+ variables: 'VARIABLES',
135
+ result: 'RESULT',
136
+ error: 'ERROR',
137
+ },
129
138
  },
130
139
 
131
140
  BRICK_TEXT_INPUT: {
@@ -142,6 +151,13 @@ export const templateActionNameMap = {
142
151
  },
143
152
  },
144
153
 
154
+ BRICK_VIDEO: {
155
+ BRICK_VIDEO_SEEK: {
156
+ seekTime: 'BRICK_VIDEO_SEEK_TIME',
157
+ play: 'BRICK_VIDEO_PLAY',
158
+ },
159
+ },
160
+
145
161
  BRICK_SLIDESHOW: {
146
162
  BRICK_SLIDESHOW_JUMP_TO_INDEX: {
147
163
  index: 'BRICK_SLIDESHOW_INDEX',
@@ -231,7 +247,12 @@ export const templateActionNameMap = {
231
247
  index: 'BRICK_ITEMS_INDEX',
232
248
  },
233
249
  },
234
-
250
+ BRICK_LOTTIE: {
251
+ BRICK_LOTTIE_PLAY: {
252
+ startFrame: 'BRICK_LOTTIE_START_FRAME',
253
+ endFrame: 'BRICK_LOTTIE_END_FRAME',
254
+ },
255
+ },
235
256
  BRICK_RIVE: {
236
257
  BRICK_RIVE_PLAY: {
237
258
  animationName: 'BRICK_RIVE_ANIMATION_NAME',
@@ -257,6 +278,10 @@ export const templateActionNameMap = {
257
278
  BRICK_WEBVIEW_INJECT_JAVASCRIPT: {
258
279
  javascriptCode: 'BRICK_WEBVIEW_JAVASCRIPT_CODE',
259
280
  },
281
+ BRICK_WEBVIEW_QUERY_SELECTOR: {
282
+ querySelector: 'BRICK_WEBVIEW_QUERY_SELECTOR',
283
+ expression: 'BRICK_WEBVIEW_EXPRESSION',
284
+ },
260
285
  },
261
286
  BRICK_CAMERA: {
262
287
  BRICK_CAMERA_TAKE_PICTURE: {
@@ -512,6 +537,36 @@ export const templateActionNameMap = {
512
537
  paramsString: 'GENERATOR_SQLITE_PARAMS_STRING',
513
538
  },
514
539
  },
540
+
541
+ GENERATOR_MCP: {
542
+ GENERATOR_MCP_LIST_RESOURCES: {
543
+ requestId: 'GENERATOR_MCP_REQUEST_ID',
544
+ },
545
+ GENERATOR_MCP_LIST_RESOURCE_TEMPLATES: {
546
+ requestId: 'GENERATOR_MCP_REQUEST_ID',
547
+ },
548
+ GENERATOR_MCP_READ_RESOURCE: {
549
+ requestId: 'GENERATOR_MCP_REQUEST_ID',
550
+ uri: 'GENERATOR_MCP_URI',
551
+ variables: 'GENERATOR_MCP_VARIABLES',
552
+ },
553
+ GENERATOR_MCP_LIST_TOOLS: {
554
+ requestId: 'GENERATOR_MCP_REQUEST_ID',
555
+ },
556
+ GENERATOR_MCP_CALL_TOOL: {
557
+ requestId: 'GENERATOR_MCP_REQUEST_ID',
558
+ name: 'GENERATOR_MCP_NAME',
559
+ variables: 'GENERATOR_MCP_VARIABLES',
560
+ },
561
+ GENERATOR_MCP_LIST_PROMPTS: {
562
+ requestId: 'GENERATOR_MCP_REQUEST_ID',
563
+ },
564
+ GENERATOR_MCP_GET_PROMPT: {
565
+ requestId: 'GENERATOR_MCP_REQUEST_ID',
566
+ name: 'GENERATOR_MCP_NAME',
567
+ variables: 'GENERATOR_MCP_VARIABLES',
568
+ },
569
+ },
515
570
  GENERATOR_TTS: {
516
571
  GENERATOR_TTS_GENERATE: {
517
572
  text: 'GENERATOR_TTS_TEXT',
@@ -521,6 +576,9 @@ export const templateActionNameMap = {
521
576
  GENERATOR_ONNX_LLM_INFER: {
522
577
  prompt: 'GENERATOR_ONNX_LLM_PROMPT',
523
578
  chat: 'GENERATOR_ONNX_LLM_CHAT',
579
+ images: 'GENERATOR_ONNX_LLM_IMAGES',
580
+ tools: 'GENERATOR_ONNX_LLM_TOOLS',
581
+ toolChoice: 'GENERATOR_ONNX_LLM_TOOL_CHOICE',
524
582
  },
525
583
  },
526
584
  GENERATOR_ONNX_STT: {
@@ -558,7 +616,37 @@ export const templateActionNameMap = {
558
616
  realtimeVadFreqThold: 'GENERATOR_SPEECH_INFERENCE_REALTIME_VAD_FREQ_THOLD',
559
617
  },
560
618
  },
619
+ GENERATOR_VAD_INFERENCE: {
620
+ GENERATOR_VAD_INFERENCE_DETECT_FILE: {
621
+ fileUrl: 'GENERATOR_VAD_INFERENCE_FILE_URL',
622
+ threshold: 'GENERATOR_VAD_INFERENCE_THRESHOLD',
623
+ minSpeechDurationMs: 'GENERATOR_VAD_INFERENCE_MIN_SPEECH_DURATION_MS',
624
+ minSilenceDurationMs: 'GENERATOR_VAD_INFERENCE_MIN_SILENCE_DURATION_MS',
625
+ maxSpeechDurationS: 'GENERATOR_VAD_INFERENCE_MAX_SPEECH_DURATION_S',
626
+ speechPadMs: 'GENERATOR_VAD_INFERENCE_SPEECH_PAD_MS',
627
+ samplesOverlap: 'GENERATOR_VAD_INFERENCE_SAMPLES_OVERLAP',
628
+ },
629
+ GENERATOR_VAD_INFERENCE_DETECT_DATA: {
630
+ data: 'GENERATOR_VAD_INFERENCE_DATA',
631
+ threshold: 'GENERATOR_VAD_INFERENCE_THRESHOLD',
632
+ minSpeechDurationMs: 'GENERATOR_VAD_INFERENCE_MIN_SPEECH_DURATION_MS',
633
+ minSilenceDurationMs: 'GENERATOR_VAD_INFERENCE_MIN_SILENCE_DURATION_MS',
634
+ maxSpeechDurationS: 'GENERATOR_VAD_INFERENCE_MAX_SPEECH_DURATION_S',
635
+ speechPadMs: 'GENERATOR_VAD_INFERENCE_SPEECH_PAD_MS',
636
+ samplesOverlap: 'GENERATOR_VAD_INFERENCE_SAMPLES_OVERLAP',
637
+ },
638
+ },
639
+
561
640
  GENERATOR_LLM: {
641
+ GENERATOR_LLM_TOKENIZE: {
642
+ mode: 'GENERATOR_LLM_MODE',
643
+ prompt: 'GENERATOR_LLM_PROMPT',
644
+ promptMediaPaths: 'GENERATOR_LLM_PROMPT_MEDIA_PATHS',
645
+ messages: 'GENERATOR_LLM_MESSAGES',
646
+ },
647
+ GENERATOR_LLM_DETOKENIZE: {
648
+ tokens: 'GENERATOR_LLM_TOKENS',
649
+ },
562
650
  GENERATOR_LLM_PROCESS_PROMPT: {
563
651
  sessionKey: 'GENERATOR_LLM_SESSION_KEY',
564
652
  mode: 'GENERATOR_LLM_MODE',
@@ -566,7 +654,9 @@ export const templateActionNameMap = {
566
654
  tools: 'GENERATOR_LLM_TOOLS',
567
655
  parallelToolCalls: 'GENERATOR_LLM_PARALLEL_TOOL_CALLS',
568
656
  toolChoice: 'GENERATOR_LLM_TOOL_CHOICE',
657
+ enableThinking: 'GENERATOR_LLM_ENABLE_THINKING',
569
658
  prompt: 'GENERATOR_LLM_PROMPT',
659
+ promptMediaPaths: 'GENERATOR_LLM_PROMPT_MEDIA_PATHS',
570
660
  promptTemplateData: 'GENERATOR_LLM_PROMPT_TEMPLATE_DATA',
571
661
  promptTemplateType: 'GENERATOR_LLM_PROMPT_TEMPLATE_TYPE',
572
662
  responseFormat: 'GENERATOR_LLM_RESPONSE_FORMAT',
@@ -578,7 +668,9 @@ export const templateActionNameMap = {
578
668
  tools: 'GENERATOR_LLM_TOOLS',
579
669
  parallelToolCalls: 'GENERATOR_LLM_PARALLEL_TOOL_CALLS',
580
670
  toolChoice: 'GENERATOR_LLM_TOOL_CHOICE',
671
+ enableThinking: 'GENERATOR_LLM_ENABLE_THINKING',
581
672
  prompt: 'GENERATOR_LLM_PROMPT',
673
+ promptMediaPaths: 'GENERATOR_LLM_PROMPT_MEDIA_PATHS',
582
674
  promptTemplateData: 'GENERATOR_LLM_PROMPT_TEMPLATE_DATA',
583
675
  promptTemplateType: 'GENERATOR_LLM_PROMPT_TEMPLATE_TYPE',
584
676
  responseFormat: 'GENERATOR_LLM_RESPONSE_FORMAT',
@@ -615,6 +707,24 @@ export const templateActionNameMap = {
615
707
  sessionCustomKey: 'GENERATOR_LLM_SESSION_CUSTOM_KEY',
616
708
  },
617
709
  },
710
+ GENERATOR_GGML_TTS: {
711
+ GENERATOR_GGML_TTS_GENERATE: {
712
+ text: 'GENERATOR_GGML_TTS_TEXT',
713
+ },
714
+ },
715
+ GENERATOR_RERANKER: {
716
+ GENERATOR_RERANKER_RERANK: {
717
+ query: 'GENERATOR_RERANKER_QUERY',
718
+ documents: 'GENERATOR_RERANKER_DOCUMENTS',
719
+ },
720
+ },
721
+ GENERATOR_QNN_LLM: {
722
+ GENERATOR_QNN_LLM_GENERATE: {
723
+ prompt: 'GENERATOR_QNN_LLM_PROMPT',
724
+ messages: 'GENERATOR_QNN_LLM_MESSAGES',
725
+ tools: 'GENERATOR_QNN_LLM_TOOLS',
726
+ },
727
+ },
618
728
  GENERATOR_OPENAI_LLM: {
619
729
  GENERATOR_OPENAI_LLM_COMPLETION: {
620
730
  messages: 'GENERATOR_OPENAI_LLM_MESSAGES',
@@ -630,10 +740,16 @@ export const templateActionNameMap = {
630
740
  responseFormat: 'GENERATOR_OPENAI_LLM_RESPONSE_FORMAT',
631
741
  },
632
742
  },
743
+ GENERATOR_OPENAI_TTS: {
744
+ GENERATOR_OPENAI_TTS_GENERATE: {
745
+ text: 'GENERATOR_OPENAI_TTS_TEXT',
746
+ },
747
+ },
633
748
  GENERATOR_ASSISTANT: {
634
749
  GENERATOR_ASSISTANT_ADD_MESSAGE: {
635
750
  role: 'GENERATOR_ASSISTANT_ROLE',
636
751
  content: 'GENERATOR_ASSISTANT_CONTENT',
752
+ image: 'GENERATOR_ASSISTANT_IMAGE',
637
753
  payload: 'GENERATOR_ASSISTANT_PAYLOAD',
638
754
  useFileSearch: 'GENERATOR_ASSISTANT_USE_FILE_SEARCH',
639
755
  filePath: 'GENERATOR_ASSISTANT_FILE_PATH',
@@ -643,15 +759,28 @@ export const templateActionNameMap = {
643
759
  fileSearchCitationCount: 'GENERATOR_ASSISTANT_FILE_SEARCH_CITATION_COUNT',
644
760
  fileSearchInsertMethod: 'GENERATOR_ASSISTANT_FILE_SEARCH_INSERT_METHOD',
645
761
  },
762
+ GENERATOR_ASSISTANT_INIT_MCP_PROMPT: {
763
+ mcpClientName: 'GENERATOR_ASSISTANT_MCP_CLIENT_NAME',
764
+ mcpPromptName: 'GENERATOR_ASSISTANT_MCP_PROMPT_NAME',
765
+ mcpArguments: 'GENERATOR_ASSISTANT_MCP_ARGUMENTS',
766
+ firstMessageAsSystem: 'GENERATOR_ASSISTANT_FIRST_MESSAGE_AS_SYSTEM',
767
+ },
768
+ GENERATOR_ASSISTANT_ADD_MCP_PROMPT_MESSAGE: {
769
+ mcpClientName: 'GENERATOR_ASSISTANT_MCP_CLIENT_NAME',
770
+ mcpPromptName: 'GENERATOR_ASSISTANT_MCP_PROMPT_NAME',
771
+ mcpArguments: 'GENERATOR_ASSISTANT_MCP_ARGUMENTS',
772
+ },
646
773
  GENERATOR_ASSISTANT_UPDATE_MESSAGE_AT_INDEX: {
647
774
  index: 'GENERATOR_ASSISTANT_INDEX',
648
775
  content: 'GENERATOR_ASSISTANT_CONTENT',
776
+ image: 'GENERATOR_ASSISTANT_IMAGE',
649
777
  payload: 'GENERATOR_ASSISTANT_PAYLOAD',
650
778
  },
651
779
  GENERATOR_ASSISTANT_ADD_AUDIO_MESSAGE: {
652
780
  role: 'GENERATOR_ASSISTANT_ROLE',
653
781
  contentFile: 'GENERATOR_ASSISTANT_CONTENT_FILE',
654
782
  contentBase64: 'GENERATOR_ASSISTANT_CONTENT_BASE64',
783
+ image: 'GENERATOR_ASSISTANT_IMAGE',
655
784
  useFileSearch: 'GENERATOR_ASSISTANT_USE_FILE_SEARCH',
656
785
  payload: 'GENERATOR_ASSISTANT_PAYLOAD',
657
786
  filePath: 'GENERATOR_ASSISTANT_FILE_PATH',
@@ -674,11 +803,27 @@ export const templateActionNameMap = {
674
803
  index: 'GENERATOR_ASSISTANT_INDEX',
675
804
  contentFile: 'GENERATOR_ASSISTANT_CONTENT_FILE',
676
805
  contentBase64: 'GENERATOR_ASSISTANT_CONTENT_BASE64',
806
+ image: 'GENERATOR_ASSISTANT_IMAGE',
677
807
  payload: 'GENERATOR_ASSISTANT_PAYLOAD',
678
808
  },
679
809
  GENERATOR_ASSISTANT_REMOVE_MESSAGE_AT_INDEX: {
680
810
  index: 'GENERATOR_ASSISTANT_INDEX',
681
811
  },
812
+ GENERATOR_ASSISTANT_SUBMIT: {
813
+ continueOnToolCallConfirm: 'GENERATOR_ASSISTANT_CONTINUE_ON_TOOL_CALL_CONFIRM',
814
+ continueOnToolCallStrategy: 'GENERATOR_ASSISTANT_CONTINUE_ON_TOOL_CALL_STRATEGY',
815
+ continueOnToolCallLimit: 'GENERATOR_ASSISTANT_CONTINUE_ON_TOOL_CALL_LIMIT',
816
+ },
817
+ GENERATOR_ASSISTANT_INSERT_MCP_RESOURCE: {
818
+ mcpClientName: 'GENERATOR_ASSISTANT_MCP_CLIENT_NAME',
819
+ mcpResourceUri: 'GENERATOR_ASSISTANT_MCP_RESOURCE_URI',
820
+ mcpVariables: 'GENERATOR_ASSISTANT_MCP_VARIABLES',
821
+ role: 'GENERATOR_ASSISTANT_ROLE',
822
+ },
823
+ GENERATOR_ASSISTANT_SUMMARY_MESSAGES: {
824
+ summaryMessages: 'GENERATOR_ASSISTANT_SUMMARY_MESSAGES',
825
+ summarySessionKey: 'GENERATOR_ASSISTANT_SUMMARY_SESSION_KEY',
826
+ },
682
827
  },
683
828
  GENERATOR_VECTOR_STORE: {
684
829
  GENERATOR_VECTOR_STORE_RESET: {
package/compile/index.ts CHANGED
@@ -856,6 +856,7 @@ export const compile = async (app: Application) => {
856
856
  fonts: app.fonts,
857
857
  ...compileApplicationSettings(app.settings),
858
858
  test_map: app.metadata?.TEMP_test_map || {},
859
+ automation_map: app.metadata?.TEMP_automation_map || {},
859
860
  }
860
861
  return config
861
862
  }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@fugood/bricks-project",
3
- "version": "2.22.0-beta.2",
3
+ "version": "2.22.0-beta.22",
4
4
  "main": "index.ts",
5
5
  "scripts": {
6
6
  "build": "node scripts/build.js"
7
7
  },
8
8
  "dependencies": {
9
+ "@modelcontextprotocol/sdk": "^1.15.0",
9
10
  "@types/escodegen": "^0.0.10",
10
11
  "@types/lodash": "^4.17.12",
11
12
  "acorn": "^8.13.0",
@@ -13,5 +14,5 @@
13
14
  "lodash": "^4.17.4",
14
15
  "uuid": "^8.3.1"
15
16
  },
16
- "gitHead": "a230efafdd33bc1dd02ed6397cf5741b318e172f"
17
+ "gitHead": "f1a67a715ee30aac5067df53b8b640511a81fc83"
17
18
  }
@@ -0,0 +1,86 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
3
+ import { z } from 'zod'
4
+ import { $ } from 'bun'
5
+
6
+ const server = new McpServer({
7
+ name: 'bricks-project',
8
+ version: '1.0.0',
9
+ })
10
+
11
+ const dirname = import.meta.dirname
12
+ const projectDir = String(dirname).split('/node_modules/')[0]
13
+
14
+ server.tool('compile', {}, async () => {
15
+ let log
16
+ try {
17
+ log = await $`bun compile`.cwd(projectDir).text()
18
+ } catch (err) {
19
+ log = err.stdout.toString() + '\n' + err.stderr.toString()
20
+ }
21
+ return {
22
+ content: [{ type: 'text', text: log || 'Compiled successfully' }],
23
+ }
24
+ })
25
+
26
+ // NOTE: Cursor (Or VSCode) seems set ELECTRON_RUN_AS_NODE to 1, so we need to unset it
27
+ process.env.ELECTRON_RUN_AS_NODE = ''
28
+
29
+ server.tool(
30
+ 'take-preview-screenshot',
31
+ {
32
+ delay: z
33
+ .number()
34
+ .describe('Delay in milliseconds before taking screenshot')
35
+ .optional()
36
+ .default(3000),
37
+ width: z.number().describe('Width of the screenshot').optional().default(600),
38
+ height: z.number().optional().default(480),
39
+ responseImage: z
40
+ .boolean()
41
+ .describe(
42
+ 'Whether to response image content (base64 encoded jpeg). If false, only saved path will be responded as text.',
43
+ )
44
+ .optional()
45
+ .default(false),
46
+ } as any,
47
+ async ({ delay, width, height, responseImage }: any) => {
48
+ let log = ''
49
+ let error = false
50
+ try {
51
+ const args = [
52
+ '--take-screenshot',
53
+ JSON.stringify({
54
+ delay,
55
+ width,
56
+ height,
57
+ path: `${dirname}/screenshot.jpg`,
58
+ closeAfter: true,
59
+ headless: true,
60
+ }),
61
+ ]
62
+ log = await $`bunx --bun electron ${dirname}/preview-main.mjs ${args}`.cwd(projectDir).text()
63
+ } catch (err) {
64
+ log = err.stdout.toString() + '\n' + err.stderr.toString()
65
+ error = true
66
+ }
67
+ let screenshotBase64: any = null
68
+ if (!error && responseImage) {
69
+ const screenshot = await Bun.file(`${dirname}/screenshot.jpg`).arrayBuffer()
70
+ screenshotBase64 = Buffer.from(screenshot).toString('base64')
71
+ }
72
+ return {
73
+ content: [
74
+ { type: 'text', text: log },
75
+ screenshotBase64 && {
76
+ type: 'image',
77
+ data: screenshotBase64,
78
+ mimeType: 'image/jpeg',
79
+ },
80
+ ].filter(Boolean),
81
+ }
82
+ },
83
+ )
84
+
85
+ const transport = new StdioServerTransport()
86
+ await server.connect(transport)
@@ -1,12 +1,70 @@
1
1
  import { $ } from 'bun'
2
+ import { stat, readFile, writeFile } from 'fs/promises'
2
3
 
3
4
  const cwd = process.cwd()
4
5
 
5
- const libFiles = ['types', 'utils', 'index.ts']
6
+ async function exists(f: string) {
7
+ try {
8
+ await stat(f)
9
+ return true
10
+ } catch {
11
+ return false
12
+ }
13
+ }
14
+
15
+ // handle flag --skip-copy
16
+ const skipCopyProject = process.argv.includes('--skip-copy-project')
17
+ if (skipCopyProject) {
18
+ console.log('Skipping copy of files to project/')
19
+ } else {
20
+
21
+ const libFiles = ['types', 'utils', 'index.ts']
22
+
23
+ await $`mkdir -p ${cwd}/project`
24
+ for (const file of libFiles) {
25
+ await $`cp -r ${__dirname}/../${file} ${cwd}/project`
26
+ }
27
+ console.log('Copied files to project/')
28
+ }
6
29
 
7
- await $`mkdir -p ${cwd}/project`
8
- for (const file of libFiles) {
9
- await $`cp -r ${__dirname}/../${file} ${cwd}/project`
30
+ const projectMcpServer = {
31
+ command: 'bun',
32
+ args: [`${cwd}/node_modules/@fugood/bricks-project/tools/mcp-server.ts`],
10
33
  }
11
34
 
12
- console.log('Copied files to project/')
35
+ const defaultMcpConfig = {
36
+ mcpServers: {
37
+ 'bricks-project': projectMcpServer,
38
+ },
39
+ }
40
+
41
+ const handleMcpConfigOverride = async (mcpConfigPath: string) => {
42
+ let mcpConfig: { mcpServers: Record<string, typeof projectMcpServer> } | null = null
43
+ if (await exists(mcpConfigPath)) {
44
+ const configStr = await readFile(mcpConfigPath, 'utf-8')
45
+ try {
46
+ mcpConfig = JSON.parse(configStr)
47
+ if (!mcpConfig?.mcpServers) throw new Error('mcpServers is not defined')
48
+ mcpConfig.mcpServers['bricks-project'] = projectMcpServer
49
+ } catch (e) {
50
+ mcpConfig = defaultMcpConfig
51
+ }
52
+ } else {
53
+ mcpConfig = defaultMcpConfig
54
+ }
55
+
56
+ await writeFile(mcpConfigPath, `${JSON.stringify(mcpConfig, null, 2)}\n`)
57
+
58
+ console.log(`Updated ${mcpConfigPath}`)
59
+ }
60
+
61
+ if (await exists(`${cwd}/.cursor/rules/instructions.mdc`)) {
62
+ const cursorMcpConfigPath = `${cwd}/.cursor/mcp.json`
63
+ await handleMcpConfigOverride(cursorMcpConfigPath)
64
+ }
65
+
66
+ if (await exists(`${cwd}/CLAUDE.md`)) {
67
+ await $`mkdir -p ${cwd}/.cursor`
68
+ const claudeCodeMcpConfigPath = `${cwd}/.mcp.json`
69
+ await handleMcpConfigOverride(claudeCodeMcpConfigPath)
70
+ }
@@ -20,7 +20,7 @@ let takeScreenshotConfig = null
20
20
  try {
21
21
  if (values['take-screenshot']) {
22
22
  takeScreenshotConfig = JSON.parse(values['take-screenshot'])
23
- if (!takeScreenshotConfig.path) takeScreenshotConfig.path = `${cwd}/screenshot.png`
23
+ if (!takeScreenshotConfig.path) takeScreenshotConfig.path = `${cwd}/screenshot.jpg`
24
24
  if (!takeScreenshotConfig.width) takeScreenshotConfig.width = 1280
25
25
  if (!takeScreenshotConfig.height) takeScreenshotConfig.height = 768
26
26
  if (!takeScreenshotConfig.delay) takeScreenshotConfig.delay = 1000
@@ -46,8 +46,13 @@ if (!previewUrl) throw new Error(`Invalid BRICKS_STAGE: ${stage}`)
46
46
 
47
47
  app.on('ready', () => {
48
48
  let show = true
49
- if (takeScreenshotConfig?.headless) show = false
50
- const mainWindow = new BrowserWindow({ width: 1280, height: 768, show })
49
+ if (takeScreenshotConfig && !takeScreenshotConfig.noHeadless) show = false
50
+ const mainWindow = new BrowserWindow({
51
+ width: takeScreenshotConfig?.width || 1280,
52
+ height: takeScreenshotConfig?.height || 768,
53
+ frame: !takeScreenshotConfig,
54
+ show,
55
+ })
51
56
  mainWindow.setBackgroundColor('#333')
52
57
  mainWindow.loadURL(previewUrl)
53
58
 
@@ -56,18 +61,19 @@ app.on('ready', () => {
56
61
  type: 'config',
57
62
  configFile: { _originTitle: 'Test', ...config, title: Math.random().toString() },
58
63
  workspace: { billing: { lock: {}, plan: 'free' } },
64
+ showMenu: false,
59
65
  }
60
66
  mainWindow.webContents.executeJavaScript(
61
67
  `window.postMessage(JSON.stringify(${JSON.stringify(payload)}))`,
62
68
  )
63
69
  if (takeScreenshotConfig) {
64
- const { delay, width, height, path, closeAfter } = takeScreenshotConfig
70
+ const { delay, width, height, path, keepOpen = false } = takeScreenshotConfig
65
71
  setTimeout(() => {
66
72
  console.log('Taking screenshot')
67
- mainWindow.webContents.capturePage({ width, height }).then((image) => {
73
+ mainWindow.webContents.capturePage().then((image) => {
68
74
  console.log('Writing screenshot to', path)
69
- writeFile(path, image.toPNG())
70
- if (closeAfter) {
75
+ writeFile(path, image.resize({ width, height }).toJPEG(75))
76
+ if (!keepOpen) {
71
77
  console.log('Closing app')
72
78
  app.quit()
73
79
  }
package/tools/preview.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { $ } from 'bun'
2
2
  import { watch } from 'fs'
3
+ import type { FSWatcher } from 'fs'
3
4
  import { parseArgs } from 'util'
4
5
  import { debounce } from 'lodash'
5
6
 
@@ -8,55 +9,60 @@ const { values } = parseArgs({
8
9
  options: {
9
10
  'skip-typecheck': { type: 'boolean' },
10
11
  'clear-cache': { type: 'boolean' },
11
- 'screenshot': { type: 'boolean' },
12
+ screenshot: { type: 'boolean' },
12
13
  'screenshot-delay': { type: 'string' },
13
14
  'screenshot-width': { type: 'string' },
14
15
  'screenshot-height': { type: 'string' },
15
16
  'screenshot-path': { type: 'string' },
16
- 'screenshot-close-after': { type: 'boolean' },
17
- 'screenshot-headless': { type: 'boolean' },
17
+ 'screenshot-keep-open': { type: 'boolean' },
18
+ 'screenshot-no-headless': { type: 'boolean' },
18
19
  },
19
20
  strict: true,
20
21
  allowPositionals: true,
21
22
  })
22
23
 
23
- const useTypecheck = !values['skip-typecheck']
24
-
25
- const compile = async () => {
26
- if (useTypecheck) await $`bun typecheck`
27
- await $`bun compile`
28
- }
29
-
30
- await compile()
31
-
32
- const compileDebounced = debounce(compile, 500)
33
-
34
24
  const cwd = process.cwd()
35
25
 
36
- const watcher = watch(`${cwd}/subspaces`, { recursive: true }, async (event, filename) => {
37
- console.log(`Detected ${event} in ${filename}`)
38
- compileDebounced()
39
- })
40
-
41
26
  const app = await Bun.file(`${cwd}/application.json`).json()
42
27
 
43
28
  let args: string[] = []
44
29
  if (values['clear-cache']) args.push('--clear-cache')
45
30
 
31
+ let needWatcher = true
46
32
  if (values['screenshot']) {
47
33
  args.push(`--take-screenshot`)
34
+ const keepOpen = values['screenshot-keep-open'] ?? false
48
35
  args.push(
49
36
  JSON.stringify({
50
37
  delay: Number(values['screenshot-delay']) || 1000,
51
- width: Number(values['screenshot-width']) || 1920,
52
- height: Number(values['screenshot-height']) || 1080,
53
- path: values['screenshot-path'] || `${cwd}/screenshot.png`,
54
- closeAfter: values['screenshot-close-after'] ?? true,
55
- headless: values['screenshot-headless'] ?? true,
38
+ width: Number(values['screenshot-width']) || 600,
39
+ height: Number(values['screenshot-height']) || 480,
40
+ path: values['screenshot-path'] || `${cwd}/screenshot.jpg`,
41
+ keepOpen,
42
+ noHeadless: values['screenshot-no-headless'] ?? false,
56
43
  }),
57
44
  )
45
+ needWatcher = keepOpen
46
+ }
47
+
48
+ const useTypecheck = !values['skip-typecheck']
49
+
50
+ const compile = async () => {
51
+ if (useTypecheck) await $`bun typecheck`
52
+ await $`bun compile`
53
+ }
54
+
55
+ await compile()
56
+
57
+ let watcher: FSWatcher | null = null
58
+ if (needWatcher) {
59
+ const compileDebounced = debounce(compile, 500)
60
+ watcher = watch(`${cwd}/subspaces`, { recursive: true }, async (event, filename) => {
61
+ console.log(`Detected ${event} in ${filename}`)
62
+ compileDebounced()
63
+ })
58
64
  }
59
65
 
60
66
  await $`BRICKS_STAGE=${app.stage || 'production'} bunx --bun electron ${__dirname}/preview-main.mjs ${args}`
61
67
 
62
- watcher.close()
68
+ if (watcher) watcher.close()