Files
wehub-resource-sync a789495a98
CI / Quality Guardrails (push) Waiting to run
CI / Build & Test (macos-latest) (push) Waiting to run
CI / Build & Test (ubuntu-latest) (push) Waiting to run
CI / Build & Test (windows-latest) (push) Waiting to run
CI / Format (push) Waiting to run
CI / PowerShell Syntax (push) Waiting to run
CI / Windows Cross-Target Check (Linux) (push) Waiting to run
FreeBSD Smoke / FreeBSD Smoke (x86_64) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:34 +08:00

138 lines
5.8 KiB
Markdown

# Windows Support Architecture
This document describes how jcode achieves cross-platform support for Linux, macOS, and Windows.
## Status
- **Transport layer**: Implemented (`src/transport/`)
- **Platform module**: Implemented (`src/platform.rs`)
- **Windows transport**: Implemented but untested (`src/transport/windows.rs`)
- **Windows platform**: Implemented (`src/platform.rs` has `#[cfg(windows)]` branches)
- **Windows CI**: Not yet set up
## Design Principle
**Zero cost on Unix.** The abstraction layer uses `#[cfg]` compile-time gates and type aliases so that Linux and macOS code paths compile to the exact same binary as before. Windows gets its own implementations behind `#[cfg(windows)]`. No traits, no dynamic dispatch, no runtime branching.
## Install Paths
Current Windows install paths from `scripts/install.ps1`:
- Launcher: `%LOCALAPPDATA%\\jcode\\bin\\jcode.exe`
- Stable channel binary: `%LOCALAPPDATA%\\jcode\\builds\\stable\\jcode.exe`
- Immutable versioned binaries: `%LOCALAPPDATA%\\jcode\\builds\\versions\\<version>\\jcode.exe`
Unlike the current Unix self-dev/local-build flow, the PowerShell installer currently installs the stable channel rather than a separate `current` channel.
## Transport Layer (`src/transport/`)
The transport layer abstracts IPC (Inter-Process Communication). On Unix, jcode uses Unix domain sockets. On Windows, jcode uses named pipes.
### Module Structure
```
src/transport/
mod.rs - conditional re-exports (cfg-gated)
unix.rs - type aliases wrapping tokio Unix sockets (zero-cost)
windows.rs - named pipe Listener/Stream with split support
```
### Unix (Linux + macOS)
Unix transport is a thin re-export of existing types:
```rust
pub use tokio::net::UnixListener as Listener;
pub use tokio::net::UnixStream as Stream;
pub use tokio::net::unix::OwnedWriteHalf as WriteHalf;
pub use tokio::net::unix::OwnedReadHalf as ReadHalf;
pub use std::os::unix::net::UnixStream as SyncStream;
```
The compiled binary is byte-for-byte identical to what it was before the abstraction.
### Windows
Windows transport provides custom types wrapping `tokio::net::windows::named_pipe`:
- **`Listener`**: Wraps `NamedPipeServer` with an accept loop that creates new pipe instances for each connection (named pipes are single-client, so a new instance is created after each accept)
- **`Stream`**: Enum over `NamedPipeServer` (accepted) or `NamedPipeClient` (connected), implementing `AsyncRead + AsyncWrite`
- **`ReadHalf` / `WriteHalf`**: Created via `stream.into_split()` using `Arc<Mutex<Stream>>` since named pipes don't support native kernel-level splitting
- **`SyncStream`**: Opens the named pipe as a regular file for blocking I/O
Socket paths are converted to pipe names: `/run/user/1000/jcode.sock` becomes `\\.\pipe\jcode`.
### API Surface
Both platforms export the same interface:
| Export | Unix | Windows |
|--------|------|---------|
| `Listener` | `tokio::net::UnixListener` | Custom struct wrapping `NamedPipeServer` |
| `Stream` | `tokio::net::UnixStream` | Enum over `NamedPipeServer`/`NamedPipeClient` |
| `ReadHalf` | `tokio::net::unix::OwnedReadHalf` | `Arc<Mutex<Stream>>` wrapper |
| `WriteHalf` | `tokio::net::unix::OwnedWriteHalf` | `Arc<Mutex<Stream>>` wrapper |
| `SyncStream` | `std::os::unix::net::UnixStream` | `std::fs::File` wrapper |
## Platform Module (`src/platform.rs`)
Centralizes all non-IPC OS-specific operations:
| Function | Unix | Windows |
|----------|------|---------|
| `symlink_or_copy(src, dst)` | `std::os::unix::fs::symlink()` | Try `symlink_file/dir`, fall back to copy |
| `atomic_symlink_swap(src, dst, temp)` | Create temp symlink + rename | Remove + copy (best effort) |
| `set_permissions_owner_only(path)` | `chmod 600` | No-op |
| `set_permissions_executable(path)` | `chmod 755` | No-op |
| `is_process_running(pid)` | `kill(pid, 0)` | Returns `true` (stub) |
| `replace_process(cmd)` | `exec()` (replaces process) | `spawn()` + `exit()` |
## Files Migrated
All OS-specific code has been moved out of application files into the transport and platform modules:
| File | What was migrated |
|------|------------------|
| `src/server.rs` | `UnixListener`, `UnixStream`, `OwnedReadHalf`, `OwnedWriteHalf` |
| `src/tui/backend.rs` | `UnixStream`, `OwnedWriteHalf`, `OwnedReadHalf` |
| `src/tui/client.rs` | `UnixStream`, `OwnedWriteHalf` |
| `src/tui/app.rs` | `UnixListener`, `OwnedWriteHalf`, file permissions |
| `src/tool/communicate.rs` | `std::os::unix::net::UnixStream` |
| `src/tool/debug_socket.rs` | `tokio::net::UnixStream` |
| `src/main.rs` | `UnixStream` (health checks), all `exec()` calls, file permissions |
| `src/build.rs` | Symlinks, executable permissions |
| `src/update.rs` | Symlinks, permissions, atomic swap |
| `src/auth/oauth.rs` | Credential file permissions |
| `src/skill.rs` | Symlink creation |
| `src/video_export.rs` | Frame symlinks |
| `src/ambient.rs` | Process liveness check |
| `src/registry.rs` | Process liveness check |
| `src/session.rs` | Process liveness check |
## Dependencies
```toml
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System_Threading"] }
```
The `tokio` dependency already includes named pipe support on Windows (part of `features = ["full"]`).
## What Doesn't Change
The vast majority of the codebase is platform-agnostic:
- All provider code (HTTP-based)
- All tool implementations (except bash tool's shell selection)
- TUI rendering (crossterm + ratatui already cross-platform)
- Agent logic, memory, sessions, config
- MCP client/server protocol
- JSON serialization, protocol handling
## Remaining Work
1. **Windows CI** - Add GitHub Actions Windows runner, test compilation and basic IPC
2. **Shell tool** - Detect platform and use `cmd.exe` or `pwsh.exe` on Windows
3. **Self-update** - Handle Windows exe replacement (can't overwrite running binary)
4. **Testing** - Run full test suite on Windows