@hagicode/hagiscript 0.1.6 → 0.1.8

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 (50) hide show
  1. package/README.md +144 -201
  2. package/bin/runtime +16 -0
  3. package/dist/cli.js +4 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/pm2-commands.d.ts +2 -0
  6. package/dist/commands/pm2-commands.js +54 -0
  7. package/dist/commands/pm2-commands.js.map +1 -0
  8. package/dist/commands/runtime-commands.d.ts +2 -0
  9. package/dist/commands/runtime-commands.js +136 -0
  10. package/dist/commands/runtime-commands.js.map +1 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.js +6 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/runtime/command-launch.js +1 -0
  15. package/dist/runtime/command-launch.js.map +1 -1
  16. package/dist/runtime/pm2-manager.d.ts +54 -0
  17. package/dist/runtime/pm2-manager.js +258 -0
  18. package/dist/runtime/pm2-manager.js.map +1 -0
  19. package/dist/runtime/runtime-executor.d.ts +45 -0
  20. package/dist/runtime/runtime-executor.js +153 -0
  21. package/dist/runtime/runtime-executor.js.map +1 -0
  22. package/dist/runtime/runtime-manager.d.ts +79 -0
  23. package/dist/runtime/runtime-manager.js +651 -0
  24. package/dist/runtime/runtime-manager.js.map +1 -0
  25. package/dist/runtime/runtime-manifest.d.ts +77 -0
  26. package/dist/runtime/runtime-manifest.js +277 -0
  27. package/dist/runtime/runtime-manifest.js.map +1 -0
  28. package/dist/runtime/runtime-paths.d.ts +31 -0
  29. package/dist/runtime/runtime-paths.js +77 -0
  30. package/dist/runtime/runtime-paths.js.map +1 -0
  31. package/dist/runtime/runtime-state.d.ts +45 -0
  32. package/dist/runtime/runtime-state.js +82 -0
  33. package/dist/runtime/runtime-state.js.map +1 -0
  34. package/package.json +9 -5
  35. package/runtime/lib/runtime-script-lib.mjs +531 -0
  36. package/runtime/manifest.yaml +136 -0
  37. package/runtime/scripts/configure-code-server.mjs +14 -0
  38. package/runtime/scripts/configure-omniroute.mjs +16 -0
  39. package/runtime/scripts/install-code-server.mjs +53 -0
  40. package/runtime/scripts/install-dotnet.mjs +24 -0
  41. package/runtime/scripts/install-node.mjs +4 -0
  42. package/runtime/scripts/install-npm-packages.mjs +4 -0
  43. package/runtime/scripts/install-omniroute.mjs +60 -0
  44. package/runtime/scripts/remove-npm-packages.mjs +4 -0
  45. package/runtime/scripts/update-npm-packages.mjs +4 -0
  46. package/runtime/scripts/verify-dotnet.mjs +10 -0
  47. package/runtime/scripts/verify-node.mjs +4 -0
  48. package/runtime/templates/code-server-config.yaml +5 -0
  49. package/runtime/templates/omniroute-config.yaml +4 -0
  50. package/README_cn.md +0 -266
