@huynle/hub 0.9.0 → 0.9.1

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 (63) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +6 -4
  3. package/package.json +1 -1
  4. package/packages/claude-code/package.json +1 -1
  5. package/packages/claude-code/src/wrapper.ts +2 -2
  6. package/packages/cli/dist/hub-cli.js +1126 -479
  7. package/packages/cli/package.json +1 -1
  8. package/packages/cli/src/bootstrap/PHASE3-CONTRACT.md +112 -0
  9. package/packages/cli/src/bootstrap/adapters/node-services/control.ts +164 -21
  10. package/packages/cli/src/bootstrap/adapters/node-services/plan.ts +24 -7
  11. package/packages/cli/src/bootstrap/adapters/node-services/render.ts +116 -9
  12. package/packages/cli/src/bootstrap/adapters/node-services/validate.ts +8 -2
  13. package/packages/cli/src/bootstrap/contracts/actions.ts +8 -6
  14. package/packages/cli/src/bootstrap/contracts/discovery.ts +4 -3
  15. package/packages/cli/src/bootstrap/contracts/exec.ts +4 -2
  16. package/packages/cli/src/bootstrap/contracts/paths.ts +2 -1
  17. package/packages/cli/src/bootstrap/contracts/platform.ts +5 -5
  18. package/packages/cli/src/bootstrap/discovery/discover.ts +7 -2
  19. package/packages/cli/src/bootstrap/discovery/host.ts +2 -0
  20. package/packages/cli/src/bootstrap/preview/plan.ts +5 -1
  21. package/packages/cli/src/bootstrap/profiles/desired.ts +16 -1
  22. package/packages/cli/src/bootstrap/profiles/history.ts +2 -1
  23. package/packages/cli/src/bootstrap/profiles/upgrade.ts +2 -2
  24. package/packages/cli/src/bootstrap/release/assets.ts +4 -1
  25. package/packages/cli/src/node.ts +94 -12
  26. package/packages/cli/src/setup/commands.ts +27 -7
  27. package/packages/cli/src/setup/runtime.ts +31 -4
  28. package/packages/codex/package.json +1 -1
  29. package/packages/codex/src/wrapper.ts +2 -2
  30. package/packages/node/package.json +1 -1
  31. package/packages/node/src/config.ts +49 -17
  32. package/packages/node/src/git.ts +16 -2
  33. package/packages/node/src/harnesses.ts +54 -9
  34. package/packages/node/src/host.ts +61 -15
  35. package/packages/node/src/opencode-service.ts +111 -0
  36. package/packages/node/src/opencode-warm.ts +11 -5
  37. package/packages/node/src/run.ts +50 -5
  38. package/packages/preset/package.json +1 -1
  39. package/packages/protocol/package.json +1 -1
  40. package/packages/protocol/src/index.ts +3 -1
  41. package/packages/protocol/src/launch.ts +39 -4
  42. package/packages/runtime-openshell/package.json +1 -1
  43. package/packages/runtime-sdk/package.json +1 -1
  44. package/packages/sdk/package.json +1 -1
  45. package/packages/spoke-sdk/package.json +1 -1
  46. package/src/central/agent/launch-spec.ts +4 -2
  47. package/src/central/install/CONTRACT.md +4 -4
  48. package/src/central/install/install.ps1 +37 -5
  49. package/src/central/install/render.ts +13 -8
  50. package/web/dist/assets/{ArtifactPage-4GoBqSpU.js → ArtifactPage-BKISN-Qj.js} +1 -1
  51. package/web/dist/assets/{ArtifactPane-Dx_0iWwH.js → ArtifactPane-CKOiAUNH.js} +1 -1
  52. package/web/dist/assets/{ArtifactWorkbench-CuHgARMk.js → ArtifactWorkbench-d7R1o-rs.js} +1 -1
  53. package/web/dist/assets/{Diagram-CZM_R7MG.js → Diagram-azw2B_QH.js} +1 -1
  54. package/web/dist/assets/{Library-TwvrwqSk.js → Library-CcjZXsfF.js} +2 -2
  55. package/web/dist/assets/{ProfilesDestination-rKNDpLjR.js → ProfilesDestination-DdzbzmeK.js} +1 -1
  56. package/web/dist/assets/{TeamsPage-DtJylLrt.js → TeamsPage-CDyjrK-I.js} +1 -1
  57. package/web/dist/assets/{Watchtower-Bmgdyfjb.js → Watchtower-DYwoUWME.js} +2 -2
  58. package/web/dist/assets/{index-D-xG9nrc.js → index-LNMZCqgE.js} +15 -15
  59. package/web/dist/assets/{live-7q72Lyj2.js → live-ycZ_aQZO.js} +1 -1
  60. package/web/dist/assets/{renderer2d-hfZxM6Xl.js → renderer2d-BIwbgRoX.js} +1 -1
  61. package/web/dist/assets/{renderer3d-Km9vipTM.js → renderer3d-C1a7eYGQ.js} +1 -1
  62. package/web/dist/assets/{safe-area-BAbgBiFk.js → safe-area-DHhPy61Q.js} +1 -1
  63. package/web/dist/index.html +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.1
4
+
5
+ **+ launch node on Windows.** `hubctl` installs `hub node` as a per-user logon task (Task Scheduler: no admin, no
6
+ stored password, no window), and on Windows the node starts OpenCode's background service, so a Windows machine stays
7
+ online and takes launches without OpenCode left open. Choose it in the console's Set up dialog or with
8
+ `install.ps1?profile=launch-node`. All harnesses (Claude Code, Codex) stays coming soon on Windows. No migration is
9
+ needed.
10
+
11
+ ### Machine setup
12
+ - **+ launch node on Windows**: `install.ps1` takes `profile=launch-node` with a `~/…` or `C:/…` workspace root and
13
+ `activate=1` (passed to hubctl as `--workspace-root` and `--confirm-activation`), and the console's Set up dialog
14
+ offers **+ launch node** on Windows (workspace folder as `C:\Users\you\projects`, `C:/…` or `~/…`; network
15
+ folders refused; Start services now). **All harnesses** stays coming soon on Windows.
16
+ - **hubctl: the `task-scheduler` service manager** (windows-x64): `hub node` runs as task `hub-node-<user>` at logon
17
+ (`conhost --headless hubctl.exe node run`, InteractiveToken, LeastPrivilege; the Task XML is UTF-16 in
18
+ `~/.local/state/hub/tasks`), restarted within a minute if it exits, controlled through a fixed `schtasks`/`taskkill`
19
+ allowlist with a locale-independent running check; `hub node install/uninstall` writes the XML and prints the
20
+ `schtasks` commands. `launch-node` plans on Windows; `full-harness` stays refused there.
21
+ - **The node on Windows**: canonical `C:/…` paths in the launch protocol, node.json (`C:\…`, `C:/…`, `~/…`) and
22
+ worktrees; it starts OpenCode's background service when none runs, then keeps it warm; a node with no workspace
23
+ roots waits for node.json instead of exiting; its log goes to `~/.local/state/hub/node.log`. git commands that hang
24
+ are killed with their children; every spawn starts hidden.
25
+
3
26
  ## 0.9.0
4
27
 
5
28
  Three things in one release: **media in sessions** (screenshots, images, Mermaid diagrams, safe HTML previews, and
package/README.md CHANGED
@@ -198,8 +198,9 @@ curl -fsSL 'https://hub.example.com/install.sh?profile=launch-node&root=~/projec
198
198
  ```
199
199
 
200
200
  ```powershell
201
- # Windows x64 (PowerShell 5.1 or 7): the same steps with hubctl-windows-x64.exe; OpenCode only for now
201
+ # Windows x64 (PowerShell 5.1 or 7): the same steps with hubctl-windows-x64.exe
202
202
  irm 'https://hub.example.com/install.ps1' | iex
203
+ irm 'https://hub.example.com/install.ps1?profile=launch-node&root=C:/Users/me/projects&activate=1' | iex
203
204
  ```
204
205
 
205
206
  Query options (each optional, at most once; anything else answers 400 with the reason):
@@ -207,11 +208,12 @@ Query options (each optional, at most once; anything else answers 400 with the r
207
208
  | Key | Values | Default |
208
209
  |---|---|---|
209
210
  | `profile` | `session-only` (OpenCode only), `launch-node` (+ a launch node), `full-harness` (all harnesses) | `session-only` |
210
- | `root` | the launch node's workspace root, only with `launch-node`: up to 200 characters of `A-Z a-z 0-9 . _ / ~ -`, starting with `/` or `~/`, no `..` or `//` | `~/projects` |
211
+ | `root` | the launch node's workspace root, only with `launch-node`: up to 200 characters of `A-Z a-z 0-9 . _ / ~ -`, starting with `/` or `~/` (`install.ps1`: `~/` or a drive path such as `C:/`, forward slashes), no `..` or `//` | `~/projects` |
211
212
  | `activate` | `1` starts the services now (`--confirm-activation`), `0` leaves them stopped | `0` |
212
213
 
213
- `install.ps1` takes only `profile=session-only` and `activate=0` for now (hubctl does not install user services on
214
- Windows yet) and runs on x64 Windows only (no arm64 build yet). It never closes your PowerShell window: a failure is
214
+ `install.ps1` takes `session-only` and `launch-node` (the node runs as a per-user logon task); `full-harness` answers
215
+ 400 for now (Claude Code and Codex need user services hubctl does not install on Windows yet). It runs on x64
216
+ Windows only (no arm64 build yet). It never closes your PowerShell window: a failure is
215
217
  one red `hub setup:` line. After a successful apply it adds `%USERPROFILE%\.local\bin` to your user PATH (once; open a
216
218
  new terminal for other windows). The scripts carry
217
219
  the hub's public URL, version and the validated choices; never a token. They download hubctl from this version's
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huynle/hub",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Hub: a harness-agnostic central hub your AI agent harnesses connect to (OpenCode first). Follow, steer and stop sessions from your phone or browser, with notifications, optional hands-free Voice and a self-hostable server.",
5
5
  "license": "MIT",
6
6
  "author": "Huy Le",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huynle/hub-claude-code",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "private": true,
5
5
  "description": "The Claude Code hooks spoke: per-user daemon, hook bridge, plugin dir, `hub claude` wrapper and daemon-backed MCP server (internal; shipped inside @huynle/hub, not published on its own).",
6
6
  "license": "MIT",
@@ -57,7 +57,7 @@ function spawnDaemon(io: ClaudeIo): void {
57
57
  ensurePrivateDir(dir)
58
58
  const log = openSync(path.join(dir, "daemon.log"), "a", 0o600)
59
59
  try {
60
- const child = spawn(io.program.execPath, [io.program.entry, "claude-code", "daemon"], { detached: true, stdio: ["ignore", log, log], env: { ...io.env, BUN_BE_BUN: "1" } })
60
+ const child = spawn(io.program.execPath, [io.program.entry, "claude-code", "daemon"], { detached: true, windowsHide: true, stdio: ["ignore", log, log], env: { ...io.env, BUN_BE_BUN: "1" } })
61
61
  child.on("error", () => {})
62
62
  child.unref()
63
63
  } finally {
@@ -100,7 +100,7 @@ async function prepare(io: ClaudeIo, socket: string): Promise<string | undefined
100
100
  /** Runs `bin` with the terminal; resolves with its exit code (128 + signal number when a signal ended it). */
101
101
  function spawnClaude(bin: string, args: readonly string[], env: Env, stderr: (s: string) => void): Promise<number> {
102
102
  return new Promise((resolve) => {
103
- const child = spawn(bin, args, { stdio: "inherit", env: env as NodeJS.ProcessEnv })
103
+ const child = spawn(bin, args, { stdio: "inherit", windowsHide: true, env: env as NodeJS.ProcessEnv })
104
104
  // The terminal sends Ctrl-C to Claude Code too: it decides what that means; this process keeps waiting.
105
105
  const ignore = () => {}
106
106
  const forward = () => child.kill("SIGTERM")