@fugood/bricks-ctor 2.25.0-beta.60 → 2.25.0-beta.62
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/package.json +4 -28
- package/tools/__tests__/legacy-forwarder.test.js +91 -0
- package/tools/_forward.ts +26 -0
- package/tools/deploy.ts +3 -175
- package/tools/mcp-server.ts +3 -35
- package/tools/postinstall.ts +3 -291
- package/tools/pull.ts +3 -198
- package/tools/push-config.ts +3 -113
- package/tools/simulator.ts +3 -149
- package/compile/__tests__/config-diff.test.js +0 -100
- package/compile/__tests__/index.test.js +0 -461
- package/compile/__tests__/util.test.js +0 -450
- package/compile/action-name-map.ts +0 -1079
- package/compile/config-diff.ts +0 -155
- package/compile/index.ts +0 -1594
- package/compile/util.ts +0 -482
- package/index.ts +0 -6
- package/skills/bricks-ctor/SKILL.md +0 -38
- package/skills/bricks-ctor/references/animation.md +0 -160
- package/skills/bricks-ctor/references/architecture-patterns.md +0 -88
- package/skills/bricks-ctor/references/automations.md +0 -232
- package/skills/bricks-ctor/references/buttress.md +0 -245
- package/skills/bricks-ctor/references/data-calculation.md +0 -252
- package/skills/bricks-ctor/references/local-sync.md +0 -129
- package/skills/bricks-ctor/references/media-flow.md +0 -165
- package/skills/bricks-ctor/references/remote-data-bank.md +0 -196
- package/skills/bricks-ctor/references/simulator.md +0 -132
- package/skills/bricks-ctor/references/source-editing-tools.md +0 -81
- package/skills/bricks-ctor/references/standby-transition.md +0 -124
- package/skills/bricks-ctor/references/verification-toolchain.md +0 -200
- package/skills/bricks-design/SKILL.md +0 -171
- package/skills/bricks-design/references/architecture-truths.md +0 -132
- package/skills/bricks-design/references/avoiding-complexity.md +0 -91
- package/skills/bricks-design/references/design-critique.md +0 -195
- package/skills/bricks-design/references/design-languages.md +0 -265
- package/skills/bricks-design/references/performance.md +0 -116
- package/skills/bricks-design/references/presentation-and-slideshow.md +0 -137
- package/skills/bricks-design/references/translating-inputs.md +0 -152
- package/skills/bricks-design/references/variations-and-tweaks.md +0 -124
- package/skills/bricks-design/references/when-the-brief-is-branded.md +0 -284
- package/skills/bricks-design/references/when-the-brief-is-vague.md +0 -85
- package/skills/bricks-design/references/workflow.md +0 -134
- package/skills/bricks-ux/SKILL.md +0 -114
- package/skills/bricks-ux/references/accessibility.md +0 -162
- package/skills/bricks-ux/references/flow-states.md +0 -175
- package/skills/bricks-ux/references/interaction-archetypes.md +0 -189
- package/skills/bricks-ux/references/monitoring-screens.md +0 -153
- package/skills/bricks-ux/references/pressable-composition.md +0 -126
- package/skills/bricks-ux/references/user-journey.md +0 -168
- package/skills/bricks-ux/references/ux-critique.md +0 -256
- package/skills/rive-marketplace/SKILL.md +0 -99
- package/tools/__tests__/_cli-error.test.ts +0 -35
- package/tools/__tests__/_mcp-config.test.ts +0 -67
- package/tools/__tests__/pull.test.ts +0 -108
- package/tools/_cli-error.ts +0 -17
- package/tools/_edits-log.ts +0 -41
- package/tools/_git-author.ts +0 -37
- package/tools/_last-pushed-commit.ts +0 -28
- package/tools/_mcp-config.ts +0 -42
- package/tools/_shell.ts +0 -180
- package/tools/icons/.gitattributes +0 -1
- package/tools/icons/fa6pro-glyphmap.json +0 -4686
- package/tools/icons/fa6pro-meta.json +0 -1
- package/tools/mcp-env.ts +0 -13
- package/tools/mcp-tools/__tests__/data-calc-editing.test.js +0 -516
- package/tools/mcp-tools/__tests__/entry-editing.test.js +0 -866
- package/tools/mcp-tools/__tests__/huggingface.test.ts +0 -49
- package/tools/mcp-tools/__tests__/icons.test.ts +0 -21
- package/tools/mcp-tools/__tests__/mcp-env.test.js +0 -19
- package/tools/mcp-tools/_editing-helpers.ts +0 -98
- package/tools/mcp-tools/_verify.ts +0 -50
- package/tools/mcp-tools/compile.ts +0 -104
- package/tools/mcp-tools/data-calc-editing.ts +0 -1311
- package/tools/mcp-tools/entry-editing.ts +0 -2297
- package/tools/mcp-tools/huggingface.ts +0 -772
- package/tools/mcp-tools/icons.ts +0 -97
- package/tools/mcp-tools/lottie.ts +0 -102
- package/tools/mcp-tools/media.ts +0 -113
- package/tools/simulator-main.mjs +0 -488
- package/tools/simulator-preload.cjs +0 -16
- package/types/animation.d.ts +0 -116
- package/types/automation.d.ts +0 -231
- package/types/brick-base.d.ts +0 -80
- package/types/bricks/Camera.d.ts +0 -246
- package/types/bricks/Chart.d.ts +0 -372
- package/types/bricks/GenerativeMedia.d.ts +0 -290
- package/types/bricks/Icon.d.ts +0 -98
- package/types/bricks/Image.d.ts +0 -126
- package/types/bricks/Items.d.ts +0 -480
- package/types/bricks/Lottie.d.ts +0 -168
- package/types/bricks/Maps.d.ts +0 -262
- package/types/bricks/QrCode.d.ts +0 -117
- package/types/bricks/Rect.d.ts +0 -150
- package/types/bricks/RichText.d.ts +0 -131
- package/types/bricks/Rive.d.ts +0 -220
- package/types/bricks/Scene3D.d.ts +0 -676
- package/types/bricks/Sketch.d.ts +0 -256
- package/types/bricks/Slideshow.d.ts +0 -201
- package/types/bricks/Svg.d.ts +0 -99
- package/types/bricks/Text.d.ts +0 -148
- package/types/bricks/TextInput.d.ts +0 -242
- package/types/bricks/Video.d.ts +0 -242
- package/types/bricks/VideoStreaming.d.ts +0 -112
- package/types/bricks/WebRtcStream.d.ts +0 -65
- package/types/bricks/WebView.d.ts +0 -168
- package/types/bricks/index.d.ts +0 -23
- package/types/canvas.d.ts +0 -82
- package/types/common.d.ts +0 -141
- package/types/data-calc-command/base.d.ts +0 -57
- package/types/data-calc-command/collection.d.ts +0 -418
- package/types/data-calc-command/color.d.ts +0 -432
- package/types/data-calc-command/constant.d.ts +0 -50
- package/types/data-calc-command/datetime.d.ts +0 -147
- package/types/data-calc-command/file.d.ts +0 -129
- package/types/data-calc-command/index.d.ts +0 -13
- package/types/data-calc-command/iteratee.d.ts +0 -23
- package/types/data-calc-command/logictype.d.ts +0 -190
- package/types/data-calc-command/math.d.ts +0 -275
- package/types/data-calc-command/object.d.ts +0 -119
- package/types/data-calc-command/sandbox.d.ts +0 -66
- package/types/data-calc-command/string.d.ts +0 -407
- package/types/data-calc-script.d.ts +0 -21
- package/types/data-calc.d.ts +0 -12
- package/types/data.d.ts +0 -97
- package/types/generators/AlarmClock.d.ts +0 -110
- package/types/generators/Assistant.d.ts +0 -640
- package/types/generators/BleCentral.d.ts +0 -247
- package/types/generators/BlePeripheral.d.ts +0 -208
- package/types/generators/CanvasMap.d.ts +0 -74
- package/types/generators/CastlesPay.d.ts +0 -87
- package/types/generators/DataBank.d.ts +0 -160
- package/types/generators/File.d.ts +0 -432
- package/types/generators/GraphQl.d.ts +0 -132
- package/types/generators/Http.d.ts +0 -222
- package/types/generators/HttpServer.d.ts +0 -230
- package/types/generators/Information.d.ts +0 -103
- package/types/generators/Intent.d.ts +0 -168
- package/types/generators/Iterator.d.ts +0 -108
- package/types/generators/Keyboard.d.ts +0 -105
- package/types/generators/LlmAnthropicCompat.d.ts +0 -212
- package/types/generators/LlmAppleBuiltin.d.ts +0 -159
- package/types/generators/LlmGgml.d.ts +0 -903
- package/types/generators/LlmMediaTekNeuroPilot.d.ts +0 -235
- package/types/generators/LlmMlx.d.ts +0 -228
- package/types/generators/LlmOnnx.d.ts +0 -213
- package/types/generators/LlmOpenAiCompat.d.ts +0 -312
- package/types/generators/LlmQualcommAiEngine.d.ts +0 -247
- package/types/generators/Mcp.d.ts +0 -637
- package/types/generators/McpServer.d.ts +0 -289
- package/types/generators/MediaFlow.d.ts +0 -170
- package/types/generators/MqttBroker.d.ts +0 -141
- package/types/generators/MqttClient.d.ts +0 -141
- package/types/generators/Question.d.ts +0 -408
- package/types/generators/RealtimeTranscription.d.ts +0 -287
- package/types/generators/RerankerGgml.d.ts +0 -195
- package/types/generators/SerialPort.d.ts +0 -151
- package/types/generators/SoundPlayer.d.ts +0 -94
- package/types/generators/SoundRecorder.d.ts +0 -139
- package/types/generators/SpeechToTextGgml.d.ts +0 -424
- package/types/generators/SpeechToTextOnnx.d.ts +0 -236
- package/types/generators/SpeechToTextPlatform.d.ts +0 -85
- package/types/generators/SqLite.d.ts +0 -159
- package/types/generators/Step.d.ts +0 -107
- package/types/generators/SttAppleBuiltin.d.ts +0 -153
- package/types/generators/Tcp.d.ts +0 -126
- package/types/generators/TcpServer.d.ts +0 -147
- package/types/generators/TextToSpeechAppleBuiltin.d.ts +0 -127
- package/types/generators/TextToSpeechGgml.d.ts +0 -221
- package/types/generators/TextToSpeechOnnx.d.ts +0 -178
- package/types/generators/TextToSpeechOpenAiLike.d.ts +0 -121
- package/types/generators/ThermalPrinter.d.ts +0 -193
- package/types/generators/Tick.d.ts +0 -83
- package/types/generators/Udp.d.ts +0 -120
- package/types/generators/VadGgml.d.ts +0 -260
- package/types/generators/VadOnnx.d.ts +0 -231
- package/types/generators/VadTraditional.d.ts +0 -138
- package/types/generators/VectorStore.d.ts +0 -257
- package/types/generators/Watchdog.d.ts +0 -107
- package/types/generators/WebCrawler.d.ts +0 -103
- package/types/generators/WebRtc.d.ts +0 -181
- package/types/generators/WebSocket.d.ts +0 -148
- package/types/generators/index.d.ts +0 -57
- package/types/index.d.ts +0 -13
- package/types/subspace.d.ts +0 -60
- package/types/switch.d.ts +0 -51
- package/types/system.d.ts +0 -707
- package/utils/__tests__/calc.test.js +0 -25
- package/utils/__tests__/id.test.js +0 -154
- package/utils/calc.ts +0 -130
- package/utils/data.ts +0 -495
- package/utils/event-props.ts +0 -912
- package/utils/id.ts +0 -133
package/package.json
CHANGED
|
@@ -1,33 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fugood/bricks-ctor",
|
|
3
|
-
"version": "2.25.0-beta.
|
|
4
|
-
"
|
|
5
|
-
"scripts": {
|
|
6
|
-
"typecheck": "tsc --noEmit",
|
|
7
|
-
"build": "bun scripts/build.js"
|
|
8
|
-
},
|
|
3
|
+
"version": "2.25.0-beta.62",
|
|
4
|
+
"description": "Deprecated: ctor tooling moved to the `bricks ctor` commands in @fugood/bricks-cli. This package now only forwards legacy project scripts and triggers migration.",
|
|
9
5
|
"dependencies": {
|
|
10
|
-
"@
|
|
11
|
-
"@babel/parser": "7.28.5",
|
|
12
|
-
"@babel/traverse": "7.28.5",
|
|
13
|
-
"@babel/types": "7.28.5",
|
|
14
|
-
"@fugood/bricks-cli": "^2.25.0-beta.60",
|
|
15
|
-
"@huggingface/gguf": "^0.3.2",
|
|
16
|
-
"@iarna/toml": "^3.0.0",
|
|
17
|
-
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
18
|
-
"@toon-format/toon": "^2.1.0",
|
|
19
|
-
"@types/bun": "^1.3.9",
|
|
20
|
-
"@types/escodegen": "^0.0.10",
|
|
21
|
-
"@types/lodash": "^4.17.12",
|
|
22
|
-
"acorn": "^8.13.0",
|
|
23
|
-
"escodegen": "2.1.0",
|
|
24
|
-
"fuse.js": "^7.0.0",
|
|
25
|
-
"json5": "^2.0.1",
|
|
26
|
-
"lodash": "^4.17.4",
|
|
27
|
-
"uuid": "^8.3.1"
|
|
28
|
-
},
|
|
29
|
-
"peerDependencies": {
|
|
30
|
-
"oxfmt": "^0.36.0"
|
|
6
|
+
"@fugood/bricks-cli": "^2.25.0-beta.62"
|
|
31
7
|
},
|
|
32
|
-
"gitHead": "
|
|
8
|
+
"gitHead": "22ea0986230856c59dbf9acccc63bdc4fd97deed"
|
|
33
9
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const mockSpawnSync = jest.fn()
|
|
2
|
+
const mockExistsSync = jest.fn()
|
|
3
|
+
|
|
4
|
+
jest.mock('node:child_process', () => ({
|
|
5
|
+
__esModule: true,
|
|
6
|
+
spawnSync: (...args) => mockSpawnSync(...args),
|
|
7
|
+
}))
|
|
8
|
+
|
|
9
|
+
jest.mock('node:fs', () => ({
|
|
10
|
+
__esModule: true,
|
|
11
|
+
existsSync: (...args) => mockExistsSync(...args),
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
const loadForwarder = () => require('../_forward.ts')
|
|
15
|
+
|
|
16
|
+
describe('legacy bricks-ctor forwarder', () => {
|
|
17
|
+
let exitSpy
|
|
18
|
+
let errorSpy
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
jest.resetModules()
|
|
22
|
+
mockSpawnSync.mockReset()
|
|
23
|
+
mockExistsSync.mockReset()
|
|
24
|
+
exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {})
|
|
25
|
+
errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
exitSpy.mockRestore()
|
|
30
|
+
errorSpy.mockRestore()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('prefers the local bricks CLI next to the legacy package', () => {
|
|
34
|
+
mockExistsSync.mockReturnValue(true)
|
|
35
|
+
mockSpawnSync.mockReturnValue({ status: 0 })
|
|
36
|
+
const { forwardLegacyCtorTool } = loadForwarder()
|
|
37
|
+
|
|
38
|
+
forwardLegacyCtorTool(
|
|
39
|
+
'deploy',
|
|
40
|
+
'file:///repo/node_modules/@fugood/bricks-ctor/tools/deploy.ts',
|
|
41
|
+
['--target', 'device'],
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
expect(mockSpawnSync).toHaveBeenCalledWith(
|
|
45
|
+
'/repo/node_modules/.bin/bricks',
|
|
46
|
+
['ctor', 'deploy', '--target', 'device'],
|
|
47
|
+
{ stdio: 'inherit' },
|
|
48
|
+
)
|
|
49
|
+
expect(exitSpy).toHaveBeenCalledWith(0)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('falls back to PATH when the local bricks CLI is missing', () => {
|
|
53
|
+
mockExistsSync.mockReturnValue(false)
|
|
54
|
+
mockSpawnSync.mockReturnValue({ status: 3 })
|
|
55
|
+
const { forwardLegacyCtorTool } = loadForwarder()
|
|
56
|
+
|
|
57
|
+
forwardLegacyCtorTool('pull', 'file:///repo/node_modules/@fugood/bricks-ctor/tools/pull.ts', [])
|
|
58
|
+
|
|
59
|
+
expect(mockSpawnSync).toHaveBeenCalledWith('bricks', ['ctor', 'pull'], { stdio: 'inherit' })
|
|
60
|
+
expect(exitSpy).toHaveBeenCalledWith(3)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('reports spawn errors and exits with failure', () => {
|
|
64
|
+
mockExistsSync.mockReturnValue(false)
|
|
65
|
+
mockSpawnSync.mockReturnValue({ error: new Error('ENOENT') })
|
|
66
|
+
const { forwardLegacyCtorTool } = loadForwarder()
|
|
67
|
+
|
|
68
|
+
forwardLegacyCtorTool(
|
|
69
|
+
'mcp',
|
|
70
|
+
'file:///repo/node_modules/@fugood/bricks-ctor/tools/mcp-server.ts',
|
|
71
|
+
[],
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
expect(errorSpy).toHaveBeenCalledWith('bricks-ctor forwarder failed to run `bricks`: ENOENT')
|
|
75
|
+
expect(exitSpy).toHaveBeenCalledWith(1)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('treats a missing child status as failure', () => {
|
|
79
|
+
mockExistsSync.mockReturnValue(false)
|
|
80
|
+
mockSpawnSync.mockReturnValue({})
|
|
81
|
+
const { forwardLegacyCtorTool } = loadForwarder()
|
|
82
|
+
|
|
83
|
+
forwardLegacyCtorTool(
|
|
84
|
+
'simulator',
|
|
85
|
+
'file:///repo/node_modules/@fugood/bricks-ctor/tools/simulator.ts',
|
|
86
|
+
[],
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
expect(exitSpy).toHaveBeenCalledWith(1)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
// @fugood/bricks-ctor is deprecated; all tooling now lives in @fugood/bricks-cli.
|
|
6
|
+
// This shared forwarder keeps legacy project scripts working until postinstall migrates them.
|
|
7
|
+
export function resolveLegacyBricksCommand(baseUrl: string) {
|
|
8
|
+
const localBricks = fileURLToPath(new URL('../../../.bin/bricks', baseUrl))
|
|
9
|
+
return existsSync(localBricks) ? localBricks : 'bricks'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function forwardLegacyCtorTool(
|
|
13
|
+
command: string,
|
|
14
|
+
baseUrl: string,
|
|
15
|
+
args = process.argv.slice(2),
|
|
16
|
+
) {
|
|
17
|
+
const bricks = resolveLegacyBricksCommand(baseUrl)
|
|
18
|
+
const result = spawnSync(bricks, ['ctor', command, ...args], { stdio: 'inherit' })
|
|
19
|
+
|
|
20
|
+
if (result.error) {
|
|
21
|
+
console.error(`bricks-ctor forwarder failed to run \`${bricks}\`: ${result.error.message}`)
|
|
22
|
+
process.exit(1)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
process.exit(result.status ?? 1)
|
|
26
|
+
}
|
package/tools/deploy.ts
CHANGED
|
@@ -1,176 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { sh } from './_shell'
|
|
4
|
-
import { extractCliErrorMessage } from './_cli-error'
|
|
5
|
-
import { buildCommitArgs } from './_git-author'
|
|
6
|
-
import { writeLastPushedCommit } from './_last-pushed-commit'
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { forwardLegacyCtorTool } from './_forward.ts'
|
|
7
3
|
|
|
8
|
-
|
|
9
|
-
process.env.BRICKS_RELEASE_SIGN = 'CTOR'
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const cwd = process.cwd()
|
|
13
|
-
|
|
14
|
-
const exists = async (p: string) => {
|
|
15
|
-
try {
|
|
16
|
-
await access(p)
|
|
17
|
-
return true
|
|
18
|
-
} catch {
|
|
19
|
-
return false
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const readJson = async (p: string) => JSON.parse(await readFile(p, 'utf8'))
|
|
24
|
-
|
|
25
|
-
const {
|
|
26
|
-
values: {
|
|
27
|
-
changelogs: changelogsArg,
|
|
28
|
-
'changelogs-file': changelogsFile,
|
|
29
|
-
'auto-commit': autoCommit,
|
|
30
|
-
'auto-version': autoVersion,
|
|
31
|
-
version: versionArg,
|
|
32
|
-
yes,
|
|
33
|
-
help,
|
|
34
|
-
},
|
|
35
|
-
} = parseArgs({
|
|
36
|
-
args: process.argv.slice(2),
|
|
37
|
-
options: {
|
|
38
|
-
changelogs: { type: 'string' },
|
|
39
|
-
'changelogs-file': { type: 'string' },
|
|
40
|
-
'auto-commit': { type: 'boolean' },
|
|
41
|
-
'auto-version': { type: 'boolean' },
|
|
42
|
-
version: { type: 'string' },
|
|
43
|
-
yes: { type: 'boolean', short: 'y' },
|
|
44
|
-
help: { type: 'boolean', short: 'h' },
|
|
45
|
-
},
|
|
46
|
-
allowPositionals: true,
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
if (help) {
|
|
50
|
-
console.log(`Options:
|
|
51
|
-
--changelogs <text> Changelogs text for the release
|
|
52
|
-
--changelogs-file <path> Read changelogs from a file
|
|
53
|
-
--auto-commit Auto-commit unstaged changes before deploying
|
|
54
|
-
--auto-version Auto-bump patch version before deploying
|
|
55
|
-
--version <version> Set explicit version for the release
|
|
56
|
-
-y, --yes Skip all prompts
|
|
57
|
-
-h, --help Show this help message`)
|
|
58
|
-
process.exit(0)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Check git status
|
|
62
|
-
const { exitCode } = await sh`cd ${cwd} && git status`.quiet().nothrow()
|
|
63
|
-
const isGitRepo = exitCode === 0
|
|
64
|
-
|
|
65
|
-
if (!isGitRepo && !yes) {
|
|
66
|
-
const confirmContinue = prompt('No git repository found, continue? (y/n)')
|
|
67
|
-
if (confirmContinue !== 'y') throw new Error('Deployment cancelled')
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Read application.json
|
|
71
|
-
const app = await readJson(`${cwd}/application.json`)
|
|
72
|
-
const config = await readJson(`${cwd}/.bricks/build/application-config.json`)
|
|
73
|
-
|
|
74
|
-
// Resolve version: explicit flag > auto-bump > package.json
|
|
75
|
-
const pkgPath = `${cwd}/package.json`
|
|
76
|
-
const pkgExists = await exists(pkgPath)
|
|
77
|
-
let version: string | undefined
|
|
78
|
-
|
|
79
|
-
if (versionArg) {
|
|
80
|
-
version = versionArg
|
|
81
|
-
if (pkgExists) {
|
|
82
|
-
const pkg = await readJson(pkgPath)
|
|
83
|
-
pkg.version = version
|
|
84
|
-
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
|
|
85
|
-
}
|
|
86
|
-
} else if (autoVersion && pkgExists) {
|
|
87
|
-
const pkg = await readJson(pkgPath)
|
|
88
|
-
const parts = (pkg.version || '0.0.0').split('.')
|
|
89
|
-
parts[2] = String(Number(parts[2] || 0) + 1)
|
|
90
|
-
version = parts.join('.')
|
|
91
|
-
pkg.version = version
|
|
92
|
-
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
|
|
93
|
-
} else {
|
|
94
|
-
version = pkgExists ? (await readJson(pkgPath)).version : undefined
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Get changelog from flag or file
|
|
98
|
-
let changelogs = ''
|
|
99
|
-
if (changelogsArg) {
|
|
100
|
-
changelogs = changelogsArg
|
|
101
|
-
} else if (changelogsFile) {
|
|
102
|
-
if (!(await exists(changelogsFile))) {
|
|
103
|
-
throw new Error(`Changelogs file not found: ${changelogsFile}`)
|
|
104
|
-
}
|
|
105
|
-
changelogs = await readFile(changelogsFile, 'utf8')
|
|
106
|
-
} else if (!yes) {
|
|
107
|
-
changelogs = prompt('Enter changelogs (optional, press Enter to skip):') || ''
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Handle unstaged changes
|
|
111
|
-
let commitId = ''
|
|
112
|
-
if (isGitRepo) {
|
|
113
|
-
const unstagedChanges = await sh`cd ${cwd} && git diff --name-only --diff-filter=ACMR`.text()
|
|
114
|
-
if (unstagedChanges) {
|
|
115
|
-
if (autoCommit) {
|
|
116
|
-
const commitMsg = `chore: release ${version || 'new version'}`
|
|
117
|
-
const commitBody = changelogs || '[no changelogs]'
|
|
118
|
-
await sh`cd ${cwd} && git add -A`
|
|
119
|
-
const commitArgs = await buildCommitArgs(cwd, [commitMsg, commitBody])
|
|
120
|
-
await sh`cd ${cwd} && git ${commitArgs}`
|
|
121
|
-
} else {
|
|
122
|
-
throw new Error(
|
|
123
|
-
'Unstaged changes found, please commit or stash your changes before deploying',
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
commitId = (await sh`cd ${cwd} && git rev-parse HEAD`.text()).trim()
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Ask for confirmation
|
|
131
|
-
if (!yes) {
|
|
132
|
-
const confirm = prompt('Are you sure you want to deploy? (y/n)')
|
|
133
|
-
if (confirm !== 'y') throw new Error('Deployment cancelled')
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const isModule = app.type === 'module'
|
|
137
|
-
const command = isModule ? 'module' : 'app'
|
|
138
|
-
|
|
139
|
-
// Add project-specific fields to config and write to temp file
|
|
140
|
-
const releaseConfig = {
|
|
141
|
-
...config,
|
|
142
|
-
title: version || config.title,
|
|
143
|
-
bricks_project_last_commit_id: commitId || undefined,
|
|
144
|
-
}
|
|
145
|
-
const configPath = `${cwd}/.bricks/build/release-config.json`
|
|
146
|
-
await writeFile(configPath, JSON.stringify(releaseConfig))
|
|
147
|
-
|
|
148
|
-
const args = ['bricks', command, 'release', app.id, '-c', configPath, '--json']
|
|
149
|
-
|
|
150
|
-
if (app.name) {
|
|
151
|
-
args.push('--name', app.name)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (version) {
|
|
155
|
-
args.push('--version', version)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (changelogs) {
|
|
159
|
-
args.push('--changelogs', changelogs)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const result = await sh`${args}`.quiet().nothrow()
|
|
163
|
-
|
|
164
|
-
if (result.exitCode !== 0) {
|
|
165
|
-
const output = result.stderr.toString() || result.stdout.toString()
|
|
166
|
-
throw new Error(extractCliErrorMessage(output, 'Release failed'))
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const output = JSON.parse(result.stdout.toString())
|
|
170
|
-
|
|
171
|
-
// Record the commit we just pushed from so a later pull can use it as the
|
|
172
|
-
// merge base regardless of what the server stores in
|
|
173
|
-
// bricks_project_last_commit_id.
|
|
174
|
-
if (commitId) await writeLastPushedCommit(cwd, commitId)
|
|
175
|
-
|
|
176
|
-
console.log(`${isModule ? 'Module' : 'App'} deployed: ${output.name}`)
|
|
4
|
+
forwardLegacyCtorTool('deploy', import.meta.url)
|
package/tools/mcp-server.ts
CHANGED
|
@@ -1,36 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { forwardLegacyCtorTool } from './_forward.ts'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
import { register as registerLottie } from './mcp-tools/lottie'
|
|
6
|
-
import { register as registerIcons } from './mcp-tools/icons'
|
|
7
|
-
import { register as registerHuggingface } from './mcp-tools/huggingface'
|
|
8
|
-
import { register as registerMedia } from './mcp-tools/media'
|
|
9
|
-
import { register as registerEntryEditing } from './mcp-tools/entry-editing'
|
|
10
|
-
import { register as registerDataCalcEditing } from './mcp-tools/data-calc-editing'
|
|
11
|
-
import { shouldRegisterEditingTools } from './mcp-env'
|
|
12
|
-
|
|
13
|
-
const server = new McpServer({
|
|
14
|
-
name: 'bricks-ctor',
|
|
15
|
-
version: '1.0.0',
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
const { dirname } = import.meta
|
|
19
|
-
const projectDir = String(dirname).split('/node_modules/')[0]
|
|
20
|
-
|
|
21
|
-
// NOTE: Cursor (Or VSCode) seems set ELECTRON_RUN_AS_NODE to 1, so we need to unset it
|
|
22
|
-
process.env.ELECTRON_RUN_AS_NODE = ''
|
|
23
|
-
|
|
24
|
-
registerCompile(server, projectDir)
|
|
25
|
-
registerLottie(server)
|
|
26
|
-
registerIcons(server)
|
|
27
|
-
registerHuggingface(server)
|
|
28
|
-
registerMedia(server, projectDir)
|
|
29
|
-
|
|
30
|
-
if (shouldRegisterEditingTools()) {
|
|
31
|
-
registerEntryEditing(server, projectDir)
|
|
32
|
-
registerDataCalcEditing(server, projectDir)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const transport = new StdioServerTransport()
|
|
36
|
-
await server.connect(transport)
|
|
4
|
+
forwardLegacyCtorTool('mcp', import.meta.url)
|
package/tools/postinstall.ts
CHANGED
|
@@ -1,292 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
lstat,
|
|
4
|
-
mkdir,
|
|
5
|
-
readFile,
|
|
6
|
-
readdir,
|
|
7
|
-
readlink,
|
|
8
|
-
rm,
|
|
9
|
-
stat,
|
|
10
|
-
symlink,
|
|
11
|
-
writeFile,
|
|
12
|
-
} from 'fs/promises'
|
|
13
|
-
import * as path from 'path'
|
|
14
|
-
import TOML from '@iarna/toml'
|
|
15
|
-
import { handleMcpConfigOverride } from './_mcp-config'
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { forwardLegacyCtorTool } from './_forward.ts'
|
|
16
3
|
|
|
17
|
-
|
|
18
|
-
const projectSkillsDir = path.join(cwd, '.bricks', 'skills')
|
|
19
|
-
const compatibilitySkillLinks = [
|
|
20
|
-
path.join(cwd, '.claude', 'skills'),
|
|
21
|
-
path.join(cwd, '.codex', 'skills'),
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
async function exists(f: string) {
|
|
25
|
-
try {
|
|
26
|
-
await stat(f)
|
|
27
|
-
return true
|
|
28
|
-
} catch {
|
|
29
|
-
return false
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function pathExists(f: string) {
|
|
34
|
-
try {
|
|
35
|
-
await lstat(f)
|
|
36
|
-
return true
|
|
37
|
-
} catch {
|
|
38
|
-
return false
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Migrate old projects: remove legacy project/ directory
|
|
43
|
-
const oldProjectDir = path.join(cwd, 'project')
|
|
44
|
-
if (await exists(oldProjectDir)) {
|
|
45
|
-
await rm(oldProjectDir, { recursive: true, force: true })
|
|
46
|
-
console.log('Removed legacy project/ directory')
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// handle flag --skip-copy
|
|
50
|
-
const skipCopyProject = process.argv.includes('--skip-copy-project')
|
|
51
|
-
if (skipCopyProject) {
|
|
52
|
-
console.log('Skipping copy of files to ctor/')
|
|
53
|
-
} else {
|
|
54
|
-
const libFiles = ['types', 'utils', 'index.ts']
|
|
55
|
-
|
|
56
|
-
const ctorDir = path.join(cwd, 'ctor')
|
|
57
|
-
await mkdir(ctorDir, { recursive: true })
|
|
58
|
-
await Promise.all(
|
|
59
|
-
libFiles.map((file) =>
|
|
60
|
-
cp(path.join(import.meta.dirname, '..', file), path.join(ctorDir, file), {
|
|
61
|
-
recursive: true,
|
|
62
|
-
}),
|
|
63
|
-
),
|
|
64
|
-
)
|
|
65
|
-
console.log('Copied files to ctor/')
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const projectMcpServer = {
|
|
69
|
-
command: 'bun',
|
|
70
|
-
args: [`${cwd}/node_modules/@fugood/bricks-ctor/tools/mcp-server.ts`],
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Codex cancels MCP tool calls it cannot prompt approval for (e.g. `codex exec`),
|
|
74
|
-
// so the project-local server's tools must be pre-approved in its config entry.
|
|
75
|
-
const codexProjectMcpServer = {
|
|
76
|
-
...projectMcpServer,
|
|
77
|
-
default_tools_approval_mode: 'approve',
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
type CodexMcpConfig = {
|
|
81
|
-
mcp_servers: Record<string, typeof codexProjectMcpServer | typeof projectMcpServer>
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const hasClaudeCode = await exists(`${cwd}/CLAUDE.md`)
|
|
85
|
-
const hasAgentsMd = await exists(`${cwd}/AGENTS.md`)
|
|
86
|
-
|
|
87
|
-
if (hasClaudeCode || hasAgentsMd) {
|
|
88
|
-
// Keep the workspace-level JSON MCP config aligned for tools that read .mcp.json.
|
|
89
|
-
const mcpConfigPath = `${cwd}/.mcp.json`
|
|
90
|
-
await handleMcpConfigOverride(mcpConfigPath, projectMcpServer)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const copyMissingSkills = async (sourceDir: string, targetDir: string) => {
|
|
94
|
-
if (!(await exists(sourceDir))) return
|
|
95
|
-
|
|
96
|
-
const packageSkills = await readdir(sourceDir, { withFileTypes: true })
|
|
97
|
-
const skillsToInstall = packageSkills.filter(
|
|
98
|
-
(entry) => entry.isDirectory() && !entry.name.startsWith('.'),
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
await mkdir(targetDir, { recursive: true })
|
|
102
|
-
|
|
103
|
-
await Promise.all(
|
|
104
|
-
skillsToInstall.map(async (entry) => {
|
|
105
|
-
const targetSkillDir = path.join(targetDir, entry.name)
|
|
106
|
-
if (await exists(targetSkillDir)) {
|
|
107
|
-
console.log(`Skill '${entry.name}' already exists, skipping`)
|
|
108
|
-
} else {
|
|
109
|
-
await cp(path.join(sourceDir, entry.name), targetSkillDir, { recursive: true })
|
|
110
|
-
console.log(`Installed skill '${entry.name}' to ${targetDir}/`)
|
|
111
|
-
}
|
|
112
|
-
}),
|
|
113
|
-
)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const migrateSkillsDir = async (legacySkillsDir: string, canonicalSkillsDir: string) => {
|
|
117
|
-
if (!(await pathExists(legacySkillsDir))) return
|
|
118
|
-
|
|
119
|
-
const legacyStats = await lstat(legacySkillsDir)
|
|
120
|
-
|
|
121
|
-
if (legacyStats.isSymbolicLink()) {
|
|
122
|
-
const linkTarget = await readlink(legacySkillsDir)
|
|
123
|
-
const resolvedTarget = path.resolve(path.dirname(legacySkillsDir), linkTarget)
|
|
124
|
-
if (resolvedTarget === canonicalSkillsDir) return
|
|
125
|
-
|
|
126
|
-
await copyMissingSkills(resolvedTarget, canonicalSkillsDir)
|
|
127
|
-
await rm(legacySkillsDir, { force: true, recursive: true })
|
|
128
|
-
return
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (legacyStats.isDirectory()) {
|
|
132
|
-
await copyMissingSkills(legacySkillsDir, canonicalSkillsDir)
|
|
133
|
-
await rm(legacySkillsDir, { force: true, recursive: true })
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
console.warn(`Skipping skills migration for ${legacySkillsDir}; expected a directory or symlink`)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const ensureCompatibilitySkillLink = async (linkPath: string, targetDir: string) => {
|
|
141
|
-
await mkdir(path.dirname(linkPath), { recursive: true })
|
|
142
|
-
|
|
143
|
-
if (await pathExists(linkPath)) {
|
|
144
|
-
const linkStats = await lstat(linkPath)
|
|
145
|
-
if (linkStats.isSymbolicLink()) {
|
|
146
|
-
const linkTarget = await readlink(linkPath)
|
|
147
|
-
const resolvedTarget = path.resolve(path.dirname(linkPath), linkTarget)
|
|
148
|
-
if (resolvedTarget === targetDir) return
|
|
149
|
-
} else {
|
|
150
|
-
console.warn(
|
|
151
|
-
`Skipping skills symlink at ${linkPath}; path already exists and is not a symlink`,
|
|
152
|
-
)
|
|
153
|
-
return
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const relativeTarget = path.relative(path.dirname(linkPath), targetDir)
|
|
158
|
-
const symlinkType = process.platform === 'win32' ? 'junction' : 'dir'
|
|
159
|
-
await symlink(relativeTarget, linkPath, symlinkType)
|
|
160
|
-
console.log(`Linked ${linkPath} -> ${relativeTarget}`)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const setupSkills = async () => {
|
|
164
|
-
const packageSkillsDir = path.join(import.meta.dirname, '..', 'skills')
|
|
165
|
-
await mkdir(projectSkillsDir, { recursive: true })
|
|
166
|
-
await copyMissingSkills(packageSkillsDir, projectSkillsDir)
|
|
167
|
-
|
|
168
|
-
for (const linkPath of compatibilitySkillLinks) {
|
|
169
|
-
await migrateSkillsDir(linkPath, projectSkillsDir)
|
|
170
|
-
await ensureCompatibilitySkillLink(linkPath, projectSkillsDir)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (hasClaudeCode || hasAgentsMd) {
|
|
175
|
-
// Install project skills once and expose them through compatibility symlinks.
|
|
176
|
-
await setupSkills()
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
type ClaudeSettings = {
|
|
180
|
-
autoMode?: {
|
|
181
|
-
environment?: string[]
|
|
182
|
-
allow?: string[]
|
|
183
|
-
soft_deny?: string[]
|
|
184
|
-
hard_deny?: string[]
|
|
185
|
-
}
|
|
186
|
-
[key: string]: unknown
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Trusted infrastructure for auto mode's classifier. `$defaults` keeps the
|
|
190
|
-
// built-in environment (the working repo and its git remotes); the extra
|
|
191
|
-
// entries stop routine syncs to the BRICKS backend from being treated as
|
|
192
|
-
// external exfiltration. See https://code.claude.com/docs/en/auto-mode-config
|
|
193
|
-
const autoModeEnvironment = [
|
|
194
|
-
'$defaults',
|
|
195
|
-
'Organization: BRICKS (bricks.tools). Primary use: building BRICKS apps/modules with the bricks CLI and the local bricks-ctor MCP server.',
|
|
196
|
-
'Trusted internal domains: all *.bricks.tools services — api.bricks.tools (project GraphQL API), bank.bricks.tools (config & asset Bank API), cdn.bricks.tools (asset CDN), plus the control/display/activity services. This project syncs its config and assets to these endpoints.',
|
|
197
|
-
]
|
|
198
|
-
|
|
199
|
-
// `.claude/settings.local.json` is per-developer local config; keep it untracked.
|
|
200
|
-
const ensureSettingsLocalGitignored = async () => {
|
|
201
|
-
const gitignorePath = path.join(cwd, '.gitignore')
|
|
202
|
-
const entry = '.claude/settings.local.json'
|
|
203
|
-
const coveredBy = new Set([entry, '.claude', '.claude/', '.claude/*', '*.local.json'])
|
|
204
|
-
|
|
205
|
-
let content = ''
|
|
206
|
-
if (await exists(gitignorePath)) {
|
|
207
|
-
content = await readFile(gitignorePath, 'utf-8')
|
|
208
|
-
if (content.split('\n').some((line) => coveredBy.has(line.trim()))) return
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const separator = content.length === 0 ? '' : content.endsWith('\n') ? '\n' : '\n\n'
|
|
212
|
-
await writeFile(gitignorePath, `${content}${separator}# Claude Code local settings\n${entry}\n`)
|
|
213
|
-
console.log(`Added ${entry} to .gitignore`)
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Pre-configure auto mode once, on initial setup. We only seed the classifier's
|
|
217
|
-
// trusted infrastructure — not `permissions.defaultMode: 'auto'`, which Claude
|
|
218
|
-
// Code ignores from project/local settings (a repo can't grant itself auto mode;
|
|
219
|
-
// it only takes effect from ~/.claude/settings.json). An existing autoMode block
|
|
220
|
-
// is left untouched so reinstalls never clobber a developer's customizations.
|
|
221
|
-
const setupClaudeAutoMode = async () => {
|
|
222
|
-
const settingsPath = path.join(cwd, '.claude', 'settings.local.json')
|
|
223
|
-
|
|
224
|
-
let settings: ClaudeSettings = {}
|
|
225
|
-
if (await exists(settingsPath)) {
|
|
226
|
-
try {
|
|
227
|
-
settings = JSON.parse(await readFile(settingsPath, 'utf-8'))
|
|
228
|
-
} catch {
|
|
229
|
-
console.warn(`Skipping auto mode setup; ${settingsPath} is not valid JSON`)
|
|
230
|
-
return
|
|
231
|
-
}
|
|
232
|
-
if (settings.autoMode) return
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
settings.autoMode = { environment: autoModeEnvironment }
|
|
236
|
-
|
|
237
|
-
await mkdir(path.dirname(settingsPath), { recursive: true })
|
|
238
|
-
await writeFile(settingsPath, `${JSON.stringify(settings, null, 2)}\n`)
|
|
239
|
-
console.log(`Set up auto mode in ${settingsPath}`)
|
|
240
|
-
|
|
241
|
-
await ensureSettingsLocalGitignored()
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (hasClaudeCode) {
|
|
245
|
-
// Pre-configure auto mode's trusted infrastructure for Claude Code projects.
|
|
246
|
-
await setupClaudeAutoMode()
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (hasAgentsMd) {
|
|
250
|
-
// Codex stores its project-local MCP config in .codex/config.toml.
|
|
251
|
-
const defaultCodexMcpConfig = {
|
|
252
|
-
mcp_servers: {
|
|
253
|
-
'bricks-ctor': codexProjectMcpServer,
|
|
254
|
-
},
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const handleCodexMcpConfigOverride = async (mcpConfigPath: string) => {
|
|
258
|
-
let mcpConfig: CodexMcpConfig
|
|
259
|
-
if (await exists(mcpConfigPath)) {
|
|
260
|
-
let parsed: unknown
|
|
261
|
-
try {
|
|
262
|
-
parsed = TOML.parse(await readFile(mcpConfigPath, 'utf-8'))
|
|
263
|
-
} catch {
|
|
264
|
-
// A malformed config is left untouched (with a warning) rather than overwritten with
|
|
265
|
-
// the default — clobbering it would silently delete the user's other server entries.
|
|
266
|
-
// Mirrors handleMcpConfigOverride's handling of a malformed .mcp.json.
|
|
267
|
-
console.warn(`Skipping .codex/config.toml update; ${mcpConfigPath} is not valid TOML`)
|
|
268
|
-
return
|
|
269
|
-
}
|
|
270
|
-
mcpConfig =
|
|
271
|
-
parsed && typeof parsed === 'object' ? (parsed as CodexMcpConfig) : { mcp_servers: {} }
|
|
272
|
-
if (!mcpConfig.mcp_servers || typeof mcpConfig.mcp_servers !== 'object') {
|
|
273
|
-
mcpConfig.mcp_servers = {}
|
|
274
|
-
}
|
|
275
|
-
mcpConfig.mcp_servers['bricks-ctor'] = codexProjectMcpServer
|
|
276
|
-
delete mcpConfig.mcp_servers['bricks-project']
|
|
277
|
-
} else {
|
|
278
|
-
mcpConfig = defaultCodexMcpConfig
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
await writeFile(mcpConfigPath, `${TOML.stringify(mcpConfig)}\n`)
|
|
282
|
-
|
|
283
|
-
console.log(`Updated ${mcpConfigPath}`)
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Keep the Codex TOML MCP config aligned with the same bricks-ctor server entry.
|
|
287
|
-
const codexConfigPath = `${cwd}/.codex/config.toml`
|
|
288
|
-
await handleCodexMcpConfigOverride(codexConfigPath)
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// TODO: .cursor/skills if needed
|
|
292
|
-
// TODO: User setting in application.json to avoid unnecessary skills/config setup
|
|
4
|
+
forwardLegacyCtorTool('postinstall', import.meta.url)
|