Skip to content

feat(hub)!: introduce @devframes/hub framework-neutral hub layer#24

Draft
antfu wants to merge 5 commits into
mainfrom
antfu/devframe-hub-eval
Draft

feat(hub)!: introduce @devframes/hub framework-neutral hub layer#24
antfu wants to merge 5 commits into
mainfrom
antfu/devframe-hub-eval

Conversation

@antfu
Copy link
Copy Markdown
Contributor

@antfu antfu commented May 22, 2026

Introduces @devframes/hub — the framework-neutral hub layer that lifts docks/terminals/messages/commands out of @vitejs/devtools-kit so any framework can build a hub kit on the same protocol. Hub-kit authors ship UI on top of the RPC + shared-state surface defined here; framework hosts only implement an adapter that calls mountDevframe().

mountDevframe() is the framework-neutral mount primitive, with built-in RPCs hub:open-path / hub:commands:execute exposing the host capabilities the UI relies on.

Two minimal example apps act as protocol witnesses:

  • examples/minimal-vite-devframe-hub/ — Vite plugin + tiny DOM UI.
  • examples/minimal-next-devframe-hub/ — Next.js host wiring the same protocol through App Router.

The DF8xxx diagnostic range is reserved for hub-side codes with per-subsystem sub-ranges; ten error reference pages and docs/guide/hub.md document the surface.

Internal devtools identifiers in the devframe package (mount paths, constants, types like DEVTOOLS_MOUNT_PATH, the REMOTE_CONNECTION_KEY value) are renamed to devframe so the surface lines up with the package name.

Coordinated thinning of @vitejs/devtools-kit to re-export from @devframes/hub is a follow-up PR in the vitejs/devtools repo.

Lifts the docks/terminals/messages/commands subsystems out of
@vitejs/devtools-kit into a framework-neutral package so any framework
(Vite, Next.js, etc.) can build a hub kit on the same infrastructure.
Adds `mountDevframe` as the framework-neutral mount primitive,
`HubHostCapabilities` for optional host capabilities (e.g. `openPath`),
and built-in RPCs `hub:open-path` / `hub:commands:execute`.

Reserves the `DF8xxx` diagnostic range for hub-side codes with
sub-ranges per subsystem. New `examples/minimal-vite-devtools-kit/`
acts as a protocol witness — a ~150-line Vite plugin + tiny DOM UI
that exercises every hub subsystem end to end.
Copilot AI review requested due to automatic review settings May 22, 2026 03:05
@netlify
Copy link
Copy Markdown

netlify Bot commented May 22, 2026

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit 96137ab
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a100cd28613ee0008e99024
😎 Deploy Preview https://deploy-preview-24--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a new framework-neutral @devframes/hub package that extracts and standardizes the multi-tool “hub” layer (docks/terminals/messages/commands + shared-state/RPC protocol) so different framework kits can build on the same infrastructure. This PR also adds a minimal Vite example that exercises the hub protocol end-to-end and documents the new surface + diagnostics.

Changes:

  • Added @devframes/hub package with node/client entrypoints, shared types/constants, built-in RPC/commands, and diagnostics in the DF8xxx range.
  • Wired workspace tooling (Turbo, TS path aliases, pnpm catalogs/lockfile) to build/consume the new package.
  • Added docs (hub guide + error reference pages) and a minimal Vite example as a protocol witness.

Reviewed changes