package/README.md CHANGED
@@ -1,288 +1,231 @@
1
- # Hagiscript
1
+ # Hagiscript Runtime Guide
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/%40hagicode%2Fhagiscript?logo=npm&color=cb3837)](https://www.npmjs.com/package/@hagicode/hagiscript)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/%40hagicode%2Fhagiscript?logo=npm&color=2d8cf0)](https://www.npmjs.com/package/@hagicode/hagiscript)
5
5
  [![license](https://img.shields.io/badge/license-MIT-ffd43b)](./LICENSE)
6
6
 
7
- `@hagicode/hagiscript` is the scoped npm package foundation for future Hagiscript language tooling. This initial package intentionally keeps runtime behavior small: it exposes version metadata, a baseline runtime-info API, and an executable CLI placeholder that can be built, tested, packed, and published safely.
7
+ `@hagicode/hagiscript` is the runtime management CLI behind the `hagicode-runtime` contract. Use it to install, inspect, update, remove, and operate a managed HagiCode runtime without depending on system Node.js, system PM2, or host-global npm packages.
8
8
 
9
- ## Installation Assumptions
9
+ ## Install
10
10
 
11
- - Node.js 20 or newer is required.
12
- - npm is the package manager for this standalone repository.
13
- - The npm package name is `@hagicode/hagiscript`.
14
- - GitHub Actions publishing uses `npm publish --provenance`. Local manual publishing should use plain `npm publish` unless you are inside a supported trusted publishing environment.
11
+ ```bash
12
+ npm install -g @hagicode/hagiscript
13
+ ```
15
14
 
16
- ## Usage
15
+ Primary entrypoints:
17
16
 
18
- Install the package from npm:
17
+ - `hagiscript`
18
+ - `hagicode-runtime` (`hagiscript runtime ...` wrapper)
19
19
 
20
- ```bash
21
- npm install @hagicode/hagiscript
22
- ```
20
+ Node.js 20 or newer is required to run the package itself.
23
21
 
24
- The installed CLI command remains `hagiscript`.
22
+ ## Runtime Model
25
23
 
26
- Run the CLI locally during development:
24
+ By default, Hagiscript loads `runtime/manifest.yaml` and manages the runtime under `~/.hagicode/runtime`.
27
25
 
28
- ```bash
29
- npm run dev -- --help
30
- npm run dev -- info
31
- npm run dev -- install-node --target .tmp/node-runtime
32
- npm run dev -- check-node --target .tmp/node-runtime
33
- npm run dev -- npm-sync --runtime .tmp/node-runtime --manifest manifest.json
26
+ ```text
27
+ <runtime-root>/
28
+ program/
29
+ bin/
30
+ npm/
31
+ components/
32
+ runtime-data/
33
+ config/
34
+ logs/
35
+ data/
36
+ components/
37
+ state.json
34
38
  ```
35
39
 
36
- After building, run the compiled CLI:
40
+ The split is intentional:
37
41
 
38
- ```bash
39
- npm run build
40
- node dist/cli.js --version
41
- node dist/cli.js info
42
- node dist/cli.js install-node --target .tmp/node-runtime
43
- node dist/cli.js check-node --target .tmp/node-runtime
44
- node dist/cli.js npm-sync --runtime .tmp/node-runtime --manifest manifest.json
45
- ```
42
+ - `program/` holds managed executables, vendored payloads, wrappers, and the managed npm prefix.
43
+ - `runtime-data/` holds mutable config, logs, state, PM2 data, and component-specific writable files.
44
+
45
+ The packaged manifest currently manages:
46
46
 
47
- ### Managed Node.js Runtime Commands
47
+ - `node` - managed Node.js runtime
48
+ - `dotnet` - managed .NET runtime
49
+ - `npm-packages` - managed npm prefix, including `pm2`
50
+ - `omniroute` - vendored bundled runtime
51
+ - `code-server` - vendored bundled runtime
48
52
 
49
- `install-node` downloads an official Node.js archive from `https://nodejs.org/dist`, extracts it into the target directory, and verifies both `node` and `npm` before reporting success.
53
+ ## Core Runtime Commands
54
+
55
+ Install the full runtime:
50
56
 
51
57
  ```bash
52
- hagiscript install-node --target /opt/hagiscript/node
53
- hagiscript install-node --target /opt/hagiscript/node20 --version 20
54
- hagiscript install-node --target /opt/hagiscript/lts --version lts
58
+ hagiscript runtime install
55
59
  ```
56
60
 
57
- When `--version` is omitted, Hagiscript installs the latest available Node.js 22 release. Supported selectors are `lts`, `latest`, `current`, a major version such as `22`, an exact version such as `22.12.0`, or an exact version with a `v` prefix such as `v22.12.0`.
61
+ Install selected components only:
58
62
 
59
- The target path must be missing or empty. Hagiscript refuses to install into a non-empty target directory and does not delete existing user files. During installation, temporary staging files are created beside the target directory and cleaned up after success or failure.
63
+ ```bash
64
+ hagiscript runtime install --components node,npm-packages
65
+ ```
60
66
 
61
- Example success output:
67
+ Preview planned changes without mutating files:
62
68
 
63
- ```text
64
- Installing Node.js 22 into /opt/hagiscript/node
65
- Download progress: 100%
66
- Node.js runtime installed successfully.
67
- Target: /opt/hagiscript/node
68
- Node.js: v22.12.0
69
- npm: 10.9.0
70
- node: /opt/hagiscript/node/bin/node
71
- npm: /opt/hagiscript/node/bin/npm
69
+ ```bash
70
+ hagiscript runtime install --dry-run
71
+ hagiscript runtime update --check-only
72
72
  ```
73
73
 
74
- `check-node` validates an existing runtime directory and exits with code `0` only when both `node --version` and `npm --version` succeed.
74
+ Inspect the canonical runtime state:
75
75
 
76
76
  ```bash
77
- hagiscript check-node --target /opt/hagiscript/node
77
+ hagiscript runtime state
78
+ hagiscript runtime state --json
78
79
  ```
79
80
 
80
- Example valid output:
81
+ Update or remove managed components:
81
82
 
82
- ```text
83
- Node.js runtime is valid.
84
- Target: /opt/hagiscript/node
85
- Node.js: v22.12.0
86
- npm: 10.9.0
87
- node: /opt/hagiscript/node/bin/node
88
- npm: /opt/hagiscript/node/bin/npm
83
+ ```bash
84
+ hagiscript runtime update
85
+ hagiscript runtime remove --components code-server --purge
89
86
  ```
90
87
 
91
- Example invalid output exits non-zero and includes the failure reason:
88
+ Override the runtime root or manifest when needed:
92
89
 
93
- ```text
94
- Node.js runtime is invalid.
95
- Target: /opt/hagiscript/node
96
- Reason: missing executable
90
+ ```bash
91
+ hagiscript runtime install --runtime-root /srv/hagicode/runtime
92
+ hagiscript runtime state --from-manifest /path/to/runtime-manifest.yaml --json
97
93
  ```
98
94
 
99
- ### npm Global Package Synchronization
100
-
101
- `npm-sync` aligns npm global packages inside a HagiScript-managed Node.js runtime with a JSON manifest. By default, it verifies or installs the managed runtime at `~/.hagiscript/node-runtime` and uses that runtime's `npm`; it does not use or mutate npm from the ambient shell `PATH`. Existing automation can keep passing `--runtime` to use an explicit runtime directory.
95
+ If you prefer the runtime-oriented wrapper:
102
96
 
103
97
  ```bash
104
- hagiscript npm-sync --manifest ./manifest.json
105
- hagiscript npm-sync --runtime /opt/hagiscript/node --manifest ./manifest.json
106
- hagiscript npm-sync --manifest ./manifest.json --force
107
- hagiscript npm-sync --manifest ./manifest.json --registry-mirror https://registry.npmmirror.com/
108
- hagiscript npm-sync --manifest ./manifest.json --registry-mirror https://registry.npmmirror.com/ --mirror-only
98
+ hagicode-runtime install --runtime-root /srv/hagicode/runtime
109
99
  ```
110
100
 
111
- Compatibility manifest schema:
112
-
113
- ```json
114
- {
115
- "registryMirror": "https://registry.npmmirror.com/",
116
- "packages": {
117
- "<npm-package-name>": {
118
- "version": "<semver range>",
119
- "target": "<optional npm install selector>"
120
- }
121
- }
122
- }
123
- ```
101
+ ## Runtime State and Maintenance
124
102
 
125
- The required `version` field accepts package.json-style semver ranges such as `^1.2.0`, `>=1.0.0 <2.0.0`, or `1.0.0 || 2.0.0`. The optional `target` field controls the selector used for `npm install -g`; when omitted, Hagiscript installs `<package>@<version>`.
103
+ `hagiscript runtime state --json` is the canonical inspection surface for automation. It reports:
126
104
 
127
- By default, `npm-sync` plans installed packages that already satisfy the requested range as `noop` and skips `npm install -g` for them. Use `--force` to skip that installed-package satisfaction check and re-run sync for matching packages. `--force` does not upgrade packages to the latest version and does not change semver selection; it only turns an otherwise skipped `noop` action into an executable `sync` action.
105
+ - resolved runtime root
106
+ - `program/` and `runtime-data/` locations
107
+ - per-component install status
108
+ - per-component runtime data homes
109
+ - derived PM2 homes for managed services
110
+ - program/data path separation
128
111
 
129
- The optional top-level `registryMirror` field configures the npm registry used for both inventory and install commands. It must be a non-empty absolute `http:` or `https:` URL. When present, HagiScript first appends `--registry <registryMirror>` to `npm list -g --depth=0 --json` and `npm install -g <package>@<selector>` without changing package selection. If that mirror-backed npm command fails, HagiScript automatically retries the same inventory or install command once against the official npm registry `https://registry.npmjs.org/`. This mirror-first retry scope is intentionally limited to npm inventory and package mutation commands; runtime validation, manifest validation, and package planning do not retry. This is useful for public mirrors such as `https://registry.npmmirror.com/` or enterprise registries such as `https://npm.company.example/repository/npm/`.
112
+ Use it before and after maintenance work to confirm the expected component set and writable paths.
130
113
 
131
- Product-managed tool sync can use the expanded `tools` manifest shape. Mandatory tools are always included using internally pinned versions from `src/runtime/tool-sync-catalog.config.json`: OpenSpec skills (`skills@1.5.1`), OmniRoute (`omniroute@3.6.9`), and code-server (`code-server@4.117.0`). Optional agent CLI sync is enabled explicitly; selected built-in CLIs or custom npm packages are added when provided.
114
+ Typical maintenance flow:
132
115
 
133
- ```json
134
- {
135
- "registryMirror": "https://npm.company.example/repository/npm/",
136
- "tools": {
137
- "optionalAgentCliSyncEnabled": true,
138
- "selectedOptionalAgentCliIds": ["codex", "claude-code", "fission-openspec", "opencode"],
139
- "customAgentClis": [
140
- {
141
- "packageName": "@scope/agent-cli",
142
- "version": "^1.0.0"
143
- }
144
- ]
145
- }
146
- }
147
- ```
116
+ 1. Check current state: `hagiscript runtime state --json`
117
+ 2. Apply changes: `hagiscript runtime install`, `update`, or `remove`
118
+ 3. Re-check state to confirm the final layout
119
+ 4. Operate services through `hagiscript pm2 ...`
120
+
121
+ Lifecycle commands print the resolved manifest, managed root, changed component count, skipped entries, and log file path when a log is generated.
122
+
123
+ ## Managed PM2 Services
124
+
125
+ Hagiscript manages runtime-scoped PM2 services for:
148
126
 
149
- The first built-in optional agent CLI IDs are `codex` (`@openai/codex@0.125.0`), `claude-code` (`@anthropic-ai/claude-code@2.1.119`), `fission-openspec` (`@fission-ai/openspec@1.3.1`), `qoder` (`@qoder-ai/qodercli@0.1.48`), and `opencode` (`opencode-ai@1.14.24`). These built-in package versions are pinned in `src/runtime/tool-sync-catalog.config.json`. HagiScript validates unknown tool IDs, npm package names, and version selectors before `npm list` or `npm install` runs.
127
+ - `omniroute`
128
+ - `code-server`
150
129
 
151
- Use `--registry-mirror <url>` when automation needs to override the manifest registry for a single run. Precedence is CLI override first, manifest `registryMirror` second, and npm's default registry behavior third. If neither the CLI nor manifest provides a mirror, HagiScript does not add `--registry` and existing npm defaults, `.npmrc`, or environment configuration continue to apply.
130
+ Supported actions:
152
131
 
153
- Use `--mirror-only` when a run must stay on the configured mirror and must not retry against `https://registry.npmjs.org/`. When omitted, automatic official-registry fallback remains enabled by default for mirror-backed npm inventory and install commands.
132
+ - `start`
133
+ - `stop`
134
+ - `status`
154
135
 
155
- For simple product-managed requests, optional CLI selections can be provided directly without writing a manifest:
136
+ Examples:
156
137
 
157
138
  ```bash
158
- hagiscript npm-sync --selected-agent-cli codex
159
- hagiscript npm-sync --selected-agent-cli codex --custom-agent-cli @scope/agent-cli@^1.0.0
139
+ hagiscript pm2 omniroute status
140
+ hagiscript pm2 omniroute start
141
+ hagiscript pm2 code-server stop
160
142
  ```
161
143
 
162
- Example manifest for openspec and skills tooling:
163
-
164
- ```json
165
- {
166
- "packages": {
167
- "@openspec/cli": {
168
- "version": "^1.0.0"
169
- },
170
- "@hagicode/skills": {
171
- "version": ">=0.5.0 <1.0.0",
172
- "target": "0.5.4"
173
- }
174
- }
175
- }
176
- ```
144
+ The PM2 flow is runtime-scoped:
177
145
 
178
- During execution, Hagiscript validates the manifest and runtime before any npm install command runs, lists global packages with `/opt/hagiscript/node/bin/npm list -g --depth=0 --json`, plans no-op, install, upgrade, downgrade, or sync actions, and then runs `npm install -g <package>@<selector>` only for packages that need changes. With `--force`, packages that already satisfy the requested range are replanned from `noop` to `sync`, so the same selector is installed again to re-sync the existing target.
146
+ - PM2 is installed into the managed npm prefix, not the host environment.
147
+ - Hagiscript resolves the runtime manifest before every PM2 action.
148
+ - PM2 runs with the managed Node runtime and managed PATH ordering.
149
+ - `PM2_HOME` is derived from the managed runtime layout, so service state stays inside the runtime data boundary.
179
150
 
180
- Example output:
151
+ This means maintenance scripts should call `hagiscript pm2 ...` instead of a system `pm2` binary.
181
152
 
182
- ```text
183
- Manifest validated: ./manifest.json (2 packages, mode=packages)
184
- Registry mirror: https://registry.npmmirror.com/
185
- Fallback policy: auto
186
- Runtime validated: /opt/hagiscript/node
187
- node: /opt/hagiscript/node/bin/node (v22.12.0)
188
- npm: /opt/hagiscript/node/bin/npm (10.9.0)
189
- Detected global packages: 4
190
- Plan: @openspec/cli noop installed=1.0.2 required=^1.0.0 selector=@openspec/cli@^1.0.0
191
- Skip: @openspec/cli already satisfies range
192
- Plan: @hagicode/skills upgrade installed=0.4.0 required=>=0.5.0 <1.0.0 selector=@hagicode/skills@0.5.4
193
- Install: @hagicode/skills using @hagicode/skills@0.5.4
194
- Synced: @hagicode/skills (upgrade)
195
- npm-sync complete.
196
- Runtime: /opt/hagiscript/node
197
- Manifest: ./manifest.json
198
- Mode: packages
199
- Registry mirror: https://registry.npmmirror.com/
200
- Fallback policy: auto
201
- Fallback used: no
202
- Packages: 2
203
- No-op: 1
204
- Changed: 1
205
- ```
153
+ ## Runtime Environment Contract
206
154
 
207
- Forced re-sync example:
155
+ Runtime lifecycle scripts and managed services receive a stable environment contract:
208
156
 
209
- ```text
210
- $ hagiscript npm-sync --manifest ./manifest.json --force
211
- Plan: @openspec/cli sync installed=1.0.2 required=^1.0.0 selector=@openspec/cli@^1.0.0
212
- Install: @openspec/cli using @openspec/cli@^1.0.0
213
- Synced: @openspec/cli (sync)
214
- ```
157
+ - `HAGICODE_RUNTIME_HOME` - runtime program home
158
+ - `HAGICODE_RUNTIME_DATA_HOME` - writable runtime data home for the current component
159
+ - `PM2_HOME` - PM2 state directory for the current managed service
160
+ - `PATH` - rebuilt so managed Node, managed npm, and managed wrappers come first
215
161
 
216
- When fallback is triggered, HagiScript logs `Fallback used: ...` during execution and records `Fallback detail: ...` in the final summary so CI or desktop automation can see which mirror failed, which official registry retry was used, and whether that retry succeeded.
162
+ This contract is what keeps installs, updates, wrappers, and PM2-managed services aligned to the same runtime root.
217
163
 
218
- Use the library API from ESM consumers:
164
+ ## Manifest Customization
219
165
 
220
- ```ts
221
- import { createRuntimeInfo, getPackageMetadata } from "@hagicode/hagiscript";
166
+ `runtime/manifest.yaml` controls the runtime shape. Common override points:
222
167
 
223
- console.log(getPackageMetadata());
224
- console.log(createRuntimeInfo());
225
- ```
168
+ - `paths.runtimeRoot`
169
+ - `paths.runtimeHome`
170
+ - `paths.runtimeDataRoot`
171
+ - `paths.componentDataRoot`
172
+ - `paths.defaultPm2Home`
173
+ - component `runtimeDataDir`
174
+ - service `pm2.appName`
175
+ - service `pm2.cwd`
176
+ - service `pm2.script`
177
+ - service `pm2.args`
178
+ - service `pm2.env`
179
+ - service `pm2.pm2Home`
226
180
 
227
- ## Development Commands
181
+ For deployment-specific behavior, keep the packaged manifest as the baseline and pass `--from-manifest` with an override manifest rather than mutating the installed package in place.
228
182
 
229
- Run all commands from `repos/hagiscript/`:
183
+ ## Related Runtime Tooling
230
184
 
231
- ```bash
232
- npm install
233
- npm run lint
234
- npm run format:check
235
- npm test
236
- npm run build
237
- npm run pack:check
238
- ```
185
+ ### Managed Node Runtime
239
186
 
240
- Additional commands:
187
+ Install a standalone managed Node.js runtime:
241
188
 
242
189
  ```bash
243
- npm run clean
244
- npm run format
245
- npm run test:watch
246
- npm run publish:prepare-dev-version
247
- npm run publish:verify-release -- v0.1.0
190
+ hagiscript install-node --target /opt/hagiscript/node
191
+ hagiscript install-node --target /opt/hagiscript/node22 --version 22
248
192
  ```
249
193
 
250
- ## Build Outputs
251
-
252
- `npm run build` compiles TypeScript with strict NodeNext settings into `dist/`. Expected entry points include:
194
+ Validate an existing managed Node.js runtime:
253
195
 
254
- - `dist/index.js`
255
- - `dist/index.d.ts`
256
- - `dist/index.js.map`
257
- - `dist/cli.js`
258
- - `dist/cli.d.ts`
259
- - `dist/cli.js.map`
196
+ ```bash
197
+ hagiscript check-node --target /opt/hagiscript/node
198
+ ```
260
199
 
261
- The package `exports` field points consumers to `dist/index.js` and `dist/index.d.ts`. The published package name is `@hagicode/hagiscript`, and the `bin.hagiscript` entry points to `dist/cli.js`.
200
+ ### Managed npm Package Sync
262
201
 
263
- ## Package Verification
202
+ Sync npm global packages into a managed runtime instead of the host environment:
264
203
 
265
- `npm run pack:check` runs a dry-run package inspection and fails if required runtime files are missing or source-only files are accidentally included. The published package should contain generated `dist` files and documentation, not raw tests, scripts, coverage, or temporary files.
204
+ ```bash
205
+ hagiscript npm-sync --manifest ./manifest.json
206
+ hagiscript npm-sync --runtime /opt/hagiscript/node --manifest ./manifest.json
207
+ ```
266
208
 
267
- ## Release Automation
209
+ This is mainly useful when runtime maintenance also needs a controlled agent CLI or package inventory inside the managed runtime.
268
210
 
269
- GitHub Actions provide three automation paths:
211
+ ## Development
270
212
 
271
- - `ci.yml` installs dependencies with `npm ci`, then runs tests, build, and package verification.
272
- - `npm-publish.yml` resolves a unique prerelease version from `main`, stamps both `package.json` and `package-lock.json` with `npm version --no-git-tag-version`, then publishes to the `dev` dist-tag.
273
- - `npm-publish.yml` also publishes stable GitHub releases tagged as `vX.Y.Z` to the `latest` dist-tag after validating the tag format, rejecting tags older than the repository base version, and stamping the stable version the same way.
274
- - `release-drafter.yml` keeps a categorized release draft using `.github/release-drafter.yml`.
213
+ Run from `repos/hagiscript/`:
275
214
 
276
- Before the first publish, make sure the npm organization or user scope `hagicode` exists on npm and grant publish access for `@hagicode/hagiscript`. For GitHub Actions releases, configure npm trusted publishing with package `@hagicode/hagiscript`, owner `HagiCode-org`, repository `hagiscript`, and workflow filename `npm-publish.yml`. Do not enter the full workflow path as the filename; leave the npm environment field empty unless the workflow job explicitly declares an environment. If the scope is missing or the workflow identity cannot create packages under it, npm returns `E404 Not Found` during the final `PUT https://registry.npmjs.org/@hagicode%2fhagiscript` publish request.
215
+ ```bash
216
+ npm install
217
+ npm test
218
+ npm run build
219
+ npm run pack:check
220
+ ```
277
221
 
278
- Run the publish prerequisite check before retrying a failed release:
222
+ Useful runtime-focused checks:
279
223
 
280
224
  ```bash
281
- npm run publish:check-prereqs
225
+ npm run integration:runtime-management
226
+ npm run integration:installed-runtime
282
227
  ```
283
228
 
284
- For local manual releases, run plain `npm publish` after logging in with an npm account that can publish under `@hagicode`.
285
-
286
229
  ## License
287
230
 
288
231
  MIT. See [LICENSE](./LICENSE).
package/bin/runtime ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCli } from "../dist/cli.js"
4
+
5
+ const argv = [
6
+ process.argv[0] ?? process.execPath,
7
+ "hagicode-runtime",
8
+ "runtime",
9
+ ...process.argv.slice(2)
10
+ ]
11
+
12
+ runCli(argv).catch((error) => {
13
+ const message = error instanceof Error ? error.message : String(error)
14
+ process.stderr.write(`${message}\n`)
15
+ process.exitCode = 1
16
+ })
package/dist/cli.js CHANGED
@@ -5,6 +5,8 @@ import { Command } from "commander";
5
5
  import { createRuntimeInfo, packageVersion } from "./index.js";
6
6
  import { registerNpmSyncCommand } from "./commands/npm-sync-commands.js";
7
7
  import { registerNodeRuntimeCommands } from "./commands/node-runtime-commands.js";
8
+ import { registerPm2Commands } from "./commands/pm2-commands.js";
9
+ import { registerRuntimeCommands } from "./commands/runtime-commands.js";
8
10
  export function createCli() {
9
11
  const program = new Command();
10
12
  program
@@ -20,6 +22,8 @@ export function createCli() {
20
22
  });
21
23
  registerNodeRuntimeCommands(program);
22
24
  registerNpmSyncCommand(program);
25
+ registerPm2Commands(program);
26
+ registerRuntimeCommands(program);
23
27
  program.action(() => {
24
28
  program.outputHelp();
25
29
  });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAElF,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,YAAY,CAAC;SAClB,WAAW,CAAC,6CAA6C,CAAC;SAC1D,OAAO,CAAC,cAAc,EAAE,eAAe,EAAE,8BAA8B,CAAC,CAAC;IAE5E,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,mCAAmC,CAAC;SAChD,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;QACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEL,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACrC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAEhC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE;QAClB,OAAO,CAAC,UAAU,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI;IAC9C,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAC3B,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAE1B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,eAAe,EAAE,EAAE,CAAC;IACtB,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAChC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;QACrC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,YAAY,CAAC;SAClB,WAAW,CAAC,6CAA6C,CAAC;SAC1D,OAAO,CAAC,cAAc,EAAE,eAAe,EAAE,8BAA8B,CAAC,CAAC;IAE5E,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,mCAAmC,CAAC;SAChD,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;QACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEL,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACrC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAChC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAEjC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE;QAClB,OAAO,CAAC,UAAU,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI;IAC9C,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAC3B,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAE1B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,eAAe,EAAE,EAAE,CAAC;IACtB,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAChC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;QACrC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerPm2Commands(program: Command): void;
@@ -0,0 +1,54 @@
1
+ import { InvalidArgumentError } from "commander";
2
+ import { renderManagedPm2StatusText, runManagedPm2Command, supportedPm2Services } from "../runtime/pm2-manager.js";
3
+ export function registerPm2Commands(program) {
4
+ program
5
+ .command("pm2")
6
+ .description("manage PM2-backed hagicode-runtime services")
7
+ .argument("<service>", "managed service name", parseManagedPm2Service)
8
+ .argument("<action>", "pm2 action", parseManagedPm2Action)
9
+ .option("--from-manifest <path>", "override the default runtime manifest")
10
+ .option("--runtime-root <path>", "managed runtime root override")
11
+ .action(async (service, action, options, command) => {
12
+ try {
13
+ const result = await runManagedPm2Command({
14
+ manifestPath: validatePathOption(options.fromManifest, "--from-manifest"),
15
+ runtimeRoot: validatePathOption(options.runtimeRoot, "--runtime-root"),
16
+ service,
17
+ action
18
+ });
19
+ process.stdout.write(`${renderManagedPm2StatusText(result)}\n`);
20
+ }
21
+ catch (error) {
22
+ command.error(formatPm2Error(error), { exitCode: 1 });
23
+ }
24
+ });
25
+ }
26
+ function parseManagedPm2Service(value) {
27
+ if (supportedPm2Services.includes(value)) {
28
+ return value;
29
+ }
30
+ throw new InvalidArgumentError(`Unsupported managed PM2 service "${value}". Supported services: ${supportedPm2Services.join(", ")}.`);
31
+ }
32
+ function parseManagedPm2Action(value) {
33
+ if (value === "start" || value === "stop" || value === "status") {
34
+ return value;
35
+ }
36
+ throw new InvalidArgumentError(`Unsupported PM2 action "${value}". Supported actions: start, stop, status.`);
37
+ }
38
+ function validatePathOption(value, optionName) {
39
+ if (value === undefined) {
40
+ return undefined;
41
+ }
42
+ const normalized = value.trim();
43
+ if (!normalized) {
44
+ throw new InvalidArgumentError(`${optionName} must be a non-empty path.`);
45
+ }
46
+ if (normalized.includes("\0")) {
47
+ throw new InvalidArgumentError(`${optionName} contains an invalid null byte.`);
48
+ }
49
+ return normalized;
50
+ }
51
+ function formatPm2Error(error) {
52
+ return error instanceof Error ? error.message : String(error);
53
+ }
54
+ //# sourceMappingURL=pm2-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm2-commands.js","sourceRoot":"","sources":["../../src/commands/pm2-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,oBAAoB,EAAE,MAAM,WAAW,CAAA;AACzD,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,oBAAoB,EAGrB,MAAM,2BAA2B,CAAA;AAOlC,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,6CAA6C,CAAC;SAC1D,QAAQ,CAAC,WAAW,EAAE,sBAAsB,EAAE,sBAAsB,CAAC;SACrE,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,qBAAqB,CAAC;SACzD,MAAM,CAAC,wBAAwB,EAAE,uCAAuC,CAAC;SACzE,MAAM,CAAC,uBAAuB,EAAE,+BAA+B,CAAC;SAChE,MAAM,CACL,KAAK,EACH,OAA8B,EAC9B,MAAwB,EACxB,OAA0B,EAC1B,OAAgB,EAChB,EAAE;QACF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC;gBACxC,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC,YAAY,EAAE,iBAAiB,CAAC;gBACzE,WAAW,EAAE,kBAAkB,CAAC,OAAO,CAAC,WAAW,EAAE,gBAAgB,CAAC;gBACtE,OAAO;gBACP,MAAM;aACP,CAAC,CAAA;YAEF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,0BAA0B,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACjE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;QACvD,CAAC;IACH,CAAC,CACF,CAAA;AACL,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa;IAC3C,IAAK,oBAA0C,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,OAAO,KAA8B,CAAA;IACvC,CAAC;IAED,MAAM,IAAI,oBAAoB,CAC5B,oCAAoC,KAAK,0BAA0B,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACtG,CAAA;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC1C,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,IAAI,oBAAoB,CAC5B,2BAA2B,KAAK,4CAA4C,CAC7E,CAAA;AACH,CAAC;AAED,SAAS,kBAAkB,CACzB,KAAyB,EACzB,UAAkB;IAElB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,oBAAoB,CAAC,GAAG,UAAU,4BAA4B,CAAC,CAAA;IAC3E,CAAC;IAED,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,oBAAoB,CAAC,GAAG,UAAU,iCAAiC,CAAC,CAAA;IAChF,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC/D,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerRuntimeCommands(program: Command): void;