@huynle/hub 0.8.7 → 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.
- package/CHANGELOG.md +152 -0
- package/README.md +75 -16
- package/package.json +5 -1
- package/packages/claude-code/package.json +1 -1
- package/packages/claude-code/src/wrapper.ts +2 -2
- package/packages/cli/dist/hub-cli.js +1413 -523
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/bootstrap/PHASE3-CONTRACT.md +112 -0
- package/packages/cli/src/bootstrap/adapters/node-services/control.ts +164 -21
- package/packages/cli/src/bootstrap/adapters/node-services/plan.ts +24 -7
- package/packages/cli/src/bootstrap/adapters/node-services/render.ts +116 -9
- package/packages/cli/src/bootstrap/adapters/node-services/validate.ts +8 -2
- package/packages/cli/src/bootstrap/contracts/actions.ts +8 -6
- package/packages/cli/src/bootstrap/contracts/discovery.ts +4 -3
- package/packages/cli/src/bootstrap/contracts/exec.ts +4 -2
- package/packages/cli/src/bootstrap/contracts/paths.ts +2 -1
- package/packages/cli/src/bootstrap/contracts/platform.ts +5 -5
- package/packages/cli/src/bootstrap/discovery/discover.ts +7 -2
- package/packages/cli/src/bootstrap/discovery/host.ts +2 -0
- package/packages/cli/src/bootstrap/preview/plan.ts +5 -1
- package/packages/cli/src/bootstrap/profiles/desired.ts +16 -1
- package/packages/cli/src/bootstrap/profiles/history.ts +2 -1
- package/packages/cli/src/bootstrap/profiles/upgrade.ts +2 -2
- package/packages/cli/src/bootstrap/release/assets.ts +4 -1
- package/packages/cli/src/cli.ts +23 -10
- package/packages/cli/src/http.ts +1 -0
- package/packages/cli/src/launches.ts +5 -1
- package/packages/cli/src/mcp.ts +28 -8
- package/packages/cli/src/messaging.ts +14 -0
- package/packages/cli/src/node.ts +94 -12
- package/packages/cli/src/setup/commands.ts +27 -7
- package/packages/cli/src/setup/runtime.ts +31 -4
- package/packages/cli/src/team-intake-mcp.ts +26 -2
- package/packages/codex/package.json +1 -1
- package/packages/codex/src/wrapper.ts +2 -2
- package/packages/node/package.json +1 -1
- package/packages/node/src/config.ts +49 -17
- package/packages/node/src/git.ts +16 -2
- package/packages/node/src/harnesses.ts +54 -9
- package/packages/node/src/host.ts +61 -15
- package/packages/node/src/opencode-service.ts +111 -0
- package/packages/node/src/opencode-warm.ts +11 -5
- package/packages/node/src/run.ts +50 -5
- package/packages/preset/package.json +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/schema/app-delivery/v1.schema.json +677 -0
- package/packages/protocol/src/artifacts.ts +43 -0
- package/packages/protocol/src/credentials.ts +38 -0
- package/packages/protocol/src/index.ts +59 -6
- package/packages/protocol/src/launch.ts +46 -6
- package/packages/protocol/src/markdown.ts +753 -0
- package/packages/protocol/src/media-allowlist.ts +240 -0
- package/packages/protocol/src/media.ts +120 -0
- package/packages/protocol/src/preview-bundle.ts +221 -0
- package/packages/protocol/src/voice-recording.ts +8 -0
- package/packages/runtime-openshell/package.json +1 -1
- package/packages/runtime-sdk/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/packages/sdk/src/client.ts +17 -3
- package/packages/sdk/src/errors.ts +1 -0
- package/packages/sdk/src/team-intake.ts +8 -0
- package/packages/sdk/src/types.ts +16 -2
- package/packages/spoke-sdk/package.json +1 -1
- package/src/central/agent/delivery.ts +35 -6
- package/src/central/agent/errors.ts +2 -0
- package/src/central/agent/events.ts +11 -2
- package/src/central/agent/launch-engine.ts +65 -4
- package/src/central/agent/launch-routes.ts +8 -0
- package/src/central/agent/launch-spec.ts +22 -3
- package/src/central/agent/launch-store.ts +2 -2
- package/src/central/agent/message-routes.ts +49 -11
- package/src/central/agent/messages.ts +17 -4
- package/src/central/agent/not-after.ts +28 -0
- package/src/central/agent/placement.ts +36 -4
- package/src/central/agent/routes.ts +3 -1
- package/src/central/agent/webhook-routes.ts +21 -9
- package/src/central/agent/webhooks.ts +27 -9
- package/src/central/artifacts/host.ts +3 -1
- package/src/central/artifacts/maintenance.ts +2 -1
- package/src/central/artifacts/preview-bundle.ts +81 -0
- package/src/central/artifacts/previews.ts +94 -0
- package/src/central/artifacts/routes.ts +12 -1
- package/src/central/artifacts/store.ts +198 -8
- package/src/central/config.ts +34 -0
- package/src/central/fetch-budget.ts +59 -0
- package/src/central/fetcher.ts +372 -0
- package/src/central/http.ts +277 -22
- package/src/central/install/CONTRACT.md +4 -4
- package/src/central/install/install.ps1 +37 -5
- package/src/central/install/render.ts +13 -8
- package/src/central/media-remote.ts +248 -0
- package/src/central/media-timeline.ts +317 -0
- package/src/central/media-unfurl.ts +119 -0
- package/src/central/profiles/content.ts +3 -35
- package/src/central/recording/routes.ts +2 -2
- package/src/central/recording/schema.ts +3 -1
- package/src/central/registry.ts +449 -21
- package/src/central/spoke-ws.ts +17 -3
- package/src/central/store.ts +21 -0
- package/src/central/teams/intake-routes.ts +2 -1
- package/src/central/teams/intake.ts +200 -15
- package/src/central/unfurl-parse.ts +313 -0
- package/src/index.ts +68 -8
- package/src/speakable.ts +33 -1
- package/src/spoke/conversation.ts +7 -4
- package/src/spoke/deliver.ts +19 -0
- package/src/spoke/media-bytes.ts +171 -0
- package/src/spoke/media-policy.ts +394 -0
- package/src/spoke/media.ts +189 -0
- package/src/spoke/own-server.ts +30 -0
- package/src/spoke/preview-bundle.ts +538 -0
- package/src/spoke/spoke.ts +387 -17
- package/src/spoke/timeline.ts +59 -5
- package/src/spoke/voice-front.ts +335 -0
- package/web/dist/assets/24BXRY42-Zfr7jm_p.js +2 -0
- package/web/dist/assets/4FHPYW2L-C6Z67098.js +2 -0
- package/web/dist/assets/4LWW3ZNH-CUiYeygH.js +1 -0
- package/web/dist/assets/5THPTBWS-Ce_hS451.js +1 -0
- package/web/dist/assets/5XYWFMKW-CW-BCKiK.js +4 -0
- package/web/dist/assets/64PMEAB3-BjpCDGU9.js +8 -0
- package/web/dist/assets/6BEWHPQE-BpNa96Ze.js +2 -0
- package/web/dist/assets/6PIGVMFT-YXn9Hgnb.js +1 -0
- package/web/dist/assets/75JW6PN6-BFpDBuGN.js +2 -0
- package/web/dist/assets/7WLXJQOR-D6QVYUu9.js +1 -0
- package/web/dist/assets/7XWI72E6-BMuIspEy.js +2 -0
- package/web/dist/assets/A4UD2L5Z-BQzcD9dU.js +8 -0
- package/web/dist/assets/ArtifactPage-BKISN-Qj.js +1 -0
- package/web/dist/assets/ArtifactPane-CKOiAUNH.js +1 -0
- package/web/dist/assets/ArtifactWorkbench-d7R1o-rs.js +6 -0
- package/web/dist/assets/BGW36YJW-CJMhya8S.js +4 -0
- package/web/dist/assets/CGIZI67J-DYDSLME8.js +2 -0
- package/web/dist/assets/DKTLEL5E-DciMwFJ1.js +1 -0
- package/web/dist/assets/DNNCRC2E-BIeKf5t-.js +5 -0
- package/web/dist/assets/Diagram-azw2B_QH.js +1 -0
- package/web/dist/assets/Diagram-vdpmp3xu.css +1 -0
- package/web/dist/assets/E67EBMDD--AucIw59.js +5 -0
- package/web/dist/assets/EFYWJBJK-CVywe_D5.js +1 -0
- package/web/dist/assets/EXE5EH6O-DR1IHCTr.js +4 -0
- package/web/dist/assets/FTXIJQGB-BZVuiBn1.js +1 -0
- package/web/dist/assets/G3MDBVQH-BZmnMkFw.js +1 -0
- package/web/dist/assets/G6GPDDNC-DEz8F449.js +2 -0
- package/web/dist/assets/G76NGGFM-CrB2V34K.js +1 -0
- package/web/dist/assets/GH6G3TJC-D3RTYEH4.js +2 -0
- package/web/dist/assets/HPNUA7RO-B19NeNOJ.js +1 -0
- package/web/dist/assets/HQRGC5D7-Dmpzq6Rn.js +4 -0
- package/web/dist/assets/IX6Z2TVR-DphRHnek.js +5 -0
- package/web/dist/assets/J77NQRCJ-B7AGcxvw.js +3 -0
- package/web/dist/assets/JAD36DTZ-B9-dbsS0.js +5 -0
- package/web/dist/assets/LF3NJQAX-koL91UZ9.js +2 -0
- package/web/dist/assets/LRZCOFJZ-Cdjasfuf.js +6 -0
- package/web/dist/assets/Library-CcjZXsfF.js +2 -0
- package/web/dist/assets/Lightbox-C8KNKwOA.css +1 -0
- package/web/dist/assets/Lightbox-Du56MXGX.js +1 -0
- package/web/dist/assets/MediaImage-Ds_JUx3a.js +4 -0
- package/web/dist/assets/N5NF2FGY-OuapYTfr.js +2 -0
- package/web/dist/assets/N7OWWQHY-BNLd-Q_U.js +2 -0
- package/web/dist/assets/NT5JY5WP-1lJM-aun.js +1 -0
- package/web/dist/assets/OT7W3RNY-jDL3drzX.js +4 -0
- package/web/dist/assets/P67P66DB-CE-opRb8.js +3 -0
- package/web/dist/assets/PFLLLM7K-DDJFgzW3.js +2 -0
- package/web/dist/assets/PUAMC4MJ-CtBm-WuU.js +12 -0
- package/web/dist/assets/PVFCHRLY-CG5JXv60.js +2 -0
- package/web/dist/assets/ProfilesDestination-DdzbzmeK.js +1 -0
- package/web/dist/assets/QQW2P742-BbcEkpa4.js +1 -0
- package/web/dist/assets/RVARI57O-CgA1WoRv.js +1 -0
- package/web/dist/assets/S63OEDPG-CKlhpvl2.js +3 -0
- package/web/dist/assets/SG5TVYLW-BBtiwXPL.js +2 -0
- package/web/dist/assets/TeamsPage-CDyjrK-I.js +1 -0
- package/web/dist/assets/UGRSUGA2-urZ_hx83.js +5 -0
- package/web/dist/assets/V44WA6U7-DYfX3OlM.js +1 -0
- package/web/dist/assets/V67O4WWV-xYxJ00QW.js +1 -0
- package/web/dist/assets/VBUCM3YD-JHGjuJC_.js +1 -0
- package/web/dist/assets/VINGRCPA-DZuJa3SH.js +7 -0
- package/web/dist/assets/WL6DNKX4-BHqripdA.js +2 -0
- package/web/dist/assets/WQ63CJYP-D6G5frDY.js +2 -0
- package/web/dist/assets/Watchtower-DYwoUWME.js +2 -0
- package/web/dist/assets/XOYAOB3S-L-KeA1EF.js +13 -0
- package/web/dist/assets/Y5LQLG3M-dr2-erb8.js +2 -0
- package/web/dist/assets/YIK6JTN6--1t-Ud8k.js +2 -0
- package/web/dist/assets/artifacts-DU9uRgs1.js +1 -0
- package/web/dist/assets/index-C3ci5UtY.css +1 -0
- package/web/dist/assets/index-LNMZCqgE.js +36 -0
- package/web/dist/assets/lazy-f3CuUNJZ.js +43 -0
- package/web/dist/assets/live-ycZ_aQZO.js +5 -0
- package/web/dist/assets/mermaid.worker-WDVRAh32.js +1 -0
- package/web/dist/assets/pane-layout-0RrLHGDr.js +1 -0
- package/web/dist/assets/preload-helper-BLdHbfdN.js +1 -0
- package/web/dist/assets/{renderer2d-CYag1CnR.js → renderer2d-BIwbgRoX.js} +1 -1
- package/web/dist/assets/{renderer3d-BRB6rgDJ.js → renderer3d-C1a7eYGQ.js} +1 -1
- package/web/dist/assets/{safe-area-fOy0AOuG.js → safe-area-DHhPy61Q.js} +1 -1
- package/web/dist/assets/{silero-worker-DhlIHyD_.js → silero-worker-e802lB5T.js} +1 -1
- package/web/dist/assets/smart-turn-v3.2-cpu-WpeLRbPA.onnx +0 -0
- package/web/dist/assets/smart-turn-worker-DaVJPdvJ.js +11 -0
- package/web/dist/assets/source-BWlvaODa.js +1 -0
- package/web/dist/assets/toast-Cuu2K0hx.js +1 -0
- package/web/dist/assets/ui-CFB4wQfF.js +3 -0
- package/web/dist/index.html +8 -6
- package/web/src/voice/turn/LICENSE +28 -0
- package/web/dist/assets/ArtifactPage-Dq7VW-bU.js +0 -1
- package/web/dist/assets/ArtifactPane-DKwbMTX9.js +0 -1
- package/web/dist/assets/ArtifactWorkbench-vrgIfncX.js +0 -6
- package/web/dist/assets/Library-D6-Go6Cu.js +0 -2
- package/web/dist/assets/ProfilesDestination-BOML2Dgf.js +0 -1
- package/web/dist/assets/TeamsPage-CNBTE8gB.js +0 -1
- package/web/dist/assets/Watchtower-Dor1Ubjy.js +0 -2
- package/web/dist/assets/hub-CrbItiwP.js +0 -13
- package/web/dist/assets/index-82Ce0IAf.css +0 -1
- package/web/dist/assets/index-D9SP3_0z.js +0 -22
- package/web/dist/assets/live-BNJgy0vg.js +0 -5
- package/web/dist/assets/pane-layout-EdR1kRrG.js +0 -1
- package/web/dist/assets/preload-helper-DqrJTq0t.js +0 -1
- package/web/dist/assets/source-Wbq35qGp.js +0 -1
- package/web/dist/assets/ui-j5FFk90B.js +0 -3
package/packages/node/src/run.ts
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
// node keeps OpenCode's background service and node.json's foreground servers warm (opencode-warm.ts) so their hub
|
|
8
8
|
// plugin loads without a client opening a project. Exit codes: 0 after a clean stop, 1 when
|
|
9
9
|
// the machine is not enrolled, EXIT_CONFIG (78, EX_CONFIG) when node.json gives the node nothing to do; the
|
|
10
|
-
// service units do not restart on 78.
|
|
10
|
+
// service units do not restart on 78. On Windows (Phase 3) the logon task restarts the node whatever its exit code,
|
|
11
|
+
// so a node with nothing to do waits there, re-reading node.json, instead of exiting; and while it offers opencode the node starts OpenCode's
|
|
12
|
+
// background service when none is registered (opencode-service.ts), since nothing else keeps it running there.
|
|
11
13
|
import { homedir } from "node:os"
|
|
12
14
|
import path from "node:path"
|
|
13
15
|
import type { NodeLaunchReport } from "../../protocol/src/index.ts"
|
|
@@ -15,8 +17,9 @@ import { OpenShellCli } from "../../runtime-openshell/src/cli.ts"
|
|
|
15
17
|
import type { Runtime } from "../../runtime-sdk/src/index.ts"
|
|
16
18
|
import { nodeConfigPath, readNodeConfig, readSpokeCredentials, type NodeConfig, type SpokeCredentials } from "./config.ts"
|
|
17
19
|
import { NodeDaemon, NODE_VERSION } from "./daemon.ts"
|
|
18
|
-
import { detectHarnesses } from "./harnesses.ts"
|
|
20
|
+
import { detectHarnesses, findExecutable, opencodeBinary } from "./harnesses.ts"
|
|
19
21
|
import { HostRuntime } from "./host.ts"
|
|
22
|
+
import { OpenCodeServiceStarter, serviceDiscovery, type StartRun } from "./opencode-service.ts"
|
|
20
23
|
import { OpenCodeWarmer, readServiceRegistration, serverEndpoint, type WarmEndpoint } from "./opencode-warm.ts"
|
|
21
24
|
import { createOpenShellRuntime, openshellBackends, PROBE_TIMEOUT_MS, sweepSandboxes } from "./openshell.ts"
|
|
22
25
|
|
|
@@ -35,8 +38,30 @@ export interface RunNodeOptions {
|
|
|
35
38
|
readonly openshellBinary?: string
|
|
36
39
|
/** Finds OpenCode's background service (default: readServiceRegistration on this env's registration file). */
|
|
37
40
|
readonly openCodeService?: () => Promise<WarmEndpoint | undefined>
|
|
41
|
+
/** The platform (default this one): win32 exits 0 for "nothing to do" and starts OpenCode's service. */
|
|
42
|
+
readonly platform?: string
|
|
43
|
+
/** win32: the OpenCode executable (default opencodeBinary found like a harness), undefined when not installed. */
|
|
44
|
+
readonly openCodeBinary?: () => string | undefined
|
|
45
|
+
/** win32: how `opencode service start` runs (default opencode-service.ts startRun). */
|
|
46
|
+
readonly startOpenCode?: StartRun
|
|
47
|
+
/** win32: how often a node with nothing to do re-reads node.json (default IDLE_RECHECK_MS). */
|
|
48
|
+
readonly idleRecheckMs?: number
|
|
38
49
|
}
|
|
39
50
|
|
|
51
|
+
/** win32: how often a node with no workspace roots re-reads node.json while it waits. */
|
|
52
|
+
export const IDLE_RECHECK_MS = 60_000
|
|
53
|
+
|
|
54
|
+
const sleep = (ms: number, signal: AbortSignal) =>
|
|
55
|
+
new Promise<void>((resolve) => {
|
|
56
|
+
const timer = setTimeout(done, ms)
|
|
57
|
+
function done() {
|
|
58
|
+
clearTimeout(timer)
|
|
59
|
+
signal.removeEventListener("abort", done)
|
|
60
|
+
resolve()
|
|
61
|
+
}
|
|
62
|
+
signal.addEventListener("abort", done, { once: true })
|
|
63
|
+
})
|
|
64
|
+
|
|
40
65
|
/** OpenCode's service registration file for `env` and `home` (@opencode/client's default location). */
|
|
41
66
|
export const openCodeServiceFile = (env: Env, home: string): string =>
|
|
42
67
|
path.join(env.XDG_STATE_HOME || path.join(home, ".local", "state"), "opencode", "service.json")
|
|
@@ -88,6 +113,7 @@ async function setupOpenShell(config: NodeConfig, credentials: SpokeCredentials,
|
|
|
88
113
|
export async function runNode(options: RunNodeOptions): Promise<number> {
|
|
89
114
|
const env = options.env ?? process.env
|
|
90
115
|
const home = options.home ?? homedir()
|
|
116
|
+
const platform = options.platform ?? process.platform
|
|
91
117
|
const log = options.log ?? ((line: string) => process.stderr.write(`[hub node] ${line}\n`))
|
|
92
118
|
|
|
93
119
|
const credentials = readSpokeCredentials(env, home)
|
|
@@ -96,11 +122,21 @@ export async function runNode(options: RunNodeOptions): Promise<number> {
|
|
|
96
122
|
return 1
|
|
97
123
|
}
|
|
98
124
|
const file = nodeConfigPath(env, home)
|
|
99
|
-
|
|
125
|
+
let { config, problems } = readNodeConfig(file, { platform, home })
|
|
100
126
|
for (const problem of problems) log(`${file}: ${problem}`)
|
|
101
127
|
if (config.workspaceRoots.length === 0) {
|
|
102
128
|
log(`${file} lists no workspaceRoots, so this node can prepare no workspaces; add e.g. {"workspaceRoots": ["${home}/projects"]}`)
|
|
103
|
-
return EXIT_CONFIG
|
|
129
|
+
if (platform !== "win32") return EXIT_CONFIG
|
|
130
|
+
// Task Scheduler restarts the logon task whatever the exit code (its repetition trigger), so a node with nothing to
|
|
131
|
+
// do waits here, re-reading node.json, instead of exiting and being started again every minute.
|
|
132
|
+
log(`waiting: re-reading ${file} every ${Math.round((options.idleRecheckMs ?? IDLE_RECHECK_MS) / 1000)} s until it lists workspaceRoots`)
|
|
133
|
+
while (config.workspaceRoots.length === 0) {
|
|
134
|
+
await sleep(options.idleRecheckMs ?? IDLE_RECHECK_MS, options.signal)
|
|
135
|
+
if (options.signal.aborted) return 0
|
|
136
|
+
;({ config, problems } = readNodeConfig(file, { platform, home }))
|
|
137
|
+
}
|
|
138
|
+
for (const problem of problems) log(`${file}: ${problem}`)
|
|
139
|
+
log(`workspace roots now set in ${file}; starting`)
|
|
104
140
|
}
|
|
105
141
|
|
|
106
142
|
if (options.signal.aborted) return 0
|
|
@@ -122,7 +158,16 @@ export async function runNode(options: RunNodeOptions): Promise<number> {
|
|
|
122
158
|
})
|
|
123
159
|
log(`hub node ${NODE_VERSION}: ${config.slots} slots, roots ${config.workspaceRoots.join(", ")}; host harnesses ${harnesses.join(", ") || "none"}`)
|
|
124
160
|
daemon.start()
|
|
125
|
-
if (harnesses.includes("opencode"))
|
|
161
|
+
if (harnesses.includes("opencode")) {
|
|
162
|
+
const read = options.openCodeService ?? (() => readServiceRegistration(openCodeServiceFile(env, home)))
|
|
163
|
+
const starter = new OpenCodeServiceStarter({
|
|
164
|
+
binary: options.openCodeBinary ?? (() => findExecutable(opencodeBinary(env, home, platform), env, platform)),
|
|
165
|
+
log,
|
|
166
|
+
env,
|
|
167
|
+
...(options.startOpenCode ? { run: options.startOpenCode } : {}),
|
|
168
|
+
})
|
|
169
|
+
startOpenCodeWarmers(config, serviceDiscovery(read, starter, platform), log, options.signal)
|
|
170
|
+
}
|
|
126
171
|
await new Promise<void>((resolve) => {
|
|
127
172
|
if (options.signal.aborted) return resolve()
|
|
128
173
|
options.signal.addEventListener("abort", () => resolve(), { once: true })
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huynle/hub-preset",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "The preset spoke: drives a harness without a spoke of its own through a terminal pane (tmux), described by a data-only preset; official presets in presets/ (internal; shipped inside @huynle/hub, not published on its own).",
|
|
6
6
|
"license": "MIT",
|