jonsoc 1.1.47 → 1.1.48

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 (45) hide show
  1. package/Dockerfile +18 -18
  2. package/bin/jonsoc +265 -265
  3. package/bunfig.toml +7 -7
  4. package/package.json +23 -23
  5. package/src/agent/generate.txt +75 -75
  6. package/src/agent/prompt/compaction.txt +12 -12
  7. package/src/agent/prompt/explore.txt +18 -18
  8. package/src/agent/prompt/summary.txt +11 -11
  9. package/src/agent/prompt/title.txt +44 -44
  10. package/src/command/template/initialize.txt +10 -10
  11. package/src/command/template/review.txt +99 -99
  12. package/src/session/prompt/anthropic-20250930.txt +168 -168
  13. package/src/session/prompt/anthropic.txt +99 -99
  14. package/src/session/prompt/anthropic_spoof.txt +1 -1
  15. package/src/session/prompt/beast.txt +149 -149
  16. package/src/session/prompt/build-switch.txt +5 -5
  17. package/src/session/prompt/codex_header.txt +81 -81
  18. package/src/session/prompt/copilot-gpt-5.txt +145 -145
  19. package/src/session/prompt/gemini.txt +157 -157
  20. package/src/session/prompt/max-steps.txt +15 -15
  21. package/src/session/prompt/plan-reminder-anthropic.txt +67 -67
  22. package/src/session/prompt/plan.txt +26 -26
  23. package/src/session/prompt/qwen.txt +111 -111
  24. package/src/tool/apply_patch.txt +33 -33
  25. package/src/tool/bash.txt +115 -115
  26. package/src/tool/batch.txt +23 -23
  27. package/src/tool/codesearch.txt +12 -12
  28. package/src/tool/edit.txt +10 -10
  29. package/src/tool/glob.txt +6 -6
  30. package/src/tool/grep.txt +8 -8
  31. package/src/tool/ls.txt +1 -1
  32. package/src/tool/lsp.txt +19 -19
  33. package/src/tool/multiedit.txt +41 -41
  34. package/src/tool/plan-enter.txt +14 -14
  35. package/src/tool/plan-exit.txt +13 -13
  36. package/src/tool/question.txt +10 -10
  37. package/src/tool/read.txt +12 -12
  38. package/src/tool/task.txt +60 -60
  39. package/src/tool/todoread.txt +14 -14
  40. package/src/tool/todowrite.txt +167 -167
  41. package/src/tool/webfetch.txt +13 -13
  42. package/src/tool/websearch.txt +14 -14
  43. package/src/tool/write.txt +8 -8
  44. package/test/fixture/lsp/fake-lsp-server.js +77 -77
  45. package/test/tool/__snapshots__/tool.test.ts.snap +9 -9