Copilot reviewed 61 out of 67 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
turbo.json Adds Turbo build pipelines for @devframes/hub and the minimal Vite example.
tsconfig.base.json Adds TS path aliases for @devframes/hub/* entrypoints.
pnpm-workspace.yaml Adds tinyexec to the dependency catalog.
pnpm-lock.yaml Locks new hub/example dependencies and workspace importers.
alias.ts Adds monorepo alias mappings for @devframes/hub/*.
AGENTS.md Documents hub package purpose and reserves DF8xxx diagnostic ranges.
packages/hub/package.json Defines the new published package exports and dependencies.
packages/hub/LICENSE.md Adds package-level MIT license.
packages/hub/tsconfig.json Hub package TS config (composite + DOM lib).
packages/hub/tsdown.config.ts Build configuration for hub multi-entry outputs.
packages/hub/src/index.ts Exposes hub’s public API (define helpers + types).
packages/hub/src/define.ts Adds defineCommand, defineDockEntry, defineJsonRenderSpec, and hub-context defineRpcFunction.
packages/hub/src/constants.ts Adds hub defaults and re-exports devframe constants.
packages/hub/src/utils/diagnostics-reporter.ts Adds ANSI diagnostics reporter wiring for hub diagnostics.
packages/hub/src/types/index.ts Hub types barrel + selective devframe type re-exports.
packages/hub/src/types/commands.ts Command palette types (server/client commands, keybindings, host).
packages/hub/src/types/docks.ts Dock entry types including remote-UI options and connection descriptor shape.
packages/hub/src/types/json-render.ts Json-render spec/renderer types.
packages/hub/src/types/messages.ts Message/toast queue types and host/client surfaces.
packages/hub/src/types/settings.ts Persisted hub user settings types.
packages/hub/src/types/terminals.ts Terminal session and child-process terminal types.
packages/hub/src/node/index.ts Hub node entrypoint barrel.
packages/hub/src/node/context.ts Implements createHubContext() wiring hosts, shared-state sync, and built-ins.
packages/hub/src/node/diagnostics.ts Defines DF8xxx diagnostics for hub subsystems.
packages/hub/src/node/host-commands.ts Implements commands registry + execution/list serialization.
packages/hub/src/node/host-docks.ts Implements dock registry, built-in dock entries, and remote-UI URL enrichment.
packages/hub/src/node/host-messages.ts Implements message queue + events + auto-delete + capacity eviction.
packages/hub/src/node/host-terminals.ts Implements terminal sessions + streaming channel integration + child-process terminals.
packages/hub/src/node/hub-builtins.ts Registers hub built-in command(s) like hub:open-path.
packages/hub/src/node/rpc-builtins.ts Adds hub built-in RPC(s) like hub:commands:execute.
packages/hub/src/node/mount-devframe.ts Adds framework-neutral mountDevframe() primitive.
packages/hub/src/node/utils.ts Adds createSimpleClientScript() helper for quick client-script entries.
packages/hub/src/client/index.ts Hub client entrypoint barrel + devframe client re-exports.
packages/hub/src/client/context.ts Adds global client-context getter and key export.
packages/hub/src/client/docks.ts Defines client-side dock/commands context types.
packages/hub/src/client/client-script.ts Defines dock client-script context shape.
packages/hub/src/client/remote.ts Adds remote-UI descriptor parsing and connectRemoteDevTools().
examples/minimal-vite-devtools-kit/package.json Adds minimal Vite example package and scripts.
examples/minimal-vite-devtools-kit/vite.config.ts Example Vite config wiring the minimal hub kit plugin.
examples/minimal-vite-devtools-kit/tsconfig.json Example TS config for Vite + DOM UI.
examples/minimal-vite-devtools-kit/index.html Minimal DOM UI shell.
examples/minimal-vite-devtools-kit/README.md Run instructions + protocol-witness explanation.
examples/minimal-vite-devtools-kit/src/minimal-hub-kit.ts Minimal Vite plugin that creates hub context and sidecar WS server.
examples/minimal-vite-devtools-kit/src/devframe.ts Demo devframe definition that registers commands/messages.
examples/minimal-vite-devtools-kit/src/client/main.ts Browser-side UI reading shared state and calling hub built-ins.
examples/minimal-vite-devtools-kit/src/client/style.css Styling for the minimal DOM UI.
docs/.vitepress/config.ts Adds hub guide to docs nav.
docs/guide/hub.md Documents hub concepts, protocol, host capabilities, and example.
docs/errors/DF8100.md Error reference for dock already registered.
docs/errors/DF8101.md Error reference for cannot change dock id.
docs/errors/DF8102.md Error reference for dock not registered.
docs/errors/DF8200.md Error reference for terminal session already registered.
docs/errors/DF8201.md Error reference for terminal session not registered.
docs/errors/DF8400.md Error reference for command already registered.
docs/errors/DF8401.md Error reference for cannot change command id.
docs/errors/DF8402.md Error reference for command not registered.
docs/errors/DF8500.md Error reference for missing host capability for built-in command.
tests/snapshots/tsnapi/@devframes/hub/index.snapshot.js Adds tsnapi public API snapshot for @devframes/hub.
tests/snapshots/tsnapi/@devframes/hub/index.snapshot.d.ts Adds tsnapi type snapshot for @devframes/hub.
tests/snapshots/tsnapi/@devframes/hub/node.snapshot.js Adds tsnapi public API snapshot for @devframes/hub/node.
tests/snapshots/tsnapi/@devframes/hub/node.snapshot.d.ts Adds tsnapi type snapshot for @devframes/hub/node.
tests/snapshots/tsnapi/@devframes/hub/client.snapshot.js Adds tsnapi public API snapshot for @devframes/hub/client.
tests/snapshots/tsnapi/@devframes/hub/client.snapshot.d.ts Adds tsnapi type snapshot for @devframes/hub/client.
tests/snapshots/tsnapi/@devframes/hub/constants.snapshot.js Adds tsnapi public API snapshot for @devframes/hub/constants.
tests/snapshots/tsnapi/@devframes/hub/constants.snapshot.d.ts Adds tsnapi type snapshot for @devframes/hub/constants.
tests/snapshots/tsnapi/@devframes/hub/types.snapshot.js Adds tsnapi public API snapshot for @devframes/hub/types.
tests/snapshots/tsnapi/@devframes/hub/types.snapshot.d.ts Adds tsnapi type snapshot for @devframes/hub/types.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +45 to +55
function buildRemoteUrl(baseUrl: string, payload: RemoteConnectionInfo, transport: 'fragment' | 'query'): string {
const encoded = base64UrlEncode(JSON.stringify(payload))
const param = `${REMOTE_CONNECTION_KEY}=${encoded}`
if (transport === 'fragment') {
// Replace any existing fragment bearing our key; otherwise append.
const hashIdx = baseUrl.indexOf('#')
if (hashIdx === -1)
return `${baseUrl}#${param}`
const before = baseUrl.slice(0, hashIdx)
return `${before}#${param}`
}
Comment on lines +134 to +138
const record = this.remoteDocks.get(view.id)
const endpoint = getInternalContext(this.context as DevToolsNodeContext).wsEndpoint
if (!record || !endpoint)
return view

Comment thread packages/hub/src/node/host-terminals.ts Outdated
Comment on lines +121 to +130
session.stream.pipeTo(writer).catch(() => {
// pipeTo rejection surfaces via writer.abort -> sink.error already.
})
this._boundStreams.set(session.id, {
dispose: () => {
if (sink && !sink.closed)
sink.close()
},
stream: session.stream,
})
Comment on lines +142 to +170
let controller: ReadableStreamDefaultController<string> | undefined
const stream = new ReadableStream<string>({
start(_controller) {
controller = _controller
},
})

function createChildProcess() {
const cp = exec(
executeOptions.command,
executeOptions.args || [],
{
nodeOptions: {
env: {
COLORS: 'true',
FORCE_COLOR: 'true',
...(executeOptions.env || {}),
},
cwd: executeOptions.cwd ?? process.cwd(),
stdio: 'pipe',
},
},
)

;(async () => {
for await (const chunk of cp) {
controller?.enqueue(chunk)
}
})()
Comment on lines +115 to +120
const docksSharedState = await context.rpc.sharedState.get('devframe:docks', { initialValue: [] })
const refreshDocks = debounce(() => {
docksSharedState.mutate(() => docks.values())
}, debounceMs)
docks.events.on('dock:entry:updated', refreshDocks)

Comment thread packages/hub/src/node/host-messages.ts
Comment thread packages/hub/src/node/host-commands.ts Outdated
@antfu antfu marked this pull request as draft May 22, 2026 03:17
@antfu antfu changed the title feat(hub): introduce @devframes/hub framework-neutral hub layer feat(hub)!: introduce @devframes/hub framework-neutral hub layer May 22, 2026
@antfu antfu requested a review from Copilot May 22, 2026 07:03
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 194 out of 210 changed files in this pull request and generated 9 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment thread vitest.config.ts
Comment on lines 1 to +7
import { defineConfig } from 'vitest/config'
import { alias } from './alias'

export default defineConfig({
resolve: {
alias,
},
Comment on lines +1 to +7
import { defineConfig } from 'vite'
import { alias } from '../../alias'
import demoDevframe from './src/devframe'
import { minimalViteDevframeHub } from './src/minimal-vite-devframe-hub'

export default defineConfig({
resolve: { alias },
Comment on lines +1 to +7
import { defineConfig } from 'vitest/config'
import { alias } from '../../alias'

export default defineConfig({
resolve: {
alias,
},
Comment on lines +1 to +5
import type { EventEmitter } from 'devframe/types'
import type { ChildProcess } from 'node:child_process'
import type { DevframeDockEntryIcon } from './docks'

export interface DevframeTerminalHost {
throw lastError
}

describe('devToolsTerminalHost stream lifecycle', () => {
import { describe, expect, it } from 'vitest'
import { DevframeMessagesHost } from '../host-messages'

describe('devToolsMessagesHost', () => {
} as unknown as HubNodeContext
}

describe('devToolsDockHost remote URL enrichment', () => {
import { describe, expect, it } from 'vitest'
import { DevframeCommandsHost } from '../host-commands'

describe('devToolsCommandsHost command id validation', () => {
Comment on lines +5 to +7
import { createHostContext, startHttpAndWs } from '../../../../devframe/src/node'
import { getInternalContext } from '../../../../devframe/src/node/internal'
import { createHubContext } from '../context'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants