refactor(core): extract application core into jcode-app-core crate (Phase A)

Move all non-presentation modules (113 modules / ~191K loc) out of the
monolithic root crate into a new physical crate, jcode-app-core, compiled
as a separate rustc unit. The root jcode crate becomes a thin facade
(pub use jcode_app_core::*) plus the presentation/entrypoint layer
(cli, tui, video_export, main).

Rationale: rustc type-checks a whole crate as one unit, so peak per-rustc
RSS is bounded by the largest crate. Splitting the 336K-loc root crate into
separate rustc processes is what actually lowers peak memory (the prior
SCC/DAG layering work was the prerequisite that made this a clean cut, since
no core module references crate::cli or crate::tui).

Measured: largest unit peak rustc VmHWM 3.18 GiB -> 2.643 GiB (app-core).
Further reductions come from sub-splitting app-core (Phase B) and extracting
jcode-tui (Phase C).

Mechanics:
- New crate crates/jcode-app-core (deps mirror root with paths rewritten;
  features default/jemalloc/jemalloc-prof/embeddings/pdf forwarded from root).
- git mv of 417 files preserving history; lib.rs aggregates pub mod decls
  and the moved CURRENT_SESSION_ID/get/set_current_session items.
- Promote cross-boundary items referenced by cli/tui from pub(crate) to pub
  (process_title, external_auth, provider selection/openrouter, server +
  session lifecycle re-exports, openai_request re-exports).
- Fix two escape-path includes now one dir deeper (macOS icns, openai test
  fixture) and import_tests ResumeTarget direct path.

