@hagicode/hagiscript 0.1.14-dev.89.1.f02e2ca → 0.1.15-dev.100.1.6114a75

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 (58) hide show
  1. package/README.md +248 -155
  2. package/dist/cli.js +4 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/manifest-commands.d.ts +2 -0
  5. package/dist/commands/manifest-commands.js +136 -0
  6. package/dist/commands/manifest-commands.js.map +1 -0
  7. package/dist/commands/npm-sync-commands.js +63 -6
  8. package/dist/commands/npm-sync-commands.js.map +1 -1
  9. package/dist/commands/server-commands.d.ts +2 -0
  10. package/dist/commands/server-commands.js +404 -0
  11. package/dist/commands/server-commands.js.map +1 -0
  12. package/dist/index.d.ts +7 -3
  13. package/dist/index.js +7 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/runtime/manifest-manager.d.ts +57 -0
  16. package/dist/runtime/manifest-manager.js +213 -0
  17. package/dist/runtime/manifest-manager.js.map +1 -0
  18. package/dist/runtime/npm-sync.d.ts +3 -1
  19. package/dist/runtime/npm-sync.js +31 -3
  20. package/dist/runtime/npm-sync.js.map +1 -1
  21. package/dist/runtime/pm2-manager.d.ts +5 -2
  22. package/dist/runtime/pm2-manager.js +181 -49
  23. package/dist/runtime/pm2-manager.js.map +1 -1
  24. package/dist/runtime/runtime-executor.d.ts +6 -0
  25. package/dist/runtime/runtime-executor.js +55 -0
  26. package/dist/runtime/runtime-executor.js.map +1 -1
  27. package/dist/runtime/runtime-manager.d.ts +9 -0
  28. package/dist/runtime/runtime-manager.js +146 -16
  29. package/dist/runtime/runtime-manager.js.map +1 -1
  30. package/dist/runtime/runtime-manifest.d.ts +5 -1
  31. package/dist/runtime/runtime-manifest.js +23 -8
  32. package/dist/runtime/runtime-manifest.js.map +1 -1
  33. package/dist/runtime/runtime-paths.d.ts +11 -1
  34. package/dist/runtime/runtime-paths.js +41 -5
  35. package/dist/runtime/runtime-paths.js.map +1 -1
  36. package/dist/runtime/server-config.d.ts +21 -0
  37. package/dist/runtime/server-config.js +169 -0
  38. package/dist/runtime/server-config.js.map +1 -0
  39. package/dist/runtime/server-manager.d.ts +107 -0
  40. package/dist/runtime/server-manager.js +928 -0
  41. package/dist/runtime/server-manager.js.map +1 -0
  42. package/dist/runtime/server-version-state.d.ts +43 -0
  43. package/dist/runtime/server-version-state.js +156 -0
  44. package/dist/runtime/server-version-state.js.map +1 -0
  45. package/dist/runtime/tool-sync-catalog.config.json +0 -18
  46. package/dist/runtime/tool-sync-catalog.js +1 -1
  47. package/dist/runtime/tool-sync-catalog.js.map +1 -1
  48. package/package.json +23 -2
  49. package/runtime/lib/runtime-script-lib.mjs +128 -69
  50. package/runtime/manifest.yaml +96 -81
  51. package/runtime/scripts/configure-code-server.mjs +14 -3
  52. package/runtime/scripts/configure-omniroute.mjs +15 -5
  53. package/runtime/scripts/install-code-server.mjs +20 -23
  54. package/runtime/scripts/install-omniroute.mjs +19 -22
  55. package/runtime/scripts/install-pm2.mjs +39 -0
  56. package/runtime/scripts/remove-pm2.mjs +25 -0
  57. package/runtime/templates/code-server-config.yaml +2 -2
  58. package/runtime/templates/omniroute-config.yaml +1 -1
@@ -7,6 +7,8 @@ import process from "node:process"
7
7
  import { createGunzip } from "node:zlib"
8
8
  import { pipeline } from "node:stream/promises"
9
9
 