package/Dockerfile CHANGED
@@ -1,18 +1,18 @@
1
- FROM alpine AS base
2
-
3
- # Disable the runtime transpiler cache by default inside Docker containers.
4
- # On ephemeral containers, the cache is not useful
5
- ARG BUN_RUNTIME_TRANSPILER_CACHE_PATH=0
6
- ENV BUN_RUNTIME_TRANSPILER_CACHE_PATH=${BUN_RUNTIME_TRANSPILER_CACHE_PATH}
7
- RUN apk add libgcc libstdc++ ripgrep
8
-
9
- FROM base AS build-amd64
10
- COPY dist/opencode-linux-x64-baseline-musl/bin/opencode /usr/local/bin/opencode
11
-
12
- FROM base AS build-arm64
13
- COPY dist/opencode-linux-arm64-musl/bin/opencode /usr/local/bin/opencode
14
-
15
- ARG TARGETARCH
16
- FROM build-${TARGETARCH}
17
- RUN opencode --version
18
- ENTRYPOINT ["opencode"]
1
+ FROM alpine AS base
2
+
3
+ # Disable the runtime transpiler cache by default inside Docker containers.
4
+ # On ephemeral containers, the cache is not useful
5
+ ARG BUN_RUNTIME_TRANSPILER_CACHE_PATH=0
6
+ ENV BUN_RUNTIME_TRANSPILER_CACHE_PATH=${BUN_RUNTIME_TRANSPILER_CACHE_PATH}
7
+ RUN apk add libgcc libstdc++ ripgrep
8
+
9
+ FROM base AS build-amd64
10
+ COPY dist/opencode-linux-x64-baseline-musl/bin/opencode /usr/local/bin/opencode
11
+
12
+ FROM base AS build-arm64
13
+ COPY dist/opencode-linux-arm64-musl/bin/opencode /usr/local/bin/opencode
14
+
15
+ ARG TARGETARCH
16
+ FROM build-${TARGETARCH}
17
+ RUN opencode --version
18
+ ENTRYPOINT ["opencode"]
package/bin/jonsoc CHANGED
@@ -1,156 +1,156 @@
1
- #!/usr/bin/env node
2
-
3
- import { spawnSync } from "child_process"
4
- import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs"
5
- import { dirname, join } from "path"
6
- import { platform as osPlatform, arch as osArch, homedir } from "os"
7
- import { fileURLToPath } from "url"
8
- import { xdgData, xdgState } from "xdg-basedir"
9
-
10
- /** Exit code 75 signals a restart request from the TUI */
11
- const EXIT_CODE_RESTART = 75
12
-
13
- const __filename = fileURLToPath(import.meta.url)
14
- const __dirname = dirname(__filename)
15
- const cwd = process.cwd()
16
- const env = {
17
- ...process.env,
18
- JONSOC_WORKDIR: process.env.JONSOC_WORKDIR ?? process.env.JOC_WORKDIR ?? cwd,
19
- JONSOC_CLI: "1",
20
- }
21
-
22
- function run(target, args, options = {}) {
23
- const result = spawnSync(target, args || process.argv.slice(2), {
24
- stdio: "inherit",
25
- shell: osPlatform() === "win32",
26
- cwd: options.cwd,
27
- env: options.env,
28
- })
29
- if (result.error) {
30
- console.error(result.error.message)
31
- process.exit(1)
32
- }
33
- return typeof result.status === "number" ? result.status : 0
34
- }
35
-
36
- const rawArgs = process.argv.slice(2)
37
- const hasFlag = (value) => rawArgs.includes(value)
38
- const safe = hasFlag("-safe") || hasFlag("--safe")
39
- const restart = hasFlag("-restart") || hasFlag("--restart") || hasFlag("-return") || hasFlag("--return")
40
- const autoReturn = hasFlag("-auto-return") || hasFlag("--auto-return")
41
- const check = hasFlag("-check") || hasFlag("--check")
42
- const safeIsolated =
43
- hasFlag("-safe-isolated") ||
44
- hasFlag("--safe-isolated") ||
45
- process.env.JONSOC_SAFE_ISOLATE === "1" ||
46
- process.env.OPENCODE_SAFE_ISOLATE === "1"
47
- const flagSet = new Set([
48
- "-safe",
49
- "--safe",
50
- "-restart",
51
- "--restart",
52
- "-return",
53
- "--return",
54
- "-auto-return",
55
- "--auto-return",
56
- "-check",
57
- "--check",
58
- "-safe-isolated",
59
- "--safe-isolated",
60
- ])
61
- const baseArgs = rawArgs.filter((arg) => !flagSet.has(arg))
62
- const appName = process.env.JONSOC_APP_NAME ?? process.env.OPENCODE_APP_NAME ?? "jonsoc"
63
- const stateAppName = safe && safeIsolated ? `${appName}-safe` : appName
64
-
65
- const stateDir = () => {
66
- const root = xdgState ?? join(homedir(), ".local", "state")
67
- return join(root, stateAppName)
68
- }
69
-
70
- const lastSession = () => {
71
- const filePath = join(stateDir(), "kv.json")
72
- if (!existsSync(filePath)) return
73
- const raw = readFileSync(filePath, "utf8")
74
- if (!raw) return
75
- try {
76
- const data = JSON.parse(raw)
77
- const session = data?.session_last
78
- if (typeof session !== "string") return
79
- return session
80
- } catch {
81
- return
82
- }
83
- }
84
-
85
- const restartArgs = (() => {
86
- if (!restart) return baseArgs
87
- if (baseArgs.includes("--session") || baseArgs.includes("-s")) return baseArgs
88
- const sessionID = lastSession()
89
- if (!sessionID) {
90
- console.error("No recent session found to restart.")
91
- process.exit(1)
92
- }
93
- return ["--session", sessionID, ...baseArgs]
94
- })()
95
-
96
- if (check) {
97
- console.log("running")
98
- process.exit(0)
99
- }
100
-
101
- /** Build args for restart - add --session if we have a last session */
102
- function buildRestartArgs() {
103
- if (baseArgs.includes("--session") || baseArgs.includes("-s")) return baseArgs
104
- const sessionID = lastSession()
105
- if (!sessionID) return baseArgs
106
- return ["--session", sessionID, ...baseArgs]
107
- }
108
-
109
- /** Run the CLI and handle restart exit code */
110
- function runWithRestart(target, prefix, trailingArgs, options = {}) {
111
- let args = [...prefix, ...trailingArgs]
112
- for (;;) {
113
- const code = run(target, args, options)
114
-
115
- // Clean exit (user typed /exit, /quit, or Ctrl+C handled cleanly)
116
- if (code === 0) {
117
- process.exit(0)
118
- }
119
-
120
- // Requested restart (code 75) or Crash/Error (code != 0)
121
- // We always attempt to return to the session on any failure.
122
- if (code !== 0) {
123
- if (code !== EXIT_CODE_RESTART) {
124
- console.error(`\n[jonsoc] unexpected exit (${code}). recovering session...`)
125
- // 1s throttle only on actual crashes to prevent cpu pinning if there's a persistent boot error
126
- spawnSync("node", ["-e", "setTimeout(() => {}, 1000)"], { stdio: "inherit" })
127
- }
128
- args = [...prefix, ...buildRestartArgs()]
129
- continue
130
- }
131
-
132
- process.exit(code)
133
- }
134
- }
135
-
136
- if (safe) {
137
- const safeEnv = {
138
- ...env,
139
- ...(safeIsolated ? { JONSOC_APP_NAME: `${appName}-safe` } : {}),
140
- JONSOC_SAFE_MODE: "1",
141
- }
142
- runWithRestart("npx", ["--yes", "jonsoc@latest"], restartArgs, { env: safeEnv })
143
- }
144
-
145
- const envPath = process.env.JONSOC_BIN_PATH || process.env.JOC_BIN_PATH || process.env.OPENCODE_BIN_PATH
146
- if (envPath) {
147
- runWithRestart(envPath, [], restartArgs, { env })
148
- }
149
-
150
- const scriptPath = realpathSync(__filename)
151
- const scriptDir = dirname(scriptPath)
152
- const pkgDir = dirname(scriptDir)
153
-
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "child_process"
4
+ import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs"
5
+ import { dirname, join } from "path"
6
+ import { platform as osPlatform, arch as osArch, homedir } from "os"
7
+ import { fileURLToPath } from "url"
8
+ import { xdgData, xdgState } from "xdg-basedir"
9
+
10
+ /** Exit code 75 signals a restart request from the TUI */
11
+ const EXIT_CODE_RESTART = 75
12
+
13
+ const __filename = fileURLToPath(import.meta.url)
14
+ const __dirname = dirname(__filename)
15
+ const cwd = process.cwd()
16
+ const env = {
17
+ ...process.env,
18
+ JONSOC_WORKDIR: process.env.JONSOC_WORKDIR ?? process.env.JOC_WORKDIR ?? cwd,
19
+ JONSOC_CLI: "1",
20
+ }
21
+
22
+ function run(target, args, options = {}) {
23
+ const result = spawnSync(target, args || process.argv.slice(2), {
24
+ stdio: "inherit",
25
+ shell: osPlatform() === "win32",
26
+ cwd: options.cwd,
27
+ env: options.env,
28
+ })
29
+ if (result.error) {
30
+ console.error(result.error.message)
31
+ process.exit(1)
32
+ }
33
+ return typeof result.status === "number" ? result.status : 0
34
+ }
35
+
36
+ const rawArgs = process.argv.slice(2)
37
+ const hasFlag = (value) => rawArgs.includes(value)
38
+ const safe = hasFlag("-safe") || hasFlag("--safe")
39
+ const restart = hasFlag("-restart") || hasFlag("--restart") || hasFlag("-return") || hasFlag("--return")
40
+ const autoReturn = hasFlag("-auto-return") || hasFlag("--auto-return")
41
+ const check = hasFlag("-check") || hasFlag("--check")
42
+ const safeIsolated =
43
+ hasFlag("-safe-isolated") ||
44
+ hasFlag("--safe-isolated") ||
45
+ process.env.JONSOC_SAFE_ISOLATE === "1" ||
46
+ process.env.OPENCODE_SAFE_ISOLATE === "1"
47
+ const flagSet = new Set([
48
+ "-safe",
49
+ "--safe",
50
+ "-restart",
51
+ "--restart",
52
+ "-return",
53
+ "--return",
54
+ "-auto-return",
55
+ "--auto-return",
56
+ "-check",
57
+ "--check",
58
+ "-safe-isolated",
59
+ "--safe-isolated",
60
+ ])
61
+ const baseArgs = rawArgs.filter((arg) => !flagSet.has(arg))
62
+ const appName = process.env.JONSOC_APP_NAME ?? process.env.OPENCODE_APP_NAME ?? "jonsoc"
63
+ const stateAppName = safe && safeIsolated ? `${appName}-safe` : appName
64
+
65
+ const stateDir = () => {
66
+ const root = xdgState ?? join(homedir(), ".local", "state")
67
+ return join(root, stateAppName)
68
+ }
69
+
70
+ const lastSession = () => {
71
+ const filePath = join(stateDir(), "kv.json")
72
+ if (!existsSync(filePath)) return
73
+ const raw = readFileSync(filePath, "utf8")
74
+ if (!raw) return
75
+ try {
76
+ const data = JSON.parse(raw)
77
+ const session = data?.session_last
78
+ if (typeof session !== "string") return
79
+ return session
80
+ } catch {
81
+ return
82
+ }
83
+ }
84
+
85
+ const restartArgs = (() => {
86
+ if (!restart) return baseArgs
87
+ if (baseArgs.includes("--session") || baseArgs.includes("-s")) return baseArgs
88
+ const sessionID = lastSession()
89
+ if (!sessionID) {
90
+ console.error("No recent session found to restart.")
91
+ process.exit(1)
92
+ }
93
+ return ["--session", sessionID, ...baseArgs]
94
+ })()
95
+
96
+ if (check) {
97
+ console.log("running")
98
+ process.exit(0)
99
+ }
100
+
101
+ /** Build args for restart - add --session if we have a last session */
102
+ function buildRestartArgs() {
103
+ if (baseArgs.includes("--session") || baseArgs.includes("-s")) return baseArgs
104
+ const sessionID = lastSession()
105
+ if (!sessionID) return baseArgs
106
+ return ["--session", sessionID, ...baseArgs]
107
+ }
108
+
109
+ /** Run the CLI and handle restart exit code */
110
+ function runWithRestart(target, prefix, trailingArgs, options = {}) {
111
+ let args = [...prefix, ...trailingArgs]
112
+ for (;;) {
113
+ const code = run(target, args, options)
114
+
115
+ // Clean exit (user typed /exit, /quit, or Ctrl+C handled cleanly)
116
+ if (code === 0) {
117
+ process.exit(0)
118
+ }
119
+
120
+ // Requested restart (code 75) or Crash/Error (code != 0)
121
+ // We always attempt to return to the session on any failure.
122
+ if (code !== 0) {
123
+ if (code !== EXIT_CODE_RESTART) {
124
+ console.error(`\n[jonsoc] unexpected exit (${code}). recovering session...`)
125
+ // 1s throttle only on actual crashes to prevent cpu pinning if there's a persistent boot error
126
+ spawnSync("node", ["-e", "setTimeout(() => {}, 1000)"], { stdio: "inherit" })
127
+ }
128
+ args = [...prefix, ...buildRestartArgs()]
129
+ continue
130
+ }
131
+
132
+ process.exit(code)
133
+ }
134
+ }
135
+
136
+ if (safe) {
137
+ const safeEnv = {
138
+ ...env,
139
+ ...(safeIsolated ? { JONSOC_APP_NAME: `${appName}-safe` } : {}),
140
+ JONSOC_SAFE_MODE: "1",
141
+ }
142
+ runWithRestart("npx", ["--yes", "jonsoc@latest"], restartArgs, { env: safeEnv })
143
+ }
144
+
145
+ const envPath = process.env.JONSOC_BIN_PATH || process.env.JOC_BIN_PATH || process.env.OPENCODE_BIN_PATH
146
+ if (envPath) {
147
+ runWithRestart(envPath, [], restartArgs, { env })
148
+ }
149
+
150
+ const scriptPath = realpathSync(__filename)
151
+ const scriptDir = dirname(scriptPath)
152
+ const pkgDir = dirname(scriptDir)
153
+
154
154
  // Development mode: run TypeScript source directly with bun when inside repo
155
155
  function repoRoot(dir) {
156
156
  const entry = join(dir, "packages", "jonsoc", "src", "index.ts")
@@ -165,115 +165,115 @@ if (root) {
165
165
  const workdir = join(root, "packages", "jonsoc")
166
166
  runWithRestart("bun", ["run", "--conditions=browser", "src/index.ts"], restartArgs, { cwd: workdir, env })
167
167
  }
168
-
169
-
170
- // Production mode: fetch compiled binary into XDG data dir
171
- const platformMap = {
172
- darwin: "darwin",
173
- linux: "linux",
174
- win32: "windows",
175
- }
176
- const archMap = {
177
- x64: "x64",
178
- arm64: "arm64",
179
- arm: "arm",
180
- }
181
-
182
- let platform = platformMap[osPlatform()]
183
- if (!platform) {
184
- platform = osPlatform()
185
- }
186
- let arch = archMap[osArch()]
187
- if (!arch) {
188
- arch = osArch()
189
- }
190
- const base = "jonsoc-" + platform + "-" + arch
191
- const binary = platform === "windows" ? "jonsoc.exe" : "jonsoc"
192
-
193
- const supported = new Set(["darwin-arm64", "linux-x64", "windows-x64"])
194
- if (!supported.has(`${platform}-${arch}`)) {
195
- console.error(`[jonsoc] Unsupported platform: ${platform}-${arch}. Supported: ${Array.from(supported).join(", ")}`)
196
- process.exit(1)
197
- }
198
-
199
- const pkgJsonPath = join(pkgDir, "package.json")
200
- const version = (() => {
201
- if (!existsSync(pkgJsonPath)) return "latest"
202
- const raw = readFileSync(pkgJsonPath, "utf8")
203
- const data = JSON.parse(raw)
204
- return typeof data.version === "string" ? data.version : "latest"
205
- })()
206
-
207
- const repo = (process.env.JONSOC_REPO ?? process.env.OPENCODE_REPO ?? "Noisemaker111/JonsOpencode").replace(
208
- /^https?:\/\/github\.com\//,
209
- "",
210
- )
211
- const dataRoot = xdgData ?? join(homedir(), ".local", "share")
212
- const dataDir = join(dataRoot, appName)
213
- const binDir = join(dataDir, "bin")
214
- const versionFile = join(binDir, "version")
215
- const binaryPath = join(binDir, binary)
216
-
217
- function ensureDir(dir) {
218
- if (existsSync(dir)) return
219
- mkdirSync(dir, { recursive: true })
220
- }
221
-
222
- function versionMatch() {
223
- if (!existsSync(binaryPath)) return false
224
- if (!existsSync(versionFile)) return false
225
- const stored = readFileSync(versionFile, "utf8").trim()
226
- return stored === version
227
- }
228
-
229
- function releaseUrl() {
230
- const asset = platform === "linux" ? `${base}.tar.gz` : `${base}.zip`
231
- const releasePath = version === "latest" ? "latest/download" : `download/v${version}`
232
- return {
233
- asset,
234
- url: `https://github.com/${repo}/releases/${releasePath}/${asset}`,
235
- }
236
- }
237
-
238
- function extractArchive(archivePath) {
239
- if (platform === "linux") {
240
- const code = run("tar", ["-xzf", archivePath, "-C", binDir], { env })
241
- if (code !== 0) process.exit(code)
242
- return
243
- }
244
-
245
- if (platform === "windows") {
246
- const cmd = `Expand-Archive -Path "${archivePath}" -DestinationPath "${binDir}" -Force`
247
- const code = run("powershell", ["-NoProfile", "-Command", cmd], { env })
248
- if (code !== 0) process.exit(code)
249
- return
250
- }
251
-
252
- const code = run("unzip", ["-o", archivePath, "-d", binDir], { env })
253
- if (code !== 0) process.exit(code)
254
- }
255
-
256
- function ensureBinary() {
257
- if (versionMatch()) return binaryPath
258
- ensureDir(binDir)
259
- const { asset, url } = releaseUrl()
260
- const archivePath = join(dataDir, asset)
261
- const code = run("curl", ["-fL", "-o", archivePath, url], { env })
262
- if (code !== 0) {
263
- console.error(`[jonsoc] Failed to download ${url}`)
264
- process.exit(code)
265
- }
266
- extractArchive(archivePath)
267
- if (platform !== "windows") {
268
- run("chmod", ["+x", binaryPath], { env })
269
- }
270
- if (!existsSync(binaryPath)) {
271
- console.error(`[jonsoc] Expected binary not found at ${binaryPath}`)
272
- process.exit(1)
273
- }
274
- writeFileSync(versionFile, version)
275
- return binaryPath
276
- }
277
-
278
- const resolved = ensureBinary()
279
- runWithRestart(resolved, [], restartArgs, { env })
168
+
169
+
170
+ // Production mode: fetch compiled binary into XDG data dir
171
+ const platformMap = {
172
+ darwin: "darwin",
173
+ linux: "linux",
174
+ win32: "windows",
175
+ }
176
+ const archMap = {
177
+ x64: "x64",
178
+ arm64: "arm64",
179
+ arm: "arm",
180
+ }
181
+
182
+ let platform = platformMap[osPlatform()]
183
+ if (!platform) {
184
+ platform = osPlatform()
185
+ }
186
+ let arch = archMap[osArch()]
187
+ if (!arch) {
188
+ arch = osArch()
189
+ }
190
+ const base = "jonsoc-" + platform + "-" + arch
191
+ const binary = platform === "windows" ? "jonsoc.exe" : "jonsoc"
192
+
193
+ const supported = new Set(["darwin-arm64", "linux-x64", "windows-x64"])
194
+ if (!supported.has(`${platform}-${arch}`)) {
195
+ console.error(`[jonsoc] Unsupported platform: ${platform}-${arch}. Supported: ${Array.from(supported).join(", ")}`)
196
+ process.exit(1)
197
+ }
198
+
199
+ const pkgJsonPath = join(pkgDir, "package.json")
200
+ const version = (() => {
201
+ if (!existsSync(pkgJsonPath)) return "latest"
202
+ const raw = readFileSync(pkgJsonPath, "utf8")
203
+ const data = JSON.parse(raw)
204
+ return typeof data.version === "string" ? data.version : "latest"
205
+ })()
206
+
207
+ const repo = (process.env.JONSOC_REPO ?? process.env.OPENCODE_REPO ?? "Noisemaker111/JonsOpencode").replace(
208
+ /^https?:\/\/github\.com\//,
209
+ "",
210
+ )
211
+ const dataRoot = xdgData ?? join(homedir(), ".local", "share")
212
+ const dataDir = join(dataRoot, appName)
213
+ const binDir = join(dataDir, "bin")
214
+ const versionFile = join(binDir, "version")
215
+ const binaryPath = join(binDir, binary)
216
+
217
+ function ensureDir(dir) {
218
+ if (existsSync(dir)) return
219
+ mkdirSync(dir, { recursive: true })
220
+ }
221
+
222
+ function versionMatch() {
223
+ if (!existsSync(binaryPath)) return false
224
+ if (!existsSync(versionFile)) return false
225
+ const stored = readFileSync(versionFile, "utf8").trim()
226
+ return stored === version
227
+ }
228
+
229
+ function releaseUrl() {
230
+ const asset = platform === "linux" ? `${base}.tar.gz` : `${base}.zip`
231
+ const releasePath = version === "latest" ? "latest/download" : `download/v${version}`
232
+ return {
233
+ asset,
234
+ url: `https://github.com/${repo}/releases/${releasePath}/${asset}`,
235
+ }
236
+ }
237
+
238
+ function extractArchive(archivePath) {
239
+ if (platform === "linux") {
240
+ const code = run("tar", ["-xzf", archivePath, "-C", binDir], { env })
241
+ if (code !== 0) process.exit(code)
242
+ return
243
+ }
244
+
245
+ if (platform === "windows") {
246
+ const cmd = `Expand-Archive -Path "${archivePath}" -DestinationPath "${binDir}" -Force`
247
+ const code = run("powershell", ["-NoProfile", "-Command", cmd], { env })
248
+ if (code !== 0) process.exit(code)
249
+ return
250
+ }
251
+
252
+ const code = run("unzip", ["-o", archivePath, "-d", binDir], { env })
253
+ if (code !== 0) process.exit(code)
254
+ }
255
+
256
+ function ensureBinary() {
257
+ if (versionMatch()) return binaryPath
258
+ ensureDir(binDir)
259
+ const { asset, url } = releaseUrl()
260
+ const archivePath = join(dataDir, asset)
261
+ const code = run("curl", ["-fL", "-o", archivePath, url], { env })
262
+ if (code !== 0) {
263
+ console.error(`[jonsoc] Failed to download ${url}`)
264
+ process.exit(code)
265
+ }
266
+ extractArchive(archivePath)
267
+ if (platform !== "windows") {
268
+ run("chmod", ["+x", binaryPath], { env })
269
+ }
270
+ if (!existsSync(binaryPath)) {
271
+ console.error(`[jonsoc] Expected binary not found at ${binaryPath}`)
272
+ process.exit(1)
273
+ }
274
+ writeFileSync(versionFile, version)
275
+ return binaryPath
276
+ }
277
+
278
+ const resolved = ensureBinary()
279
+ runWithRestart(resolved, [], restartArgs, { env })
package/bunfig.toml CHANGED
@@ -1,7 +1,7 @@
1
- preload = ["@opentui/solid/preload"]
2
-
3
- [test]
4
- preload = ["./test/preload.ts"]
5
- timeout = 10000 # 10 seconds (default is 5000ms)
6
- # Enable code coverage
7
- coverage = true
1
+ preload = ["@opentui/solid/preload"]
2
+
3
+ [test]
4
+ preload = ["./test/preload.ts"]
5
+ timeout = 10000 # 10 seconds (default is 5000ms)
6
+ # Enable code coverage
7
+ coverage = true