goatchain-cli 0.0.9-beta.20 → 0.0.9-beta.23

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.
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env node
2
+ import childProcess from 'node:child_process'
3
+ import fs from 'node:fs'
4
+ import os from 'node:os'
5
+ import path from 'node:path'
6
+ import process from 'node:process'
7
+ import { fileURLToPath, pathToFileURL } from 'node:url'
8
+
9
+ const __filename = fileURLToPath(import.meta.url)
10
+ const __dirname = path.dirname(__filename)
11
+ const isWindows = os.platform() === 'win32'
12
+
13
+ let wrapperVersion = ''
14
+ try {
15
+ const pkg = JSON.parse(
16
+ fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'),
17
+ )
18
+ wrapperVersion = pkg.version || ''
19
+ }
20
+ catch {}
21
+
22
+ const wrapperDir = path.join(__dirname, '..').replace(/\\/g, '/').toLowerCase()
23
+ const wrapperPm
24
+ = wrapperDir.includes('.bun/') || wrapperDir.includes('bun/install/')
25
+ ? 'bun'
26
+ : 'npm'
27
+
28
+ const args = process.argv.slice(2)
29
+ const routing = resolveRouting(args)
30
+
31
+ if (routing.target === 'opentui') {
32
+ runOpentui(routing.forwardArgs)
33
+ }
34
+ else {
35
+ await runInk()
36
+ }
37
+
38
+ function resolveRouting(argv) {
39
+ // Explicit `goatchain ink ...` forces the Ink TUI.
40
+ if (argv[0] === 'ink')
41
+ return { target: 'ink', forwardArgs: argv.slice(1) }
42
+ // Explicit `goatchain opentui ...` forces the opentui binary.
43
+ if (argv[0] === 'opentui')
44
+ return { target: 'opentui', forwardArgs: argv.slice(1) }
45
+
46
+ // Known subcommands handled only by the opentui binary.
47
+ const first = String(argv[0] ?? '').trim().toLowerCase()
48
+ const opentuiSubcommands = new Set([
49
+ 'version',
50
+ '--version',
51
+ '-v',
52
+ 'upgrade',
53
+ 'update',
54
+ 'acp',
55
+ 'auth',
56
+ 'exec',
57
+ 'e',
58
+ '--help',
59
+ '-h',
60
+ ])
61
+ if (opentuiSubcommands.has(first))
62
+ return { target: 'opentui', forwardArgs: argv }
63
+
64
+ // One-shot prompt (non-flag first positional, e.g. `goatchain hi`) or
65
+ // one-shot flags (`--cwd`, `--session`, `--no-interaction`) go to opentui.
66
+ if (isOneShotPromptArgv(argv))
67
+ return { target: 'opentui', forwardArgs: argv }
68
+
69
+ // Bare invocation (no args) or flag-only invocation: default to Ink.
70
+ return { target: 'ink', forwardArgs: argv }
71
+ }
72
+
73
+ function isOneShotPromptArgv(argv) {
74
+ const oneShotFlags = new Set([
75
+ '-c',
76
+ '-cwd',
77
+ '--cwd',
78
+ '--chdir',
79
+ '-s',
80
+ '--session',
81
+ '--no-interaction',
82
+ ])
83
+ let sawOneShotFlag = false
84
+ for (let i = 0; i < argv.length; i++) {
85
+ const arg = String(argv[i] ?? '').trim()
86
+ if (!arg)
87
+ continue
88
+ if (arg === '--')
89
+ return true
90
+ if (arg.startsWith('-cwd=')) {
91
+ sawOneShotFlag = true
92
+ continue
93
+ }
94
+ if (oneShotFlags.has(arg)) {
95
+ sawOneShotFlag = true
96
+ i += 1
97
+ continue
98
+ }
99
+ if (arg.startsWith('-'))
100
+ return false
101
+ return true
102
+ }
103
+ return sawOneShotFlag
104
+ }
105
+
106
+ async function runInk() {
107
+ const inkEntry = path.join(__dirname, '..', 'dist', 'ink.mjs')
108
+ if (!fs.existsSync(inkEntry)) {
109
+ console.error('[goatchain] Ink bundle missing: ' + inkEntry)
110
+ console.error('[goatchain] Try reinstalling goatchain-cli.')
111
+ process.exit(1)
112
+ }
113
+ // Inject wrapper identity so the in-process upgrade check targets the
114
+ // npm wrapper package rather than upstream `dimcode`.
115
+ process.env.DIMCODE_NPM_PACKAGE = 'goatchain-cli'
116
+ process.env.DIMCODE_NPM_PACKAGE_MANAGER = wrapperPm
117
+ if (wrapperVersion)
118
+ process.env.DIMCODE_NPM_PACKAGE_VERSION = wrapperVersion
119
+ try {
120
+ await import(pathToFileURL(inkEntry).href)
121
+ }
122
+ catch (err) {
123
+ console.error('[goatchain] Failed to start Ink TUI:')
124
+ console.error(err)
125
+ process.exit(1)
126
+ }
127
+ }
128
+
129
+ function runOpentui(restArgs) {
130
+ const envPath = process.env.DIMCODE_BIN_PATH
131
+ if (envPath) {
132
+ if (!fs.existsSync(envPath)) {
133
+ console.error(
134
+ '[goatchain] DIMCODE_BIN_PATH is set but file not found: ' + envPath,
135
+ )
136
+ process.exit(1)
137
+ }
138
+ spawnBinary(envPath, restArgs)
139
+ return
140
+ }
141
+
142
+ const scriptPath = fs.realpathSync(__filename)
143
+ const scriptDir = path.dirname(scriptPath)
144
+
145
+ const platformMap = { darwin: 'darwin', linux: 'linux', win32: 'windows' }
146
+ const archMap = { x64: 'x64', arm64: 'arm64' }
147
+ const platform = platformMap[os.platform()] || os.platform()
148
+ const arch = archMap[os.arch()] || os.arch()
149
+ const base = 'goatchain-cli-' + platform + '-' + arch
150
+ const binary = platform === 'windows' ? 'goatchain.exe' : 'goatchain'
151
+
152
+ if (process.env.DIMCODE_DEBUG) {
153
+ console.error('[goatchain] Wrapper version: ' + wrapperVersion)
154
+ console.error('[goatchain] Platform: ' + platform + ' Arch: ' + arch)
155
+ console.error('[goatchain] Looking for package: ' + base)
156
+ console.error('[goatchain] Script dir: ' + scriptDir)
157
+ }
158
+
159
+ const resolved = findBinary(scriptDir, base, binary)
160
+ if (!resolved) {
161
+ console.error(
162
+ '[goatchain] Could not find the opentui binary for your platform.\n'
163
+ + '\n'
164
+ + ' Platform: ' + os.platform() + ' (' + platform + ')\n'
165
+ + ' Arch: ' + os.arch() + ' (' + arch + ')\n'
166
+ + ' Expected: ' + base + '/bin/' + binary + '\n'
167
+ + ' Searched: ' + scriptDir + ' (and parent directories)\n'
168
+ + '\n'
169
+ + 'Try manually installing the platform package:\n'
170
+ + ' npm install ' + base + '\n',
171
+ )
172
+ process.exit(1)
173
+ }
174
+
175
+ if (process.env.DIMCODE_DEBUG)
176
+ console.error('[goatchain] Resolved binary: ' + resolved)
177
+
178
+ spawnBinary(resolved, restArgs)
179
+ }
180
+
181
+ function findBinary(startDir, base, binary) {
182
+ let current = startDir
183
+ for (;;) {
184
+ const modules = path.join(current, 'node_modules')
185
+ if (fs.existsSync(modules)) {
186
+ const candidate = path.join(modules, base, 'bin', binary)
187
+ if (fs.existsSync(candidate))
188
+ return candidate
189
+ }
190
+ const parent = path.dirname(current)
191
+ if (parent === current)
192
+ return
193
+ current = parent
194
+ }
195
+ }
196
+
197
+ function spawnBinary(target, forwardedArgs) {
198
+ const env = {
199
+ ...process.env,
200
+ DIMCODE_NPM_PACKAGE: 'goatchain-cli',
201
+ DIMCODE_NPM_PACKAGE_MANAGER: wrapperPm,
202
+ }
203
+ if (wrapperVersion)
204
+ env.DIMCODE_NPM_PACKAGE_VERSION = wrapperVersion
205
+
206
+ const result = childProcess.spawnSync(target, forwardedArgs, {
207
+ stdio: 'inherit',
208
+ cwd: process.cwd(),
209
+ env,
210
+ windowsHide: false,
211
+ })
212
+ if (result.error) {
213
+ console.error(
214
+ '[goatchain] Failed to start opentui binary: ' + result.error.message,
215
+ )
216
+ if (isWindows) {
217
+ console.error('[goatchain] Binary path: ' + target)
218
+ if (result.error.code === 'ENOENT') {
219
+ console.error(
220
+ '[goatchain] The binary file was not found. Try reinstalling:',
221
+ )
222
+ console.error(
223
+ ' npm uninstall -g goatchain-cli && npm install -g goatchain-cli',
224
+ )
225
+ }
226
+ }
227
+ process.exit(1)
228
+ }
229
+ if (result.status !== 0 && result.status !== null) {
230
+ if (process.env.DIMCODE_DEBUG)
231
+ console.error('[goatchain] Binary exited with code: ' + result.status)
232
+ }
233
+ process.exit(typeof result.status === 'number' ? result.status : 0)
234
+ }