Compare commits

..

No commits in common. "c185261909f20abfae320b688e816bf6f67c131d" and "f35a365d830a5a49546acec03a2b00a904c98b05" have entirely different histories.

10 changed files with 213 additions and 1219 deletions

View file

@ -145,7 +145,7 @@ jobs:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Download all artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
path: artifacts

241
Cargo.lock generated
View file

@ -47,7 +47,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures 0.2.17",
"cpufeatures",
]
[[package]]
@ -304,7 +304,7 @@ dependencies = [
"futures-lite",
"parking",
"polling",
"rustix",
"rustix 1.1.3",
"slab",
"windows-sys 0.61.2",
]
@ -475,12 +475,6 @@ version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "basic-udev"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a45f9771ced8a774de5e5ebffbe520f52e3943bf5a9a6baa3a5d14a5de1afe6"
[[package]]
name = "bincode"
version = "2.0.1"
@ -565,7 +559,7 @@ dependencies = [
"cc",
"cfg-if",
"constant_time_eq",
"cpufeatures 0.2.17",
"cpufeatures",
]
[[package]]
@ -701,18 +695,7 @@ checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures 0.2.17",
]
[[package]]
name = "chacha20"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
"rand_core 0.10.0",
"cpufeatures",
]
[[package]]
@ -722,7 +705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
"chacha20 0.9.1",
"chacha20",
"cipher",
"poly1305",
"zeroize",
@ -964,6 +947,16 @@ dependencies = [
"url",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation"
version = "0.10.1"
@ -998,15 +991,6 @@ dependencies = [
"libc",
]
[[package]]
name = "cpufeatures"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.5.0"
@ -1151,7 +1135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"cpufeatures",
"curve25519-dalek-derive",
"digest",
"fiat-crypto",
@ -2005,7 +1989,6 @@ dependencies = [
"cfg-if",
"libc",
"r-efi",
"rand_core 0.10.0",
"wasip2",
"wasip3",
]
@ -2198,6 +2181,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hermit-abi"
version = "0.5.2"
@ -2216,12 +2205,12 @@ version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "565dd4c730b8f8b2c0fb36df6be12e5470ae10895ddcc4e9dcfbfb495de202b0"
dependencies = [
"basic-udev",
"cc",
"cfg-if",
"libc",
"nix 0.27.1",
"pkg-config",
"udev",
"windows-sys 0.48.0",
]
@ -2718,6 +2707,17 @@ dependencies = [
"mach2 0.5.0",
]
[[package]]
name = "io-lifetimes"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi 0.3.9",
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "ipnet"
version = "2.11.0"
@ -2926,6 +2926,22 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libudev-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
dependencies = [
"libc",
"pkg-config",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "linux-raw-sys"
version = "0.11.0"
@ -3669,24 +3685,43 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
dependencies = [
"hermit-abi",
"hermit-abi 0.5.2",
"libc",
]
[[package]]
name = "nusb"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f861541f15de120eae5982923d073bfc0c1a65466561988c82d6e197734c19e"
dependencies = [
"atomic-waker",
"core-foundation 0.9.4",
"core-foundation-sys",
"futures-core",
"io-kit-sys 0.4.1",
"libc",
"log",
"once_cell",
"rustix 0.38.44",
"slab",
"windows-sys 0.48.0",
]
[[package]]
name = "nusb"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5750d884c774a2862b0049b0318aea27cecc9e873485540af5ed8ab8841247da"
dependencies = [
"core-foundation",
"core-foundation 0.10.1",
"core-foundation-sys",
"futures-core",
"io-kit-sys 0.5.0",
"linux-raw-sys",
"linux-raw-sys 0.11.0",
"log",
"once_cell",
"rustix",
"rustix 1.1.3",
"slab",
"windows-sys 0.61.2",
]
@ -4126,9 +4161,9 @@ checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"hermit-abi 0.5.2",
"pin-project-lite",
"rustix",
"rustix 1.1.3",
"windows-sys 0.61.2",
]
@ -4138,7 +4173,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures 0.2.17",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
@ -4150,7 +4185,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
@ -4259,9 +4294,9 @@ dependencies = [
[[package]]
name = "probe-rs"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee50102aaa214117fc4fbe1311077835f0f4faa71e4a769bf65f955cc020ee34"
checksum = "7ee27329ac37fa02b194c62a4e3c1aa053739884ea7bcf861249866d3bf7de00"
dependencies = [
"anyhow",
"async-io",
@ -4278,8 +4313,8 @@ dependencies = [
"ihex",
"itertools 0.14.0",
"jep106",
"nusb",
"object 0.38.1",
"nusb 0.1.14",
"object 0.37.3",
"parking_lot",
"probe-rs-target",
"rmp-serde",
@ -4295,9 +4330,9 @@ dependencies = [
[[package]]
name = "probe-rs-target"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "031bed1313b45d93dae4ca8f0fee098530c6632e4ebd9e2769d5a49cdef273d3"
checksum = "2239aca5dc62c68ca6d8ff0051fe617cb8363b803380fbc60567e67c82b474df"
dependencies = [
"base64",
"indexmap",
@ -4313,7 +4348,7 @@ version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
dependencies = [
"toml_edit",
"toml_edit 0.23.10+spec-1.0.0",
]
[[package]]
@ -4583,17 +4618,6 @@ dependencies = [
"rand_core 0.9.5",
]
[[package]]
name = "rand"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8"
dependencies = [
"chacha20 0.10.0",
"getrandom 0.4.1",
"rand_core 0.10.0",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
@ -5057,6 +5081,19 @@ dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.11.0",
"errno",
"libc",
"linux-raw-sys 0.4.15",
"windows-sys 0.59.0",
]
[[package]]
name = "rustix"
version = "1.1.3"
@ -5066,7 +5103,7 @@ dependencies = [
"bitflags 2.11.0",
"errno",
"libc",
"linux-raw-sys",
"linux-raw-sys 0.11.0",
"windows-sys 0.61.2",
]
@ -5214,7 +5251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38"
dependencies = [
"bitflags 2.11.0",
"core-foundation",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
"security-framework-sys",
@ -5359,6 +5396,15 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
"serde",
]
[[package]]
name = "serde_spanned"
version = "1.0.4"
@ -5416,7 +5462,7 @@ checksum = "2acaf3f973e8616d7ceac415f53fc60e190b2a686fbcf8d27d0256c741c5007b"
dependencies = [
"bitflags 2.11.0",
"cfg-if",
"core-foundation",
"core-foundation 0.10.1",
"core-foundation-sys",
"io-kit-sys 0.4.1",
"mach2 0.4.3",
@ -5433,7 +5479,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"cpufeatures",
"digest",
]
@ -5444,7 +5490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"cpufeatures",
"digest",
]
@ -5713,7 +5759,7 @@ dependencies = [
"fastrand",
"getrandom 0.4.1",
"once_cell",
"rustix",
"rustix 1.1.3",
"windows-sys 0.61.2",
]
@ -6002,6 +6048,18 @@ dependencies = [
"tokio-util",
]
[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned 0.6.9",
"toml_datetime 0.6.11",
"toml_edit 0.22.27",
]
[[package]]
name = "toml"
version = "0.9.12+spec-1.1.0"
@ -6009,7 +6067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
dependencies = [
"serde_core",
"serde_spanned",
"serde_spanned 1.0.4",
"toml_datetime 0.7.5+spec-1.1.0",
"toml_parser",
"winnow 0.7.14",
@ -6023,13 +6081,22 @@ checksum = "bbe30f93627849fa362d4a602212d41bb237dc2bd0f8ba0b2ce785012e124220"
dependencies = [
"indexmap",
"serde_core",
"serde_spanned",
"serde_spanned 1.0.4",
"toml_datetime 1.0.0+spec-1.1.0",
"toml_parser",
"toml_writer",
"winnow 0.7.14",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_datetime"
version = "0.7.5+spec-1.1.0"
@ -6048,6 +6115,20 @@ dependencies = [
"serde_core",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned 0.6.9",
"toml_datetime 0.6.11",
"toml_write",
"winnow 0.7.14",
]
[[package]]
name = "toml_edit"
version = "0.23.10+spec-1.0.0"
@ -6069,6 +6150,12 @@ dependencies = [
"winnow 0.7.14",
]
[[package]]
name = "toml_write"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "toml_writer"
version = "1.0.6+spec-1.1.0"
@ -6305,6 +6392,18 @@ version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36a83ea2b3c704935a01b4642946aadd445cea40b10935e3f8bd8052b8193d6"
[[package]]
name = "udev"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50051c6e22be28ee6f217d50014f3bc29e81c20dc66ff7ca0d5c5226e1dcc5a1"
dependencies = [
"io-lifetimes",
"libc",
"libudev-sys",
"pkg-config",
]
[[package]]
name = "uf2-decode"
version = "0.2.0"
@ -7584,7 +7683,7 @@ dependencies = [
"lettre",
"mail-parser",
"matrix-sdk",
"nusb",
"nusb 0.2.2",
"opentelemetry",
"opentelemetry-otlp",
"opentelemetry_sdk",
@ -7594,7 +7693,7 @@ dependencies = [
"probe-rs",
"prometheus",
"prost 0.14.3",
"rand 0.10.0",
"rand 0.9.2",
"regex",
"reqwest",
"ring",
@ -7649,7 +7748,7 @@ dependencies = [
"thiserror 2.0.18",
"tokio",
"tokio-test",
"toml 1.0.1+spec-1.1.0",
"toml 0.8.23",
"tracing",
]

View file

@ -72,7 +72,7 @@ sha2 = "0.10"
hex = "0.4"
# CSPRNG for secure token generation
rand = "0.10"
rand = "0.9"
# serde-big-array for wa-rs storage (large array serialization)
serde-big-array = { version = "0.5", optional = true }
@ -142,7 +142,7 @@ tokio-serial = { version = "5", default-features = false, optional = true }
nusb = { version = "0.2", default-features = false, optional = true }
# probe-rs for STM32/Nucleo memory read (Phase B)
probe-rs = { version = "0.31", optional = true }
probe-rs = { version = "0.30", optional = true }
# PDF extraction for datasheet RAG (optional, enable with --features rag-pdf)
pdf-extract = { version = "0.10", optional = true }

View file

@ -25,7 +25,7 @@ Built by students and members of the Harvard, MIT, and Sundai.Club communities.
</p>
<p align="center">
🌐 <strong>Languages:</strong> <a href="README.md">English</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.ru.md">Русский</a> · <a href="README.vi.md">Tiếng Việt</a>
🌐 <strong>Languages:</strong> <a href="README.md">English</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.ru.md">Русский</a>
</p>
<p align="center">

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,7 @@ tokio = { version = "1.42", features = ["rt-multi-thread", "macros", "time", "sy
# Serialization
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "1.0"
toml = "0.8"
# HTTP client (for Ollama vision)
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }

View file

@ -1099,13 +1099,11 @@ pub(crate) async fn run_tool_call_loop(
arguments: call.arguments.clone(),
};
// On CLI, prompt interactively. On other channels where
// interactive approval is not possible, deny the call to
// respect the supervised autonomy setting.
// Only prompt interactively on CLI; auto-approve on other channels.
let decision = if channel_name == "cli" {
mgr.prompt_cli(&request)
} else {
ApprovalResponse::No
ApprovalResponse::Yes
};
mgr.record_decision(&call.name, &call.arguments, decision, channel_name);

View file

@ -61,7 +61,7 @@ async fn execute_job_with_retry(
for attempt in 0..=retries {
let (success, output) = match job.job_type {
JobType::Shell => run_job_command(config, security, job).await,
JobType::Agent => run_agent_job(config, security, job).await,
JobType::Agent => run_agent_job(config, job).await,
};
last_output = output;
@ -116,31 +116,7 @@ async fn execute_and_persist_job(
(job.id.clone(), success)
}
async fn run_agent_job(
config: &Config,
security: &SecurityPolicy,
job: &CronJob,
) -> (bool, String) {
if !security.can_act() {
return (
false,
"blocked by security policy: autonomy is read-only".to_string(),
);
}
if security.is_rate_limited() {
return (
false,
"blocked by security policy: rate limit exceeded".to_string(),
);
}
if !security.record_action() {
return (
false,
"blocked by security policy: action budget exhausted".to_string(),
);
}
async fn run_agent_job(config: &Config, job: &CronJob) -> (bool, String) {
let name = job.name.clone().unwrap_or_else(|| "cron-job".to_string());
let prompt = job.prompt.clone().unwrap_or_default();
let prefixed_prompt = format!("[cron:{} {name}] {prompt}", job.id);
@ -677,43 +653,13 @@ mod tests {
let mut job = test_job("");
job.job_type = JobType::Agent;
job.prompt = Some("Say hello".into());
let security = SecurityPolicy::from_config(&config.autonomy, &config.workspace_dir);
let (success, output) = run_agent_job(&config, &security, &job).await;
assert!(!success);
assert!(output.contains("agent job failed:"));
}
#[tokio::test]
async fn run_agent_job_blocks_readonly_mode() {
let tmp = TempDir::new().unwrap();
let mut config = test_config(&tmp);
config.autonomy.level = crate::security::AutonomyLevel::ReadOnly;
let mut job = test_job("");
job.job_type = JobType::Agent;
job.prompt = Some("Say hello".into());
let security = SecurityPolicy::from_config(&config.autonomy, &config.workspace_dir);
let (success, output) = run_agent_job(&config, &security, &job).await;
assert!(!success);
assert!(output.contains("blocked by security policy"));
assert!(output.contains("read-only"));
}
#[tokio::test]
async fn run_agent_job_blocks_rate_limited() {
let tmp = TempDir::new().unwrap();
let mut config = test_config(&tmp);
config.autonomy.max_actions_per_hour = 0;
let mut job = test_job("");
job.job_type = JobType::Agent;
job.prompt = Some("Say hello".into());
let security = SecurityPolicy::from_config(&config.autonomy, &config.workspace_dir);
let (success, output) = run_agent_job(&config, &security, &job).await;
assert!(!success);
assert!(output.contains("blocked by security policy"));
assert!(output.contains("rate limit exceeded"));
let (success, output) = run_agent_job(&config, &job).await;
assert!(!success, "Agent job without provider key should fail");
assert!(
!output.is_empty(),
"Expected non-empty error output from failed agent job"
);
}
#[tokio::test]

View file

@ -39,41 +39,41 @@ use clap::Subcommand;
use serde::{Deserialize, Serialize};
pub mod agent;
pub(crate) mod approval;
pub(crate) mod auth;
pub mod approval;
pub mod auth;
pub mod channels;
pub mod config;
pub(crate) mod cost;
pub(crate) mod cron;
pub(crate) mod daemon;
pub(crate) mod doctor;
pub mod cost;
pub mod cron;
pub mod daemon;
pub mod doctor;
pub mod gateway;
pub(crate) mod hardware;
pub(crate) mod health;
pub(crate) mod heartbeat;
pub(crate) mod identity;
pub(crate) mod integrations;
pub mod hardware;
pub mod health;
pub mod heartbeat;
pub mod identity;
pub mod integrations;
pub mod memory;
pub(crate) mod migration;
pub(crate) mod multimodal;
pub mod migration;
pub mod multimodal;
pub mod observability;
pub(crate) mod onboard;
pub mod onboard;
pub mod peripherals;
pub mod providers;
pub mod rag;
pub mod runtime;
pub(crate) mod security;
pub(crate) mod service;
pub(crate) mod skills;
pub mod security;
pub mod service;
pub mod skills;
pub mod tools;
pub(crate) mod tunnel;
pub(crate) mod util;
pub mod tunnel;
pub mod util;
pub use config::Config;
/// Service management subcommands
#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub(crate) enum ServiceCommands {
pub enum ServiceCommands {
/// Install daemon service unit for auto-start and restart
Install,
/// Start daemon service
@ -90,7 +90,7 @@ pub(crate) enum ServiceCommands {
/// Channel management subcommands
#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub(crate) enum ChannelCommands {
pub enum ChannelCommands {
/// List all configured channels
List,
/// Start all configured channels (handled in main.rs for async)
@ -139,7 +139,7 @@ Examples:
/// Skills management subcommands
#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub(crate) enum SkillCommands {
pub enum SkillCommands {
/// List all installed skills
List,
/// Install a new skill from a git URL (HTTPS/SSH) or local path
@ -156,7 +156,7 @@ pub(crate) enum SkillCommands {
/// Migration subcommands
#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub(crate) enum MigrateCommands {
pub enum MigrateCommands {
/// Import memory from an `OpenClaw` workspace into this `ZeroClaw` workspace
Openclaw {
/// Optional path to `OpenClaw` workspace (defaults to ~/.openclaw/workspace)
@ -171,7 +171,7 @@ pub(crate) enum MigrateCommands {
/// Cron subcommands
#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub(crate) enum CronCommands {
pub enum CronCommands {
/// List all scheduled tasks
List,
/// Add a new scheduled task
@ -286,7 +286,7 @@ Examples:
/// Integration subcommands
#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub(crate) enum IntegrationCommands {
pub enum IntegrationCommands {
/// Show details about a specific integration
Info {
/// Integration name

View file

@ -215,7 +215,9 @@ fn generate_code() -> String {
/// on macOS). The 32 random bytes (256 bits) are hex-encoded for a
/// 64-character token, providing 256 bits of entropy.
fn generate_token() -> String {
let bytes: [u8; 32] = rand::random();
use rand::RngCore;
let mut bytes = [0u8; 32];
rand::rng().fill_bytes(&mut bytes);
format!("zc_{}", hex::encode(bytes))
}