The casement crate was depended on through a sibling-repo path (`../../../winit`) that only existed on the maintainer's machine, so CI couldn't load the workspace manifest and every Rust Check job died with "failed to read winit/Cargo.toml". Vendoring it as a real submodule under `vendor/casement` (matching the `vendor/jian` pattern, picked up by CI's `submodules: recursive` checkout) closes that gap. The renamed GitHub repo `ZSeven-W/casement` (was `ZSeven-W/winit`) tracks the `op-file-open` branch — `feat(macos): drain_opened_file_urls` + the package rename landed there as commit 5877fa83. - `.gitmodules`: add vendor/casement. - Root Cargo.toml: exclude vendor/casement from the workspace glob (it's its own workspace). - op-host-native + op-host-desktop: path = "../../vendor/casement".
199 lines
9.6 KiB
TOML
199 lines
9.6 KiB
TOML
[package]
|
|
name = "op-host-desktop"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
description = "OpenPencil desktop host — winit + skia-safe binary that drives the Rust editor on macOS / Linux / Windows"
|
|
|
|
# The shipped executable keeps the stable `openpencil-desktop` name so
|
|
# release artifacts + external CLI integrations are unaffected by the
|
|
# Phase 7.3 crate rename.
|
|
[[bin]]
|
|
name = "openpencil-desktop"
|
|
path = "src/main.rs"
|
|
|
|
# File-association metadata for `cargo-bundle` (`cargo bundle`). This
|
|
# declares OpenPencil as the OS-level handler for `.op` / `.pen`
|
|
# documents: macOS writes `CFBundleDocumentTypes` into the `.app`
|
|
# Info.plist, Windows registers the extensions, Linux emits a
|
|
# `.desktop` MimeType entry. Once the association is registered the
|
|
# OS launches this binary with the document path in argv, which
|
|
# `main.rs` opens at startup (see `src/main.rs` argv handling).
|
|
[package.metadata.bundle]
|
|
name = "OpenPencil"
|
|
identifier = "com.zseven-w.openpencil"
|
|
|
|
[[package.metadata.bundle.file_associations]]
|
|
ext = "op"
|
|
name = "OpenPencil Document"
|
|
role = "Editor"
|
|
|
|
[[package.metadata.bundle.file_associations]]
|
|
ext = "pen"
|
|
name = "OpenPencil Document"
|
|
role = "Editor"
|
|
|
|
# Desktop-only binary. The op-host-native lib is multi-platform (mobile
|
|
# stubs land in Step 1f) but the runner here pulls winit + glutin via
|
|
# op-host-native's desktop dep set, so the whole crate is gated to
|
|
# macos / linux / windows.
|
|
[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dependencies]
|
|
# Phase 7.3 reorg: openpencil-shell-core dissolved — widget facade /
|
|
# render-backend / layout scene paths resolve through op-editor-ui.
|
|
op-editor-ui = { path = "../op-editor-ui" }
|
|
op-host-native = { path = "../op-host-native", version = "0.1.0" }
|
|
# Phase 5 strangler reorg: the stdio MCP server (`mcp_serve.rs`) drives an
|
|
# `op_editor_core::EditorState` (canonical `.op` document) instead of the
|
|
# old shell-core `Document`.
|
|
op-editor-core = { path = "../op-editor-core" }
|
|
# Locale tables — git dialog strings go through `op_i18n::translate`
|
|
# so they are localized like the rest of the chrome.
|
|
op-i18n = { path = "../op-i18n" }
|
|
# Phase 7 strangler reorg: the MCP tool registry + JSON-RPC stdio layer
|
|
# (`mcp.rs` + `mcp/*`) was extracted out of the dissolved shell-core into the
|
|
# op-mcp crate; `mcp_serve.rs` registers tools through `op_mcp::*`.
|
|
op-mcp = { path = "../op-mcp" }
|
|
# Phase 7 strangler reorg: the transport-free AI chat data shapes
|
|
# (`ChatProvider` trait + model catalog + agent-settings state) were
|
|
# extracted into op-ai; the `src/chat_*.rs` real transports + the
|
|
# model-discovery path import them through `op_ai::*`.
|
|
op-ai = { path = "../op-ai" }
|
|
# AI skill engine — the BuiltIn agent provider resolves
|
|
# generation-phase prompt skills through it (`chat_runtime.rs`).
|
|
op-ai-skills = { path = "../op-ai-skills" }
|
|
# ACP client — the `AcpProvider` chat backend (`chat_acp.rs`) drives
|
|
# third-party Agent Client Protocol agents through it.
|
|
op-acp = { path = "../op-acp" }
|
|
# Canonical `.op` (PenDocument) → shell `Document` loader / adapter.
|
|
# Extracted out of this binary into a shared library crate so library
|
|
# crates (op-host-native) can reuse the conversion;
|
|
# `persistence.rs` keeps only the desktop-only `rfd` Save/Open + error
|
|
# dialogs.
|
|
op-pen-loader = { path = "../op-pen-loader" }
|
|
# In-app Git — `git_session.rs` binds an `op_git::GitRepo` to the
|
|
# currently-open document so the Git panel can show branch / status
|
|
# / history and drive commits.
|
|
op-git = { path = "../op-git" }
|
|
# Structured node-level 3-way merge for `.op` documents — the in-app
|
|
# Git merge orchestrator feeds it the conflicting file's three index
|
|
# stages so a merge conflict resolves per PenNode, not as raw text.
|
|
op-opmerge = { path = "../op-opmerge" }
|
|
# Canonical `.op` / `.pen` schema — all persistence + interop goes
|
|
# through `PenDocument` rather than the desktop's private DocPayload.
|
|
# Falling back to the schema's `load_str` lets us open files saved by
|
|
# the TS editor, Jian apps, or any tool that emits the canonical form.
|
|
jian-ops-schema = { path = "../../vendor/jian/crates/jian-ops-schema" }
|
|
# jian-core ships the taffy-backed `LayoutEngine` that is the
|
|
# canonical flex solver for `.op` files. We reuse it (instead of
|
|
# rolling our own) so layout stays bit-identical with what the TS
|
|
# editor + future jian native runtime produce.
|
|
jian-core = { path = "../../vendor/jian/crates/jian-core" }
|
|
# jian-skia ships `SkiaMeasure` — a `MeasureBackend` impl that
|
|
# defers to skia's paragraph shaper. Wiring it into the layout
|
|
# engine replaces the ~10% character-count heuristic with real
|
|
# glyph advances so text frames sized to `fit_content` agree
|
|
# with what the canvas painter draws (TS parity for line-wrap +
|
|
# fixed-width text growth).
|
|
jian-skia = { path = "../../vendor/jian/crates/jian-skia", features = ["textlayout"] }
|
|
skia-safe = { version = "0.97.0", default-features = false, features = [
|
|
"binary-cache",
|
|
"textlayout",
|
|
"gl",
|
|
"pdf",
|
|
] }
|
|
# `casement` — ZSeven-W's winit fork (vendored as a submodule under
|
|
# `vendor/casement`). It adds `winit::platform::macos::drain_opened_file_urls`,
|
|
# the macOS open-documents Apple-event hook upstream winit lacks. The
|
|
# `package` key keeps the `winit` import name, so all `use winit::…`
|
|
# stays unchanged.
|
|
winit = { package = "casement", path = "../../vendor/casement", default-features = false, features = [
|
|
"x11",
|
|
"wayland",
|
|
"wayland-csd-adwaita",
|
|
"rwh_06",
|
|
] }
|
|
# Document Save / Open (.pen / .op). Serialization lives in
|
|
# `src/persistence.rs` as a hand-rolled DTO so shell-core stays
|
|
# serde-free (Color / Rect / Point2D come from glam + jian-core
|
|
# which would otherwise need wrapper types). rfd pops the native
|
|
# Save/Open file dialogs so the user picks the path.
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
rfd = "0.14"
|
|
# Base64-encodes chat image attachments for providers that take
|
|
# inline image content blocks (Claude SDK) or a base64 body field
|
|
# (HTTP-server transport). Same pure-Rust crate op-figma uses.
|
|
base64 = "0.22"
|
|
# 2D affine transforms used by PNG export's bounds walker so nested
|
|
# rotated containers don't clip their children. Pinned to the same
|
|
# version shell-core uses for `Point2D = glam::Vec2`.
|
|
glam = { version = "0.29", default-features = false, features = ["std"] }
|
|
# Resolves the platform-specific user-config dir for the auto-saved
|
|
# settings file (TS parity with `agent-settings-store` localStorage):
|
|
# macOS → ~/Library/Application Support/openpencil/settings.json
|
|
# Linux → ~/.config/openpencil/settings.json
|
|
# Windows → %APPDATA%/openpencil/settings.json
|
|
dirs = "5"
|
|
# Cross-product Rust agent runtime — provides `QueryEngine` + the
|
|
# generic `Provider` trait + streaming `Event`s. Vendored as the
|
|
# `vendor/agent` git submodule (the agent-rs repo) and referenced by
|
|
# relative path so the BuiltIn ChatProvider in `src/chat_runtime.rs`
|
|
# can drive a real LLM turn. The submodule keeps CI self-contained.
|
|
#
|
|
# Compiled with NO default features today — the `anthropic` feature
|
|
# would drag in reqwest's TLS stack (rustls / icu / idna) which needs
|
|
# rustc ≥ 1.86 while this workspace pins 1.85. The BuiltIn bridge ships
|
|
# the trait + the engine wiring + `from_provider`; concrete
|
|
# Provider impls (Anthropic / OpenAI-compat / Ollama) flip on once the
|
|
# workspace rust-toolchain bumps.
|
|
agent = { path = "../../vendor/agent/crates/agent", default-features = false }
|
|
# Forked from bartolli/anthropic-agent-sdk — lives under
|
|
# `vendor/anthropic-agent-sdk/` so OP owns the source and can diverge
|
|
# from upstream. Provides the Claude Code CLI subprocess transport +
|
|
# stream-json message parser that `src/chat_claude.rs` wraps as a
|
|
# `ChatProvider`. Default features (no rmcp) keep the dep set tight.
|
|
anthropic-agent-sdk = { path = "../../vendor/anthropic-agent-sdk" }
|
|
# Official GitHub Copilot CLI SDK (github/copilot-sdk). Replaces
|
|
# the former in-workspace fork. Drives the Copilot chat bridge in
|
|
# `src/chat_copilot.rs` over the CLI's `--server --stdio` JSON-RPC
|
|
# transport. Requires Rust 1.94 / edition 2024 (the workspace
|
|
# toolchain was bumped for it).
|
|
github-copilot-sdk = "0.1"
|
|
async-trait = "0.1"
|
|
# HTTP client for the Codex / OpenCode bridges. They run as local
|
|
# HTTP servers (spawned via `<bin> serve`) and we POST JSON requests
|
|
# to them — `reqwest` is already in the dep graph via
|
|
# anthropic-agent-sdk so adding it here costs no new deps.
|
|
# Default-features-off + rustls-tls keeps the TLS choice consistent
|
|
# with the SDK's. We still talk to 127.0.0.1, but rustls is a
|
|
# small price for not having two parallel TLS stacks.
|
|
reqwest = { version = "0.12", default-features = false, features = [
|
|
"rustls-tls",
|
|
"json",
|
|
"stream",
|
|
] }
|
|
# Async runtime — agent-rs is async; the BuiltIn ChatProvider impl
|
|
# bridges its `EventStream` into the sync `Iterator<ChatDelta>`
|
|
# shape via a tokio task + std::sync::mpsc channel.
|
|
tokio = { version = "1", default-features = false, features = [
|
|
"rt-multi-thread",
|
|
"macros",
|
|
"sync",
|
|
"io-util",
|
|
"process",
|
|
"net",
|
|
"time",
|
|
] }
|
|
futures = { version = "0.3", default-features = false, features = ["std"] }
|
|
|
|
# Native menu bar (`src/menu.rs`). winit owns the window but has no
|
|
# menu primitive, so `muda` builds the NSMenu / Win32 menu and routes
|
|
# selections through its global event channel. Gated to macOS /
|
|
# Windows: `muda`'s Linux backend needs a GTK window, but this
|
|
# binary's winit is built for the x11 / wayland backends (no GTK), so
|
|
# Linux falls back to the in-canvas File menu. `default-features =
|
|
# false` drops the Linux-only `gtk` / `libxdo` feature deps.
|
|
[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies]
|
|
muda = { version = "0.17", default-features = false }
|