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:
Generated
+111
@@ -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
@@ -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"] }
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user