Build: cargo check/build -p jcode --bin jcode exit 0.
This commit is contained in:
jeremy
2026-05-29 03:37:29 -07:00
parent 648049a719
commit 4dd91a9c6c
428 changed files with 459 additions and 140 deletions
Generated
+111
View File
@@ -3296,6 +3296,7 @@ dependencies = [
"image",
"jcode-agent-runtime",
"jcode-ambient-types",
"jcode-app-core",
"jcode-auth-types",
"jcode-azure-auth",
"jcode-background-types",
@@ -3392,6 +3393,116 @@ dependencies = [
"serde",
]
[[package]]
name = "jcode-app-core"
version = "0.1.0"
dependencies = [
"agentgrep",
"anyhow",
"arboard",
"async-trait",
"aws-config",
"aws-credential-types",
"aws-sdk-bedrock",
"aws-sdk-bedrockruntime",
"aws-sdk-sts",
"aws-smithy-types",
"aws-types",
"base64 0.22.1",
"bytes",
"chrono",
"clap",
"crossterm",
"dirs",
"flate2",
"futures",
"glob",
"global-hotkey",
"hex",
"ignore",
"image",
"jcode-agent-runtime",
"jcode-ambient-types",
"jcode-auth-types",
"jcode-azure-auth",
"jcode-background-types",
"jcode-batch-types",
"jcode-build-meta",
"jcode-build-support",
"jcode-compaction-core",
"jcode-config-types",
"jcode-core",
"jcode-embedding",
"jcode-gateway-types",
"jcode-import-core",
"jcode-logging",
"jcode-memory-types",
"jcode-message-types",
"jcode-notify-email",
"jcode-overnight-core",
"jcode-pdf",
"jcode-plan",
"jcode-protocol",
"jcode-provider-core",
"jcode-provider-gemini",
"jcode-provider-metadata",
"jcode-provider-openai",
"jcode-provider-openrouter",
"jcode-selfdev-types",
"jcode-session-types",
"jcode-side-panel-types",
"jcode-storage",
"jcode-swarm-core",
"jcode-task-types",
"jcode-terminal-image",
"jcode-terminal-launch",
"jcode-tool-core",
"jcode-tool-types",
"jcode-tui-account-picker",
"jcode-tui-core",
"jcode-tui-markdown",
"jcode-tui-mermaid",
"jcode-tui-messages",
"jcode-tui-render",
"jcode-tui-session-picker",
"jcode-tui-style",
"jcode-tui-tool-display",
"jcode-tui-usage-overlay",
"jcode-tui-workspace",
"jcode-update-core",
"jcode-usage-types",
"libc",
"open",
"proctitle",
"qrcode",
"rand 0.9.3",
"ratatui",
"regex",
"reqwest",
"rustls 0.23.37",
"serde",
"serde_json",
"serde_yaml",
"sha2 0.10.9",
"similar",
"tar",
"tempfile",
"thiserror 1.0.69",
"tikv-jemalloc-ctl",
"tikv-jemalloc-sys",
"tikv-jemallocator",
"tokio",
"tokio-stream",
"tokio-tungstenite",
"toml",
"unicode-width 0.2.0",
"url",
"urlencoding",
"uuid",
"walkdir",
"windows-sys 0.59.0",
]
[[package]]
name = "jcode-auth-types"
version = "0.1.0"
+9 -2
View File
@@ -194,6 +194,11 @@ jcode-background-types = { path = "crates/jcode-background-types" }
jcode-batch-types = { path = "crates/jcode-batch-types" }
jcode-build-support = { path = "crates/jcode-build-support" }
jcode-build-meta = { path = "crates/jcode-build-meta" }
# Application core: all non-presentation modules, compiled as a separate rustc
# unit. The root crate (cli + tui + bin) re-exports it via `pub use
# jcode_app_core::*`. default-features=false so the root feature set fully
# controls app-core's features (see [features]).
jcode-app-core = { path = "crates/jcode-app-core", default-features = false }
jcode-compaction-core = { path = "crates/jcode-compaction-core" }
jcode-config-types = { path = "crates/jcode-config-types" }
jcode-core = { path = "crates/jcode-core" }
@@ -238,15 +243,17 @@ jemalloc = [
"dep:tikv-jemalloc-sys",
"tikv-jemallocator/stats",
"tikv-jemalloc-ctl/stats",
"jcode-app-core/jemalloc",
]
jemalloc-prof = [
"jemalloc",
"tikv-jemallocator/profiling",
"tikv-jemalloc-ctl/profiling",
"jcode-app-core/jemalloc-prof",
]
embeddings = ["dep:jcode-embedding"]
embeddings = ["dep:jcode-embedding", "jcode-app-core/embeddings"]
mmdr-size-api = ["jcode-tui-mermaid/mmdr-size-api"]
pdf = ["dep:jcode-pdf"]
pdf = ["dep:jcode-pdf", "jcode-app-core/pdf"]
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System_Threading"] }
+169
View File
@@ -0,0 +1,169 @@
[package]
name = "jcode-app-core"
version = "0.1.0"
edition = "2024"
publish = false
# Application core for jcode: all non-presentation modules (server, agent,
# provider, auth, session, tool, config, etc.) extracted out of the monolithic
# root `jcode` crate so they compile as a separate rustc unit. The root `jcode`
# crate (cli + tui + bin) re-exports this crate's modules via `pub use
# jcode_app_core::*`, preserving every existing `crate::<module>` path.
[lib]
name = "jcode_app_core"
path = "src/lib.rs"
[dependencies]
# Memory allocator (reduces fragmentation for long-running server)
tikv-jemallocator = { version = "0.6", features = ["unprefixed_malloc_on_supported_platforms"], optional = true }
tikv-jemalloc-ctl = { version = "0.6", optional = true }
tikv-jemalloc-sys = { version = "0.6", optional = true }
# Async runtime
tokio = { version = "1", features = ["fs", "io-std", "io-util", "macros", "net", "process", "rt-multi-thread", "signal", "sync", "time"] }
futures = "0.3"
async-trait = "0.1"
# HTTP client
reqwest = { version = "0.12", features = ["json", "stream", "blocking"] }
rustls = { version = "0.23", default-features = false, features = ["aws_lc_rs"] }
tokio-tungstenite = { version = "0.24", default-features = false, features = ["connect", "rustls-tls-native-roots"] }
# Serialization
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["raw_value"] }
serde_yaml = "0.9"
toml = "0.8"
# CLI
clap = { version = "4", features = ["derive"] }
# File operations
glob = "0.3"
ignore = "0.4" # gitignore-aware file walking
walkdir = "2"
similar = "2" # diffing for edits
# Utilities
dirs = "5" # home directory
anyhow = "1"
thiserror = "1"
libc = "0.2" # Unix system calls (flock)
chrono = { version = "0.4", features = ["serde"] }
regex = "1"
urlencoding = "2" # URL encoding for web search
uuid = { version = "1", features = ["v4", "v5"] }
proctitle = "0.1"
# Embeddings (local inference) - behind feature flag (163 crates, slow to compile)
jcode-embedding = { path = "../jcode-embedding", optional = true }
jcode-gateway-types = { path = "../jcode-gateway-types" }
jcode-import-core = { path = "../jcode-import-core" }
jcode-logging = { path = "../jcode-logging" }
# OAuth
base64 = "0.22"
sha2 = "0.10"
rand = "0.9.3"
hex = "0.4"
url = "2"
open = "5" # Open URLs in browser
jcode-auth-types = { path = "../jcode-auth-types" }
jcode-azure-auth = { path = "../jcode-azure-auth" }
jcode-agent-runtime = { path = "../jcode-agent-runtime" }
jcode-ambient-types = { path = "../jcode-ambient-types" }
jcode-notify-email = { path = "../jcode-notify-email" }
jcode-provider-metadata = { path = "../jcode-provider-metadata" }
jcode-provider-core = { path = "../jcode-provider-core" }
jcode-provider-openai = { path = "../jcode-provider-openai" }
jcode-provider-openrouter = { path = "../jcode-provider-openrouter" }
jcode-provider-gemini = { path = "../jcode-provider-gemini" }
jcode-tui-markdown = { path = "../jcode-tui-markdown" }
jcode-tui-messages = { path = "../jcode-tui-messages" }
jcode-tui-core = { path = "../jcode-tui-core" }
jcode-tui-mermaid = { path = "../jcode-tui-mermaid" }
jcode-tui-account-picker = { path = "../jcode-tui-account-picker" }
jcode-tui-render = { path = "../jcode-tui-render" }
jcode-tui-session-picker = { path = "../jcode-tui-session-picker", features = ["serde"] }
jcode-tui-style = { path = "../jcode-tui-style" }
jcode-tui-tool-display = { path = "../jcode-tui-tool-display" }
jcode-tui-usage-overlay = { path = "../jcode-tui-usage-overlay" }
jcode-update-core = { path = "../jcode-update-core" }
jcode-terminal-launch = { path = "../jcode-terminal-launch" }
jcode-terminal-image = { path = "../jcode-terminal-image" }
jcode-tui-workspace = { path = "../jcode-tui-workspace" }
jcode-usage-types = { path = "../jcode-usage-types" }
# Streaming
tokio-stream = "0.1"
bytes = "1"
# TUI
ratatui = "0.30"
crossterm = { version = "0.29", features = ["event-stream"] }
arboard = "3" # Clipboard support
image = { version = "0.25", default-features = false, features = ["png", "jpeg"] } # Only PNG/JPEG (skip avif/rav1e, exr, gif, tiff, etc)
# Markdown & syntax highlighting
unicode-width = "0.2" # Unicode character display width
# PDF parsing (behind feature flag)
jcode-pdf = { path = "../jcode-pdf", optional = true }
jcode-background-types = { path = "../jcode-background-types" }
jcode-batch-types = { path = "../jcode-batch-types" }
jcode-build-support = { path = "../jcode-build-support" }
jcode-build-meta = { path = "../jcode-build-meta" }
jcode-compaction-core = { path = "../jcode-compaction-core" }
jcode-config-types = { path = "../jcode-config-types" }
jcode-core = { path = "../jcode-core" }
jcode-memory-types = { path = "../jcode-memory-types" }
jcode-message-types = { path = "../jcode-message-types" }
jcode-overnight-core = { path = "../jcode-overnight-core" }
jcode-plan = { path = "../jcode-plan" }
jcode-swarm-core = { path = "../jcode-swarm-core" }
jcode-protocol = { path = "../jcode-protocol" }
jcode-selfdev-types = { path = "../jcode-selfdev-types" }
jcode-session-types = { path = "../jcode-session-types" }
jcode-storage = { path = "../jcode-storage" }
jcode-task-types = { path = "../jcode-task-types" }
jcode-tool-core = { path = "../jcode-tool-core" }
jcode-tool-types = { path = "../jcode-tool-types" }
jcode-side-panel-types = { path = "../jcode-side-panel-types" }
# Archive extraction (for auto-update)
flate2 = "1"
tar = "0.4"
tempfile = "3"
agentgrep = { git = "https://github.com/1jehuang/agentgrep.git", tag = "v0.1.2" }
qrcode = { version = "0.14.1", default-features = false }
aws-config = "1.8.16"
aws-credential-types = "1.2.14"
aws-sdk-bedrockruntime = "1.130.0"
aws-types = "1.3.15"
aws-smithy-types = "1.4.7"
aws-sdk-bedrock = "1.141.0"
aws-sdk-sts = "1.103.0"
[features]
default = ["pdf", "embeddings"]
jemalloc = [
"dep:tikv-jemallocator",
"dep:tikv-jemalloc-ctl",
"dep:tikv-jemalloc-sys",
"tikv-jemallocator/stats",
"tikv-jemalloc-ctl/stats",
]
jemalloc-prof = [
"jemalloc",
"tikv-jemallocator/profiling",
"tikv-jemalloc-ctl/profiling",
]
embeddings = ["dep:jcode-embedding"]
pdf = ["dep:jcode-pdf"]
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System_Threading"] }
[target.'cfg(target_os = "macos")'.dependencies]
global-hotkey = "0.7"
@@ -12,13 +12,13 @@ use std::io::{self, IsTerminal, Write};
use crate::auth;
pub(crate) fn can_prompt_for_external_auth() -> bool {
pub fn can_prompt_for_external_auth() -> bool {
std::io::stdin().is_terminal()
&& std::io::stderr().is_terminal()
&& std::env::var("JCODE_NON_INTERACTIVE").is_err()
}
pub(crate) fn external_auth_blocked_message(
pub fn external_auth_blocked_message(
provider_name: &str,
source_name: &str,
path: &std::path::Path,
@@ -33,7 +33,7 @@ pub(crate) fn external_auth_blocked_message(
)
}
pub(crate) fn prompt_to_trust_external_auth(
pub fn prompt_to_trust_external_auth(
provider_name: &str,
source_name: &str,
path: &std::path::Path,
@@ -69,7 +69,7 @@ enum ExternalAuthReviewAction {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct ExternalAuthReviewCandidate {
pub struct ExternalAuthReviewCandidate {
pub(crate) provider_summary: String,
pub(crate) source_name: String,
pub(crate) path: std::path::PathBuf,
@@ -77,13 +77,13 @@ pub(crate) struct ExternalAuthReviewCandidate {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct ExternalAuthAutoImportOutcome {
pub struct ExternalAuthAutoImportOutcome {
pub imported: usize,
pub messages: Vec<String>,
}
impl ExternalAuthAutoImportOutcome {
pub(crate) fn render_markdown(&self) -> String {
pub fn render_markdown(&self) -> String {
if self.messages.is_empty() {
return "No external auth sources were imported.".to_string();
}
@@ -96,7 +96,7 @@ impl ExternalAuthAutoImportOutcome {
}
}
pub(crate) fn pending_external_auth_review_candidates() -> Result<Vec<ExternalAuthReviewCandidate>>
pub fn pending_external_auth_review_candidates() -> Result<Vec<ExternalAuthReviewCandidate>>
{
let mut candidates = Vec::new();
@@ -169,7 +169,7 @@ pub(crate) fn pending_external_auth_review_candidates() -> Result<Vec<ExternalAu
Ok(candidates)
}
pub(crate) fn parse_external_auth_review_selection(
pub fn parse_external_auth_review_selection(
input: &str,
count: usize,
) -> Result<Vec<usize>> {
@@ -411,7 +411,7 @@ async fn validate_external_auth_review_candidate(
}
}
pub(crate) async fn maybe_run_external_auth_auto_import_flow() -> Result<Option<usize>> {
pub async fn maybe_run_external_auth_auto_import_flow() -> Result<Option<usize>> {
if !can_prompt_for_external_auth() {
return Ok(None);
}
@@ -430,7 +430,7 @@ pub(crate) async fn maybe_run_external_auth_auto_import_flow() -> Result<Option<
Ok(Some(outcome.imported))
}
pub(crate) fn format_external_auth_review_candidates_markdown(
pub fn format_external_auth_review_candidates_markdown(
candidates: &[ExternalAuthReviewCandidate],
) -> String {
let mut message = String::from(
@@ -448,7 +448,7 @@ pub(crate) fn format_external_auth_review_candidates_markdown(
message
}
pub(crate) async fn run_external_auth_auto_import_candidates(
pub async fn run_external_auth_auto_import_candidates(
candidates: &[ExternalAuthReviewCandidate],
selected: &[usize],
) -> Result<ExternalAuthAutoImportOutcome> {

Some files were not shown because too many files have changed in this diff Show More