jonsoc 1.1.48 → 1.1.49
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/Dockerfile +18 -18
- package/bin/jonsoc +265 -265
- package/bunfig.toml +7 -7
- package/package.json +25 -25
- package/src/agent/generate.txt +75 -75
- package/src/agent/prompt/compaction.txt +12 -12
- package/src/agent/prompt/explore.txt +18 -18
- package/src/agent/prompt/summary.txt +11 -11
- package/src/agent/prompt/title.txt +44 -44
- package/src/command/template/initialize.txt +10 -10
- package/src/command/template/review.txt +99 -99
- package/src/session/prompt/anthropic-20250930.txt +168 -168
- package/src/session/prompt/anthropic.txt +99 -99
- package/src/session/prompt/anthropic_spoof.txt +1 -1
- package/src/session/prompt/beast.txt +149 -149
- package/src/session/prompt/build-switch.txt +5 -5
- package/src/session/prompt/codex_header.txt +81 -81
- package/src/session/prompt/copilot-gpt-5.txt +145 -145
- package/src/session/prompt/gemini.txt +157 -157
- package/src/session/prompt/max-steps.txt +15 -15
- package/src/session/prompt/plan-reminder-anthropic.txt +67 -67
- package/src/session/prompt/plan.txt +26 -26
- package/src/session/prompt/qwen.txt +111 -111
- package/src/tool/apply_patch.txt +33 -33
- package/src/tool/bash.txt +115 -115
- package/src/tool/batch.txt +23 -23
- package/src/tool/codesearch.txt +12 -12
- package/src/tool/edit.txt +10 -10
- package/src/tool/glob.txt +6 -6
- package/src/tool/grep.txt +8 -8
- package/src/tool/ls.txt +1 -1
- package/src/tool/lsp.txt +19 -19
- package/src/tool/multiedit.txt +41 -41
- package/src/tool/plan-enter.txt +14 -14
- package/src/tool/plan-exit.txt +13 -13
- package/src/tool/question.txt +10 -10
- package/src/tool/read.txt +12 -12
- package/src/tool/task.txt +60 -60
- package/src/tool/todoread.txt +14 -14
- package/src/tool/todowrite.txt +167 -167
- package/src/tool/webfetch.txt +13 -13
- package/src/tool/websearch.txt +14 -14
- package/src/tool/write.txt +8 -8
- package/test/fixture/lsp/fake-lsp-server.js +77 -77
- 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
|