10
+ const PLACEHOLDER_PATTERN = /{{([A-Z0-9_]+)}}/g
11
+
10
12
  export function readRuntimeScriptContext() {
11
13
  return {
12
14
  runtimeRoot: requiredEnv("HAGISCRIPT_RUNTIME_ROOT"),
@@ -24,11 +26,14 @@ export function readRuntimeScriptContext() {
24
26
  componentDataDir: requiredEnv("HAGISCRIPT_RUNTIME_COMPONENT_DATA_DIR"),
25
27
  componentLogsDir: requiredEnv("HAGISCRIPT_RUNTIME_COMPONENT_LOGS_DIR"),
26
28
  componentPm2Home: requiredEnv("HAGISCRIPT_RUNTIME_COMPONENT_PM2_HOME"),
27
- templateDir: requiredEnv("HAGISCRIPT_RUNTIME_TEMPLATE_DIR"),
29
+ runtimeNpmPrefix: requiredEnv("HAGISCRIPT_RUNTIME_NPM_PREFIX"),
30
+ templateDir: process.env.HAGISCRIPT_RUNTIME_TEMPLATE_DIR?.trim() || null,
28
31
  componentVersion: process.env.HAGISCRIPT_RUNTIME_COMPONENT_VERSION?.trim() || null,
32
+ npmRegistryMirror: process.env.HAGISCRIPT_RUNTIME_NPM_REGISTRY_MIRROR?.trim() || null,
33
+ pm2VersionOverride: process.env.HAGISCRIPT_RUNTIME_PM2_VERSION_OVERRIDE?.trim() || null,
29
34
  vendoredRepository: process.env.HAGISCRIPT_RUNTIME_VENDORED_REPOSITORY?.trim() || "HagiCode-org/vendered",
30
35
  vendoredTag:
31
- process.env.HAGISCRIPT_RUNTIME_VENDORED_TAG?.trim() || "v2026.0509.0040",
36
+ process.env.HAGISCRIPT_RUNTIME_VENDORED_TAG?.trim() || "v2026.0516.0063",
32
37
  vendoredBaseUrl: process.env.HAGISCRIPT_RUNTIME_VENDORED_BASE_URL?.trim() || "https://github.com",
33
38
  downloadCacheEnabled: process.env.HAGISCRIPT_DOWNLOAD_CACHE !== "0",
34
39
  downloadCacheDir:
@@ -62,20 +67,42 @@ export async function writeComponentMarker(context, extra = {}) {
62
67
  return markerPath
63
68
  }
64
69
 
65
- export async function materializeTemplate(templateName, destinationPath, variables) {
66
- const templatePath = path.join(readRuntimeScriptContext().templateDir, templateName)
67
- const template = await readFile(templatePath, "utf8")
68
- let rendered = template
69
-
70
- for (const [key, value] of Object.entries(variables)) {
71
- rendered = rendered.replaceAll(`{{${key}}}`, String(value))
70
+ export async function materializeTemplate(templateName, destinationPath, variables, templateDir) {
71
+ const resolvedTemplateDir = templateDir || readRuntimeScriptContext().templateDir
72
+ if (!resolvedTemplateDir) {
73
+ throw new Error(`No template directory configured for ${templateName}`)
72
74
  }
73
75
 
76
+ const templatePath = path.join(resolvedTemplateDir, templateName)
77
+ const template = await readFile(templatePath, "utf8")
78
+ const rendered = renderConfigTemplate(template, variables)
79
+
74
80
  await ensureDirectory(path.dirname(destinationPath))
75
81
  await writeFile(destinationPath, rendered, "utf8")
76
82
  return destinationPath
77
83
  }
78
84
 
85
+ export function renderConfigTemplate(template, values) {
86
+ const rendered = String(template).replace(PLACEHOLDER_PATTERN, (match, key) => {
87
+ if (!Object.hasOwn(values, key)) {
88
+ throw new Error(`Missing template variable ${key}`)
89
+ }
90
+
91
+ return String(values[key])
92
+ })
93
+
94
+ const unresolved = rendered.match(PLACEHOLDER_PATTERN)
95
+ if (unresolved) {
96
+ throw new Error(`Unresolved template variables remain: ${unresolved.join(", ")}`)
97
+ }
98
+
99
+ return rendered.endsWith("\n") ? rendered : `${rendered}\n`
100
+ }
101
+
102
+ export function quoteYamlString(value) {
103
+ return JSON.stringify(String(value))
104
+ }
105
+
79
106
  export async function writeNodeEntrypoint(filePath, message) {
80
107
  await ensureDirectory(path.dirname(filePath))
81
108
  await writeFile(
@@ -87,17 +114,33 @@ export async function writeNodeEntrypoint(filePath, message) {
87
114
  return filePath
88
115
  }
89
116
 
90
- export async function writeCommandWrapper(binDir, commandName, scriptPath) {
117
+ export async function writeCommandWrapper(binDir, commandName, scriptPath, options = {}) {
91
118
  await ensureDirectory(binDir)
119
+ const baseArgs = Array.isArray(options.baseArgs) ? options.baseArgs.map((entry) => String(entry)) : []
120
+ const extension = path.extname(scriptPath).toLowerCase()
92
121
  const nodeWrapperPath = path.join(binDir, process.platform === "win32" ? "node.cmd" : "node")
93
122
 
94
123
  if (process.platform === "win32") {
95
124
  const wrapperPath = path.join(binDir, `${commandName}.cmd`)
96
125
  const relativeTarget = path.relative(path.dirname(wrapperPath), scriptPath).replaceAll("/", "\\")
97
- const relativeNode = path.relative(path.dirname(wrapperPath), nodeWrapperPath).replaceAll("/", "\\")
126
+ const renderedBaseArgs = renderWindowsWrapperArgs(baseArgs)
127
+
128
+ if (isNodeScriptExtension(extension)) {
129
+ const relativeNode = path.relative(path.dirname(wrapperPath), nodeWrapperPath).replaceAll("/", "\\")
130
+ await writeFile(
131
+ wrapperPath,
132
+ `@echo off\r\nset "HAGISCRIPT_NODE=%~dp0\\${relativeNode}"\r\nif exist "%HAGISCRIPT_NODE%" (\r\n "%HAGISCRIPT_NODE%" "%~dp0\\${relativeTarget}"${renderedBaseArgs} %*\r\n) else (\r\n node "%~dp0\\${relativeTarget}"${renderedBaseArgs} %*\r\n)\r\n`,
133
+ "utf8"
134
+ )
135
+ return wrapperPath
136
+ }
137
+
138
+ const invokeTarget = isWindowsBatchExtension(extension)
139
+ ? `call "%~dp0\\${relativeTarget}"`
140
+ : `"%~dp0\\${relativeTarget}"`
98
141
  await writeFile(
99
142
  wrapperPath,
100
- `@echo off\r\nset "HAGISCRIPT_NODE=%~dp0\\${relativeNode}"\r\nif exist "%HAGISCRIPT_NODE%" (\r\n "%HAGISCRIPT_NODE%" "%~dp0\\${relativeTarget}" %*\r\n) else (\r\n node "%~dp0\\${relativeTarget}" %*\r\n)\r\n`,
143
+ `@echo off\r\n${invokeTarget}${renderedBaseArgs} %*\r\nexit /b %ERRORLEVEL%\r\n`,
101
144
  "utf8"
102
145
  )
103
146
  return wrapperPath
@@ -105,18 +148,34 @@ export async function writeCommandWrapper(binDir, commandName, scriptPath) {
105
148
 
106
149
  const wrapperPath = path.join(binDir, commandName)
107
150
  const relativeTarget = path.relative(path.dirname(wrapperPath), scriptPath).replaceAll("\\", "/")
108
- const relativeNode = path.relative(path.dirname(wrapperPath), nodeWrapperPath).replaceAll("\\", "/")
109
- await writeFile(
110
- wrapperPath,
111
- `#!/usr/bin/env sh
151
+ const renderedBaseArgs = renderShellWrapperArgs(baseArgs)
152
+ const targetPathExpression = `"$(dirname "$0")/${relativeTarget}"`
153
+
154
+ if (isNodeScriptExtension(extension)) {
155
+ const relativeNode = path.relative(path.dirname(wrapperPath), nodeWrapperPath).replaceAll("\\", "/")
156
+ await writeFile(
157
+ wrapperPath,
158
+ `#!/usr/bin/env sh
112
159
  node_cmd="$(dirname "$0")/${relativeNode}"
113
160
  if [ -x "$node_cmd" ]; then
114
- exec "$node_cmd" "$(dirname "$0")/${relativeTarget}" "$@"
161
+ exec "$node_cmd" ${targetPathExpression}${renderedBaseArgs} "$@"
115
162
  fi
116
- exec node "$(dirname "$0")/${relativeTarget}" "$@"
163
+ exec node ${targetPathExpression}${renderedBaseArgs} "$@"
117
164
  `,
118
- "utf8"
119
- )
165
+ "utf8"
166
+ )
167
+ } else {
168
+ const launchCommand = shouldInvokeWithShell(extension)
169
+ ? `exec sh ${targetPathExpression}${renderedBaseArgs} "$@"`
170
+ : `exec ${targetPathExpression}${renderedBaseArgs} "$@"`
171
+ await writeFile(
172
+ wrapperPath,
173
+ `#!/usr/bin/env sh
174
+ ${launchCommand}
175
+ `,
176
+ "utf8"
177
+ )
178
+ }
120
179
  await makeExecutable(wrapperPath)
121
180
  return wrapperPath
122
181
  }
@@ -198,48 +257,6 @@ export async function installVendoredPackage(context, options) {
198
257
 
199
258
  export async function writeManagedPackageLauncher(filePath, options) {
200
259
  await ensureDirectory(path.dirname(filePath))
201
- const configLoader =
202
- options.serviceKind === "omniroute"
203
- ? `
204
- const runtimeConfig = await loadOmnirouteConfig()
205
- const runtimeEnv = {
206
- ...(runtimeConfig.dataDir ? { DATA_DIR: runtimeConfig.dataDir } : {}),
207
- ...(runtimeConfig.logDir ? { LOG_DIR: runtimeConfig.logDir } : {}),
208
- ...(runtimeConfig.port ? { PORT: runtimeConfig.port } : {})
209
- }
210
- `
211
- : ""
212
- const configHelpers =
213
- options.serviceKind === "omniroute"
214
- ? `
215
- async function loadOmnirouteConfig() {
216
- try {
217
- const [{ readFile }, { parse }] = await Promise.all([
218
- import("node:fs/promises"),
219
- import("yaml")
220
- ])
221
- const loaded = parse(await readFile(configPath, "utf8"))
222
- const listen = typeof loaded?.listen === "string" ? loaded.listen : ""
223
- const portMatch = listen.match(/:(\\d+)$/u)
224
- return {
225
- dataDir: typeof loaded?.dataDir === "string" ? loaded.dataDir : ${JSON.stringify(
226
- options.defaultEnv?.DATA_DIR ?? ""
227
- )},
228
- logDir: typeof loaded?.logDir === "string" ? loaded.logDir : ${JSON.stringify(
229
- options.defaultEnv?.LOG_DIR ?? ""
230
- )},
231
- port: portMatch?.[1] ?? ${JSON.stringify(options.defaultEnv?.PORT ?? "")}
232
- }
233
- } catch {
234
- return {
235
- dataDir: ${JSON.stringify(options.defaultEnv?.DATA_DIR ?? "")},
236
- logDir: ${JSON.stringify(options.defaultEnv?.LOG_DIR ?? "")},
237
- port: ${JSON.stringify(options.defaultEnv?.PORT ?? "")}
238
- }
239
- }
240
- }
241
- `
242
- : ""
243
260
 
244
261
  await writeFile(
245
262
  filePath,
@@ -247,10 +264,8 @@ async function loadOmnirouteConfig() {
247
264
  import { spawn } from "node:child_process"
248
265
 
249
266
  const entrypointPath = ${JSON.stringify(options.entrypointPath)}
250
- const configPath = ${JSON.stringify(options.configPath)}
251
267
  const baseArgs = ${JSON.stringify(options.baseArgs ?? [])}
252
268
  const baseEnv = ${JSON.stringify(options.defaultEnv ?? {})}
253
- ${configLoader}
254
269
  const child = spawn(
255
270
  process.execPath,
256
271
  [entrypointPath, ...baseArgs, ...process.argv.slice(2)],
@@ -258,8 +273,7 @@ const child = spawn(
258
273
  stdio: "inherit",
259
274
  env: {
260
275
  ...process.env,
261
- ...baseEnv,
262
- ${options.serviceKind === "omniroute" ? "...runtimeEnv" : ""}
276
+ ...baseEnv
263
277
  }
264
278
  }
265
279
  )
@@ -286,7 +300,6 @@ child.on("error", (error) => {
286
300
  process.stderr.write(String(error?.stack ?? error) + "\\n")
287
301
  process.exit(1)
288
302
  })
289
- ${configHelpers}
290
303
  `,
291
304
  "utf8"
292
305
  )
@@ -294,6 +307,34 @@ ${configHelpers}
294
307
  return filePath
295
308
  }
296
309
 
310
+ function isNodeScriptExtension(extension) {
311
+ return extension === ".js" || extension === ".mjs" || extension === ".cjs"
312
+ }
313
+
314
+ function isWindowsBatchExtension(extension) {
315
+ return extension === ".cmd" || extension === ".bat"
316
+ }
317
+
318
+ function shouldInvokeWithShell(extension) {
319
+ return extension === "" || extension === ".sh"
320
+ }
321
+
322
+ function renderShellWrapperArgs(args) {
323
+ if (args.length === 0) {
324
+ return ""
325
+ }
326
+
327
+ return ` ${args.map((entry) => JSON.stringify(entry)).join(" ")}`
328
+ }
329
+
330
+ function renderWindowsWrapperArgs(args) {
331
+ if (args.length === 0) {
332
+ return ""
333
+ }
334
+
335
+ return ` ${args.map((entry) => `"${String(entry).replaceAll('"', '""')}"`).join(" ")}`
336
+ }
337
+
297
338
  function requiredEnv(name) {
298
339
  const value = process.env[name]?.trim()
299
340
 
@@ -312,7 +353,7 @@ async function makeExecutable(filePath) {
312
353
  await chmod(filePath, 0o755)
313
354
  }
314
355
 
315
- function runManagedCommand(command, args, options = {}) {
356
+ export function runManagedCommand(command, args, options = {}) {
316
357
  return new Promise((resolve, reject) => {
317
358
  const child = spawn(command, args, {
318
359
  env: options.env,
@@ -556,7 +597,21 @@ function safeArchiveJoin(root, entryName) {
556
597
  async function replaceDirectory(sourceDirectory, targetDirectory) {
557
598
  await rm(targetDirectory, { recursive: true, force: true })
558
599
  await ensureDirectory(path.dirname(targetDirectory))
559
- await rename(sourceDirectory, targetDirectory)
600
+ try {
601
+ await rename(sourceDirectory, targetDirectory)
602
+ } catch (error) {
603
+ if (!isCrossDeviceRenameError(error)) {
604
+ throw error
605
+ }
606
+
607
+ await cp(sourceDirectory, targetDirectory, {
608
+ recursive: true,
609
+ force: false,
610
+ errorOnExist: true,
611
+ preserveTimestamps: true
612
+ })
613
+ await rm(sourceDirectory, { recursive: true, force: true })
614
+ }
560
615
  }
561
616
 
562
617
  async function restoreVendoredPackageFromCache(cacheRoot, prefixRoot, entrypointRelativePath) {
@@ -645,3 +700,7 @@ function isAlreadyCachedError(error) {
645
700
  (error.code === "EEXIST" || error.code === "ENOTEMPTY")
646
701
  )
647
702
  }
703
+
704
+ function isCrossDeviceRenameError(error) {
705
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === "EXDEV")
706
+ }
@@ -1,11 +1,14 @@
1
1
  runtime:
2
2
  name: "hagicode-runtime"
3
3
  version: "1.0.0"
4
+ hagicodeInstance: "hagicode"
4
5
 
5
6
  paths:
6
7
  runtimeRoot: "~/.hagicode/runtime"
7
8
  runtimeHome: "program"
8
9
  runtimeDataRoot: "runtime-data"
10
+ serverProgramRoot: "server"
11
+ serverDataRoot: "server-data"
9
12
  bin: "bin"
10
13
  config: "config"
11
14
  logs: "logs"
@@ -20,96 +23,108 @@ paths:
20
23
  vendoredRoot: "components/bundled"
21
24
 
22
25
  components:
23
- - name: "node"
24
- type: "runtime"
25
- source: "desktop-bundled-node"
26
- version: "22.22.2"
27
- channelVersion: "22"
28
- installScript: "scripts/install-node.mjs"
29
- verifyScript: "scripts/verify-node.mjs"
26
+ - name: "node"
27
+ type: "runtime"
28
+ source: "desktop-bundled-node"
29
+ version: "22.22.2"
30
+ channelVersion: "22"
31
+ installScript: "scripts/install-node.mjs"
32
+ verifyScript: "scripts/verify-node.mjs"
30
33
 
31
- - name: "dotnet"
32
- type: "runtime"
33
- source: "desktop-embedded-dotnet"
34
- version: "10.0.5"
35
- channelVersion: "10.0"
36
- installScript: "scripts/install-dotnet.mjs"
37
- verifyScript: "scripts/verify-dotnet.mjs"
38
- removeScript: "scripts/remove-dotnet.mjs"
34
+ - name: "dotnet"
35
+ type: "runtime"
36
+ source: "desktop-embedded-dotnet"
37
+ version: "10.0.5"
38
+ channelVersion: "10.0"
39
+ installScript: "scripts/install-dotnet.mjs"
40
+ verifyScript: "scripts/verify-dotnet.mjs"
41
+ removeScript: "scripts/remove-dotnet.mjs"
39
42
 
40
- - name: "omniroute"
41
- type: "bundled-runtime"
42
- source: "desktop-vendored-runtime"
43
- version: "3.6.9"
44
- runtimeDataDir: "services/omniroute"
45
- lifecycleDependencies:
46
- - "node"
47
- installScript: "scripts/install-omniroute.mjs"
48
- configureScript: "scripts/configure-omniroute.mjs"
49
- pm2:
50
- appName: "hagicode-omniroute"
51
- nameIdentifierEnv: "hagicode_pm2_name"
52
- cwd: "."
53
- script: "current/omniroute-launcher.mjs"
43
+ - name: "omniroute"
44
+ type: "bundled-runtime"
45
+ source: "desktop-vendored-runtime"
46
+ version: "3.6.9"
47
+ runtimeDataDir: "services/omniroute"
48
+ lifecycleDependencies:
49
+ - "node"
50
+ installScript: "scripts/install-omniroute.mjs"
51
+ configureScript: "scripts/configure-omniroute.mjs"
52
+ pm2:
53
+ appName: "hagicode-omniroute"
54
+ cwd: "current"
54
55
 
55
- - name: "code-server"
56
- type: "bundled-runtime"
57
- source: "desktop-vendored-runtime"
58
- version: "4.117.0"
59
- runtimeDataDir: "services/code-server"
60
- lifecycleDependencies:
61
- - "node"
62
- installScript: "scripts/install-code-server.mjs"
63
- configureScript: "scripts/configure-code-server.mjs"
64
- pm2:
65
- appName: "hagicode-code-server"
66
- nameIdentifierEnv: "hagicode_pm2_name"
67
- cwd: "."
68
- script: "current/code-server-launcher.mjs"
56
+ - name: "code-server"
57
+ type: "bundled-runtime"
58
+ source: "desktop-vendored-runtime"
59
+ version: "4.117.0"
60
+ runtimeDataDir: "services/code-server"
61
+ lifecycleDependencies:
62
+ - "node"
63
+ installScript: "scripts/install-code-server.mjs"
64
+ configureScript: "scripts/configure-code-server.mjs"
65
+ pm2:
66
+ appName: "hagicode-code-server"
67
+ cwd: "current"
69
68
 
70
- - name: "server"
71
- type: "released-service"
72
- source: "hagicode-release-package"
73
- runtimeDataDir: "services/server"
74
- lifecycleDependencies:
75
- - "node"
76
- - "dotnet"
77
- installScript: "scripts/install-server.mjs"
78
- configureScript: "scripts/configure-server.mjs"
79
- removeScript: "scripts/remove-server.mjs"
80
- pm2:
81
- appName: "hagicode-server"
82
- nameIdentifierEnv: "hagicode_pm2_name"
83
- pm2Home: ".pm2"
84
- env:
85
- ASPNETCORE_ENVIRONMENT: "Production"
86
- ASPNETCORE_URLS: "http://127.0.0.1:39150"
87
- releasedService:
88
- dllPath: "current/lib/PCode.Web.dll"
89
- workingDirectory: "current/lib"
90
- configRoot: "current/lib"
91
- runtimeFilesDir: "pm2-runtime"
92
- startScript: "current/start.sh"
69
+ - name: "server"
70
+ type: "released-service"
71
+ source: "hagicode-release-package"
72
+ runtimeDataDir: "services/server"
73
+ lifecycleDependencies:
74
+ - "node"
75
+ - "dotnet"
76
+ installScript: "scripts/install-server.mjs"
77
+ configureScript: "scripts/configure-server.mjs"
78
+ removeScript: "scripts/remove-server.mjs"
79
+ pm2:
80
+ appName: "hagicode-server"
81
+ env:
82
+ ASPNETCORE_ENVIRONMENT: "Production"
83
+ ASPNETCORE_URLS: "http://127.0.0.1:39150"
84
+ releasedService:
85
+ dllPath: "lib/PCode.Web.dll"
86
+ workingDirectory: "lib"
87
+ configRoot: "lib"
88
+ runtimeFilesDir: "pm2-runtime"
89
+ startScript: "start.sh"
93
90
 
94
91
  phases:
95
92
  install:
96
93
  order:
97
- - "node"
98
- - "dotnet"
99
- - "server"
100
- - "omniroute"
101
- - "code-server"
94
+ - "node"
95
+ - "dotnet"
96
+ - "server"
97
+ - "omniroute"
98
+ - "code-server"
102
99
  remove:
103
100
  order:
104
- - "server"
105
- - "code-server"
106
- - "omniroute"
107
- - "dotnet"
108
- - "node"
101
+ - "server"
102
+ - "code-server"
103
+ - "omniroute"
104
+ - "dotnet"
105
+ - "node"
109
106
  update:
110
107
  order:
111
- - "node"
112
- - "dotnet"
113
- - "server"
114
- - "omniroute"
115
- - "code-server"
108
+ - "node"
109
+ - "dotnet"
110
+ - "server"
111
+ - "omniroute"
112
+ - "code-server"
113
+
114
+ npmSync:
115
+ packages:
116
+ "pm2":
117
+ version: "7.0.1"
118
+ target: "7.0.1"
119
+ "@anthropic-ai/claude-code":
120
+ version: "2.1.119"
121
+ target: "2.1.119"
122
+ "@fission-ai/openspec":
123
+ version: "1.3.1"
124
+ target: "1.3.1"
125
+ "@openai/codex":
126
+ version: "0.125.0"
127
+ target: "0.125.0"
128
+ "skills":
129
+ version: "1.5.1"
130
+ target: "1.5.1"
@@ -3,12 +3,23 @@ import path from "node:path"
3
3
  import process from "node:process"
4
4
  import {
5
5
  materializeTemplate,
6
+ quoteYamlString,
6
7
  readRuntimeScriptContext
7
8
  } from "../lib/runtime-script-lib.mjs"
8
9
 
9
10
  const context = readRuntimeScriptContext()
11
+ const currentRoot = path.join(context.componentRoot, "current")
10
12
  const configPath = path.join(context.componentConfigDir, "config.yaml")
11
- await materializeTemplate("code-server-config.yaml", configPath, {
12
- DATA_DIR: context.runtimeDataHome
13
- })
13
+ const bindPort = process.env.CODE_SERVER_BIND_PORT ?? "8080"
14
+ const bindHost = process.env.CODE_SERVER_BIND_HOST ?? "127.0.0.1"
15
+ await materializeTemplate(
16
+ "code-server-config.yaml",
17
+ configPath,
18
+ {
19
+ BIND_ADDR: quoteYamlString(`${bindHost}:${bindPort}`),
20
+ DATA_DIR: quoteYamlString(context.runtimeDataHome),
21
+ EXTENSIONS_DIR: quoteYamlString(path.join(context.runtimeDataHome, "extensions"))
22
+ },
23
+ path.join(currentRoot, "templates")
24
+ )
14
25
  process.stdout.write(`Configured code-server template at ${configPath}\n`)
@@ -3,14 +3,24 @@ import path from "node:path"
3
3
  import process from "node:process"
4
4
  import {
5
5
  materializeTemplate,
6
+ quoteYamlString,
6
7
  readRuntimeScriptContext
7
8
  } from "../lib/runtime-script-lib.mjs"
8
9
 
9
10
  const context = readRuntimeScriptContext()
11
+ const currentRoot = path.join(context.componentRoot, "current")
10
12
  const configPath = path.join(context.componentConfigDir, "config.yaml")
11
- await materializeTemplate("omniroute-config.yaml", configPath, {
12
- RUNTIME_ROOT: context.runtimeHome,
13
- DATA_DIR: context.runtimeDataHome,
14
- LOGS_DIR: context.componentLogsDir
15
- })
13
+ const listenPort = process.env.OMNIROUTE_LISTEN_PORT ?? "39001"
14
+ const listenHost = process.env.OMNIROUTE_LISTEN_HOST ?? "127.0.0.1"
15
+ await materializeTemplate(
16
+ "omniroute-config.yaml",
17
+ configPath,
18
+ {
19
+ RUNTIME_ROOT: quoteYamlString(context.runtimeHome),
20
+ LISTEN_ADDR: quoteYamlString(`${listenHost}:${listenPort}`),
21
+ DATA_DIR: quoteYamlString(context.runtimeDataHome),
22
+ LOGS_DIR: quoteYamlString(context.componentLogsDir)
23
+ },
24
+ path.join(currentRoot, "templates")
25
+ )
16
26
  process.stdout.write(`Configured omniroute template at ${configPath}\n`)
@@ -1,52 +1,49 @@
1
1
  #!/usr/bin/env node
2
2
  import path from "node:path"
3
3
  import process from "node:process"
4
- import { writeFile } from "node:fs/promises"
5
4
  import {
6
5
  ensureDirectory,
7
6
  installVendoredPackage,
8
7
  materializeTemplate,
8
+ quoteYamlString,
9
9
  readRuntimeScriptContext,
10
10
  writeCommandWrapper,
11
- writeComponentMarker,
12
- writeManagedPackageLauncher
11
+ writeComponentMarker
13
12
  } from "../lib/runtime-script-lib.mjs"
14
13
 
15
14
  const context = readRuntimeScriptContext()
16
15
  const currentRoot = path.join(context.componentRoot, "current")
17
- const launcherPath = path.join(currentRoot, "code-server-launcher.mjs")
18
16
  const configPath = path.join(context.componentConfigDir, "config.yaml")
19
- const entrypointPackageJsonPath = path.join(currentRoot, "out", "node", "package.json")
17
+ const extensionsPath = path.join(context.runtimeDataHome, "extensions")
18
+ const wrapperPath = path.join(
19
+ currentRoot,
20
+ "bin",
21
+ process.platform === "win32" ? "code-server.cmd" : "code-server"
22
+ )
20
23
 
21
24
  await ensureDirectory(currentRoot)
22
- await materializeTemplate("code-server-config.yaml", configPath, {
23
- DATA_DIR: context.runtimeDataHome
24
- })
25
25
  const installedPackage = await installVendoredPackage(context, {
26
26
  prefixRoot: currentRoot,
27
27
  packageName: "code-server",
28
28
  entrypointRelativePath: path.join("out", "node", "entry.js")
29
29
  })
30
- await writeFile(
31
- entrypointPackageJsonPath,
32
- `${JSON.stringify({ type: "commonjs" }, null, 2)}\n`,
33
- "utf8"
34
- )
35
- await writeManagedPackageLauncher(
36
- launcherPath,
30
+ await materializeTemplate(
31
+ "code-server-config.yaml",
32
+ configPath,
37
33
  {
38
- entrypointPath: installedPackage.entrypointPath,
39
- configPath,
40
- baseArgs: ["--config", configPath],
41
- serviceKind: "code-server"
42
- }
34
+ BIND_ADDR: quoteYamlString("127.0.0.1:8080"),
35
+ DATA_DIR: quoteYamlString(context.runtimeDataHome),
36
+ EXTENSIONS_DIR: quoteYamlString(extensionsPath)
37
+ },
38
+ path.join(currentRoot, "templates")
43
39
  )
44
- await writeCommandWrapper(context.binDir, "code-server", launcherPath)
40
+ await writeCommandWrapper(context.binDir, "code-server", wrapperPath, {
41
+ baseArgs: ["--config", configPath]
42
+ })
45
43
  await writeComponentMarker(context, {
46
44
  configPath,
47
- launcherPath,
45
+ wrapperPath,
48
46
  entrypointPath: installedPackage.entrypointPath,
49
- entrypointPackageJsonPath,
50
47
  vendoredReleaseRepository: installedPackage.releaseRepository,
51
48
  vendoredReleaseTag: installedPackage.releaseTag,
52
49
  vendoredReleaseName: installedPackage.releaseName,