diff --git a/.gitignore b/.gitignore index 55cdaa4..4ccac12 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ Icon[ ] Network Trash Folder Temporary Items .apdisk + +.agentfs diff --git a/cli/Cargo.lock b/cli/Cargo.lock index 5d8445f..1cf32ce 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -89,8 +89,10 @@ dependencies = [ "reverie-process", "reverie-ptrace", "serde", + "serde_json", "tempfile", "tokio", + "tracing", "tracing-subscriber", "turso", "uuid", @@ -221,6 +223,12 @@ dependencies = [ "syn 2.0.112", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atty" version = "0.2.14" @@ -238,6 +246,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -247,6 +261,29 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.10.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.112", + "which", +] + [[package]] name = "bit-vec" version = "0.4.4" @@ -277,6 +314,15 @@ dependencies = [ "bit-vec", ] +[[package]] +name = "branches" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e426eb5cc1900033930ec955317b302e68f19f326cc7bb0c8a86865a826cdf0c" +dependencies = [ + "rustc_version", +] + [[package]] name = "built" version = "0.7.7" @@ -349,6 +395,15 @@ dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -391,6 +446,17 @@ dependencies = [ "inout", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "3.2.25" @@ -530,6 +596,16 @@ dependencies = [ "unicode-segmentation", ] +[[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-sys" version = "0.8.7" @@ -686,6 +762,25 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -748,6 +843,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -755,7 +859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -769,6 +873,12 @@ dependencies = [ "syn 2.0.112", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -895,6 +1005,21 @@ dependencies = [ "slab", ] +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "genawaiter-macro", +] + +[[package]] +name = "genawaiter-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" + [[package]] name = "generic-array" version = "0.14.7" @@ -961,6 +1086,12 @@ dependencies = [ "url", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "goblin" version = "0.10.4" @@ -1032,6 +1163,112 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.64" @@ -1242,6 +1479,24 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.17" @@ -1284,6 +1539,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.178" @@ -1372,6 +1633,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[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" @@ -1463,6 +1730,12 @@ dependencies = [ "libmimalloc-sys", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1484,6 +1757,23 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "never-say-never" version = "6.6.666" @@ -1535,6 +1825,16 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1611,6 +1911,50 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -1760,6 +2104,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.112", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1808,6 +2162,29 @@ dependencies = [ "rustix 0.36.17", ] +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + [[package]] name = "quote" version = "1.0.42" @@ -2066,12 +2443,27 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.36.17" @@ -2100,6 +2492,19 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.3" @@ -2151,6 +2556,15 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -2177,6 +2591,35 @@ dependencies = [ "syn 2.0.112", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.10.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" version = "1.0.228" @@ -2573,6 +3016,16 @@ dependencies = [ "syn 2.0.112", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -2598,6 +3051,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.44" @@ -2687,24 +3146,37 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "turso" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f927be684ce9c612d2f11d04b9d48f4ba553fa98cf6e3bd2073c16602c8d7dc4" +checksum = "b33c17bb7f930ce5dab1fa1eb398dd8a6449418a890d9d4185162a4523535a47" dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", "mimalloc", "thiserror 2.0.17", + "tokio", "tracing", "tracing-subscriber", - "turso_core", + "turso_sdk_kit", + "turso_sync_sdk_kit", ] [[package]] name = "turso_core" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88848a55b47fde014039f36dad09f33af34ad27ed94e70161fb8cf435ea3f3" +checksum = "0c23c0ce43d01fbef7e744a67883b0ad8971e5ff8da6e5000e893eea80e23815" dependencies = [ "aegis", "aes", @@ -2712,7 +3184,9 @@ dependencies = [ "arc-swap", "bitflags 2.10.0", "bloom", + "branches", "built", + "bumpalo", "bytemuck", "cfg_block", "chrono", @@ -2735,7 +3209,7 @@ dependencies = [ "regex", "regex-syntax", "roaring", - "rustc-hash", + "rustc-hash 2.1.1", "rustix 1.1.3", "ryu", "simsimd", @@ -2755,9 +3229,9 @@ dependencies = [ [[package]] name = "turso_ext" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e03badf97da72c41c3289ac19245109096e6262017151dad23ecf7115ee433" +checksum = "946540b249d321721a8332d08ea92a583df9e3d4ebe38b91045b570d49e0dca8" dependencies = [ "chrono", "getrandom 0.3.4", @@ -2766,9 +3240,9 @@ dependencies = [ [[package]] name = "turso_macros" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681754e341a0420494203b73e067b0b69b29ccf0852d0d24bc7d5255d4441dea" +checksum = "c3b6b7fa63373cac352c7d6999965f9aaaee8f131639f6f128de698dc77a34e9" dependencies = [ "proc-macro2", "quote", @@ -2777,11 +3251,12 @@ dependencies = [ [[package]] name = "turso_parser" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92dd528809dfb32facb949b9b5416a33ee8f856b444f882854c0835428f511dd" +checksum = "596dacab0730f96884c3e0153f705b6a3f364ef27f1b48cd57b4989a3f860db3" dependencies = [ "bitflags 2.10.0", + "memchr", "miette", "strum", "strum_macros", @@ -2789,6 +3264,73 @@ dependencies = [ "turso_macros", ] +[[package]] +name = "turso_sdk_kit" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d553324de462845c9a81131e9c9c96fca5dc79f3d5ea2a9556f4bea832d21bb8" +dependencies = [ + "bindgen", + "env_logger", + "tracing", + "tracing-appender", + "tracing-subscriber", + "turso_core", + "turso_sdk_kit_macros", +] + +[[package]] +name = "turso_sdk_kit_macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c441611414af2182470f2bbc2af3dd2178799dabbabbd2fb2162eb417a83d2d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "turso_sync_engine" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5c1acca39d882ba8546b00c8b086b8dc649c21c778c233e042972d477bca12" +dependencies = [ + "base64", + "bytes", + "genawaiter", + "http", + "libc", + "prost", + "roaring", + "serde", + "serde_json", + "thiserror 2.0.17", + "tracing", + "turso_core", + "turso_parser", + "uuid", +] + +[[package]] +name = "turso_sync_sdk_kit" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2ab8fe160a3f385364b6e7609a5a6a02b5e07749315f7e7e32733266278c54" +dependencies = [ + "bindgen", + "env_logger", + "genawaiter", + "parking_lot", + "tracing", + "tracing-appender", + "tracing-subscriber", + "turso_core", + "turso_sdk_kit", + "turso_sdk_kit_macros", + "turso_sync_engine", +] + [[package]] name = "twox-hash" version = "1.6.3" @@ -2881,7 +3423,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38290439f8459ba56c4bf15fc776463f495fefc4f0112f87a1a075540441b083" dependencies = [ - "foreign-types", + "foreign-types 0.5.0", "libc", "unwind-sys", ] @@ -2950,6 +3492,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -3010,6 +3561,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + [[package]] name = "winapi" version = "0.2.8" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 2f78c6e..a35346b 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -17,11 +17,13 @@ agentfs-sdk = { path = "../sdk/rust" } tokio = { version = "1", features = ["full"] } clap = { version = "4", features = ["derive"] } anyhow = "1.0" -turso = "0.4.0-pre.17" +turso = { version = "0.4.0", features = ["sync"] } serde = { version = "1.0", features = ["derive"] } parking_lot = "0.12.5" clap_complete = { version = "=4.5.61", features = ["unstable-dynamic"] } dirs = "6" +serde_json = "1.0.147" +tracing = "0.1.44" tracing-subscriber = { version = "0.3", features = ["env-filter"] } # Unix dependencies diff --git a/cli/src/cmd/fs.rs b/cli/src/cmd/fs.rs index c7424c4..50585b5 100644 --- a/cli/src/cmd/fs.rs +++ b/cli/src/cmd/fs.rs @@ -1,8 +1,10 @@ use std::collections::VecDeque; -use agentfs_sdk::{AgentFS, AgentFSOptions}; +use agentfs_sdk::AgentFSOptions; use anyhow::{Context, Result as AnyhowResult}; -use turso::{Builder, Value}; +use turso::Value; + +use crate::cmd::init::open_agentfs; const ROOT_INO: i64 = 1; const S_IFMT: u32 = 0o170000; @@ -16,15 +18,10 @@ pub async fn ls_filesystem( path: &str, ) -> AnyhowResult<()> { let options = AgentFSOptions::resolve(&id_or_path)?; - let db_path = options.path.context("No database path resolved")?; eprintln!("Using agent: {}", id_or_path); - let db = Builder::new_local(&db_path) - .build() - .await - .context("Failed to open filesystem")?; - - let conn = db.connect().context("Failed to connect to filesystem")?; + let (_, agentfs) = open_agentfs(options).await?; + let conn = agentfs.get_connection(); if path != "/" { anyhow::bail!("Only root directory (/) is currently supported"); @@ -104,14 +101,8 @@ pub async fn cat_filesystem( path: &str, ) -> AnyhowResult<()> { let options = AgentFSOptions::resolve(&id_or_path)?; - let db_path = options.path.context("No database path resolved")?; - - let db = Builder::new_local(&db_path) - .build() - .await - .context("Failed to open filesystem")?; - - let conn = db.connect().context("Failed to connect to filesystem")?; + let (_, agentfs) = open_agentfs(options).await?; + let conn = agentfs.get_connection(); let path_components: Vec<&str> = path .trim_start_matches('/') @@ -236,7 +227,7 @@ pub async fn diff_filesystem(id_or_path: String) -> AnyhowResult<()> { let options = AgentFSOptions::resolve(&id_or_path)?; eprintln!("Using agent: {}", id_or_path); - let agent = AgentFS::open(options) + let (_, agent) = open_agentfs(options) .await .context("Failed to open agent")?; diff --git a/cli/src/cmd/init.rs b/cli/src/cmd/init.rs index cf0ae20..4a4ab44 100644 --- a/cli/src/cmd/init.rs +++ b/cli/src/cmd/init.rs @@ -1,11 +1,91 @@ use std::path::PathBuf; use std::time::{SystemTime, UNIX_EPOCH}; -use agentfs_sdk::{agentfs_dir, AgentFS, AgentFSOptions}; +use agentfs_sdk::{agentfs_dir, AgentFS, AgentFSOptions, OverlayFS}; use anyhow::{Context, Result as AnyhowResult}; +use turso::sync::{PartialBootstrapStrategy, PartialSyncOpts}; + +use crate::parser::SyncCommandOptions; + +pub async fn open_agentfs( + options: AgentFSOptions, +) -> anyhow::Result<(Option, AgentFS)> { + let path = options.db_path()?; + let meta_path = format!("{path}-info"); + if !std::fs::exists(meta_path)? { + return Ok(( + None, + AgentFS::open(options) + .await + .context("Failed to open database")?, + )); + } + let mut builder = turso::sync::Builder::new_remote(&options.db_path()?); + if let Ok(auth_token) = std::env::var("TURSO_DB_AUTH_TOKEN") { + builder = builder.with_auth_token(auth_token); + } + let db = builder.build().await?; + let conn = db.connect().await?; + let agent = AgentFS::open_with(conn) + .await + .context("Failed to open synced database")?; + Ok((Some(db), agent)) +} + +pub async fn create_agentfs( + options: AgentFSOptions, + sync_options: SyncCommandOptions, +) -> anyhow::Result<(Option, AgentFS)> { + if let Some(remote_url) = sync_options.sync_remote_url { + let mut builder = + turso::sync::Builder::new_remote(&options.db_path()?).with_remote_url(remote_url); + if let Ok(auth_token) = std::env::var("TURSO_DB_AUTH_TOKEN") { + builder = builder.with_auth_token(auth_token); + } + let mut partial_sync = PartialSyncOpts { + bootstrap_strategy: Some(PartialBootstrapStrategy::Prefix { length: 128 * 1024 }), + prefetch: false, + segment_size: 128 * 1024, + }; + let mut has_partial_sync = false; + if let Some(prefetch) = sync_options.sync_partial_prefetch { + partial_sync.prefetch = prefetch; + has_partial_sync = true; + } + if let Some(segment_size) = sync_options.sync_partial_segment_size { + partial_sync.segment_size = segment_size; + has_partial_sync = true; + } + if let Some(length) = sync_options.sync_partial_bootstrap_length { + partial_sync.bootstrap_strategy = Some(PartialBootstrapStrategy::Prefix { length }); + has_partial_sync = true; + } + if let Some(query) = sync_options.sync_partial_bootstrap_query { + partial_sync.bootstrap_strategy = Some(PartialBootstrapStrategy::Query { query }); + has_partial_sync = true; + } + if has_partial_sync { + builder = builder.with_partial_sync_opts_experimental(partial_sync); + } + let db = builder.build().await?; + let conn = db.connect().await?; + let agent = AgentFS::open_with(conn) + .await + .context("Failed to initialize synced database")?; + Ok((Some(db), agent)) + } else { + Ok(( + None, + AgentFS::open(options) + .await + .context("Failed to initialize database")?, + )) + } +} pub async fn init_database( id: Option, + sync_options: SyncCommandOptions, force: bool, base: Option, ) -> AnyhowResult<()> { @@ -19,7 +99,7 @@ pub async fn init_database( }); // Validate agent ID for safety - if !AgentFS::validate_agent_id(&id) { + if !AgentFSOptions::validate_agent_id(&id) { anyhow::bail!( "Invalid agent ID '{}'. Agent IDs must contain only alphanumeric characters, hyphens, and underscores.", id @@ -64,16 +144,33 @@ pub async fn init_database( // Use the SDK to initialize the database - this ensures consistency // The SDK will create .agentfs directory and database file - let _agent = AgentFS::open(open_options) - .await - .context("Failed to initialize database")?; + let (synced_db, agent) = create_agentfs(open_options, sync_options).await?; // If base is provided, initialize the overlay schema using the SDK if let Some(base_path) = base { + let base_path_str = base_path + .canonicalize() + .context("Failed to canonicalize base path")? + .to_string_lossy() + .to_string(); + + // Use SDK's OverlayFS::init_schema to ensure schema consistency + OverlayFS::init_schema(&agent.get_connection(), &base_path_str) + .await + .context("Failed to initialize overlay schema")?; + + if let Some(synced_db) = synced_db { + synced_db.push().await?; + } + eprintln!("Created overlay filesystem: {}", db_path.display()); eprintln!("Agent ID: {}", id); eprintln!("Base: {}", base_path.display()); } else { + if let Some(synced_db) = synced_db { + synced_db.push().await?; + } + eprintln!("Created agent filesystem: {}", db_path.display()); eprintln!("Agent ID: {}", id); } diff --git a/cli/src/cmd/mod.rs b/cli/src/cmd/mod.rs index 3e05dc5..9662d50 100644 --- a/cli/src/cmd/mod.rs +++ b/cli/src/cmd/mod.rs @@ -1,6 +1,7 @@ pub mod completions; pub mod fs; pub mod init; +pub mod sync; #[cfg(target_os = "linux")] mod mount; diff --git a/cli/src/cmd/mount.rs b/cli/src/cmd/mount.rs index 7389964..8ddc63f 100644 --- a/cli/src/cmd/mount.rs +++ b/cli/src/cmd/mount.rs @@ -1,9 +1,9 @@ -use agentfs_sdk::{AgentFS, AgentFSOptions, FileSystem, HostFS, OverlayFS}; +use agentfs_sdk::{AgentFSOptions, FileSystem, HostFS, OverlayFS}; use anyhow::Result; use std::{os::unix::fs::MetadataExt, path::PathBuf, sync::Arc}; -use turso::Value; +use turso::value::Value; -use crate::fuse::FuseMountOptions; +use crate::{cmd::init::open_agentfs, fuse::FuseMountOptions}; /// Arguments for the mount command. #[derive(Debug, Clone)] @@ -79,7 +79,7 @@ pub fn mount(args: MountArgs) -> Result<()> { let mount = move || { let rt = crate::get_runtime(); - let agentfs = rt.block_on(AgentFS::open(opts))?; + let (_db, agentfs) = rt.block_on(open_agentfs(opts))?; // Check for overlay configuration let fs: Arc = rt.block_on(async { diff --git a/cli/src/cmd/nfs.rs b/cli/src/cmd/nfs.rs index c34f41a..c390fe2 100644 --- a/cli/src/cmd/nfs.rs +++ b/cli/src/cmd/nfs.rs @@ -4,7 +4,7 @@ //! filesystem over the network, allowing remote systems (like VMs) to mount //! it as their root filesystem. -use agentfs_sdk::{agentfs_dir, AgentFS, AgentFSOptions, FileSystem, HostFS, OverlayFS}; +use agentfs_sdk::{agentfs_dir, AgentFSOptions, FileSystem, HostFS, OverlayFS}; use anyhow::{Context, Result}; use nfsserve::tcp::NFSTcp; use std::path::PathBuf; @@ -12,6 +12,7 @@ use std::sync::Arc; use tokio::signal; use tokio::sync::Mutex; +use crate::cmd::init::open_agentfs; use crate::nfs::AgentNFS; /// Handle the `nfs` command - start a standalone NFS server. @@ -24,9 +25,8 @@ pub async fn handle_nfs_command(id_or_path: String, bind: String, port: u32) -> .to_str() .context("Database path contains non-UTF8 characters")?; - let agentfs = AgentFS::open(AgentFSOptions::with_path(db_path_str)) - .await - .context("Failed to open AgentFS database")?; + let options = AgentFSOptions::with_path(db_path_str); + let (_, agentfs) = open_agentfs(options).await?; // Check if overlay is configured in the database let base_path = agentfs diff --git a/cli/src/cmd/sync.rs b/cli/src/cmd/sync.rs new file mode 100644 index 0000000..f3a361b --- /dev/null +++ b/cli/src/cmd/sync.rs @@ -0,0 +1,59 @@ +use agentfs_sdk::AgentFSOptions; +use anyhow::anyhow; + +use crate::cmd::init::open_agentfs; + +pub async fn handle_pull_command(id_or_path: String) -> anyhow::Result<()> { + let options = AgentFSOptions::resolve(&id_or_path)?; + eprintln!("Using agent: {}", id_or_path); + + let (db, _) = open_agentfs(options).await?; + let Some(db) = db else { + return Err(anyhow!("db is not connected to the remote")); + }; + db.pull().await?; + eprintln!("Remote data pulled to local db successfully"); + Ok(()) +} + +pub async fn handle_push_command(id_or_path: String) -> anyhow::Result<()> { + let options = AgentFSOptions::resolve(&id_or_path)?; + eprintln!("Using agent: {}", id_or_path); + + let (db, _) = open_agentfs(options).await?; + let Some(db) = db else { + return Err(anyhow!("db is not connected to the remote")); + }; + db.push().await?; + eprintln!("Local data pushed to remote db successfully"); + Ok(()) +} + +pub async fn handle_checkpoint_command(id_or_path: String) -> anyhow::Result<()> { + let options = AgentFSOptions::resolve(&id_or_path)?; + eprintln!("Using agent: {}", id_or_path); + + let (db, _) = open_agentfs(options).await?; + let Some(db) = db else { + return Err(anyhow!("db is not connected to the remote")); + }; + db.checkpoint().await?; + eprintln!("Local db checkpoined successfully"); + Ok(()) +} + +pub async fn handle_stats_command( + stdout: &mut impl std::io::Write, + id_or_path: String, +) -> anyhow::Result<()> { + let options = AgentFSOptions::resolve(&id_or_path)?; + eprintln!("Using agent: {}", id_or_path); + + let (db, _) = open_agentfs(options).await?; + let Some(db) = db else { + return Err(anyhow!("db is not connected to the remote")); + }; + let stats = db.stats().await?; + stdout.write_all(serde_json::to_string(&stats)?.as_bytes())?; + Ok(()) +} diff --git a/cli/src/main.rs b/cli/src/main.rs index d7e0c1b..f7404ad 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,7 +1,7 @@ use agentfs::{ cmd::{self, completions::handle_completions}, get_runtime, - parser::{Args, Command, FsCommand}, + parser::{Args, Command, FsCommand, SyncCommand}, }; use clap::{CommandFactory, Parser}; use clap_complete::CompleteEnv; @@ -22,13 +22,54 @@ fn main() { let args = Args::parse(); match args.command { - Command::Init { id, force, base } => { + Command::Init { + id, + force, + base, + sync, + } => { let rt = get_runtime(); - if let Err(e) = rt.block_on(cmd::init::init_database(id, force, base)) { + if let Err(e) = rt.block_on(cmd::init::init_database(id, sync, force, base)) { eprintln!("Error: {}", e); std::process::exit(1); } } + Command::Sync { + id_or_path, + command, + } => match command { + SyncCommand::Pull => { + let rt = get_runtime(); + if let Err(e) = rt.block_on(cmd::sync::handle_pull_command(id_or_path)) { + eprintln!("Error: {}", e); + std::process::exit(1); + } + } + SyncCommand::Push => { + let rt = get_runtime(); + if let Err(e) = rt.block_on(cmd::sync::handle_push_command(id_or_path)) { + eprintln!("Error: {}", e); + std::process::exit(1); + } + } + SyncCommand::Checkpoint => { + let rt = get_runtime(); + if let Err(e) = rt.block_on(cmd::sync::handle_checkpoint_command(id_or_path)) { + eprintln!("Error: {}", e); + std::process::exit(1); + } + } + SyncCommand::Stats => { + let rt = get_runtime(); + if let Err(e) = rt.block_on(cmd::sync::handle_stats_command( + &mut std::io::stdout(), + id_or_path, + )) { + eprintln!("Error: {}", e); + std::process::exit(1); + } + } + }, Command::Run { allow, no_default_allows, @@ -82,13 +123,13 @@ fn main() { std::process::exit(1); } } - Command::Fs { command } => { + Command::Fs { + command, + id_or_path, + } => { let rt = get_runtime(); match command { - FsCommand::Ls { - id_or_path, - fs_path, - } => { + FsCommand::Ls { fs_path } => { if let Err(e) = rt.block_on(cmd::fs::ls_filesystem( &mut std::io::stdout(), id_or_path, @@ -98,10 +139,7 @@ fn main() { std::process::exit(1); } } - FsCommand::Cat { - id_or_path, - file_path, - } => { + FsCommand::Cat { file_path } => { if let Err(e) = rt.block_on(cmd::fs::cat_filesystem( &mut std::io::stdout(), id_or_path, diff --git a/cli/src/parser.rs b/cli/src/parser.rs index c6f1d9b..1059582 100644 --- a/cli/src/parser.rs +++ b/cli/src/parser.rs @@ -15,6 +15,20 @@ pub struct Args { pub command: Command, } +#[derive(Debug, Parser)] +pub struct SyncCommandOptions { + #[arg(long)] + pub sync_remote_url: Option, + #[arg(long)] + pub sync_partial_prefetch: Option, + #[arg(long)] + pub sync_partial_segment_size: Option, + #[arg(long)] + pub sync_partial_bootstrap_query: Option, + #[arg(long)] + pub sync_partial_bootstrap_length: Option, +} + #[derive(Subcommand, Debug)] pub enum Command { /// Manage shell completions @@ -34,9 +48,25 @@ pub enum Command { /// Base directory for overlay filesystem (copy-on-write) #[arg(long)] base: Option, + + #[command(flatten)] + sync: SyncCommandOptions, + }, + /// Remote sync operations + Sync { + /// Agent ID or database path + #[arg(add = ArgValueCompleter::new(id_or_path_completer))] + id_or_path: String, + + #[command(subcommand)] + command: SyncCommand, }, /// Filesystem operations Fs { + /// Agent ID or database path + #[arg(add = ArgValueCompleter::new(id_or_path_completer))] + id_or_path: String, + #[command(subcommand)] command: FsCommand, }, @@ -133,25 +163,29 @@ pub enum Command { pub enum FsCommand { /// List files in the filesystem Ls { - /// Agent ID or database path - #[arg(add = ArgValueCompleter::new(id_or_path_completer))] - id_or_path: String, - /// Path to list (default: /) #[arg(default_value = "/")] fs_path: String, }, /// Display file contents Cat { - /// Agent ID or database path - #[arg(add = ArgValueCompleter::new(id_or_path_completer))] - id_or_path: String, - /// Path to the file in the filesystem file_path: String, }, } +#[derive(Subcommand, Debug)] +pub enum SyncCommand { + /// Pull remote changes (only of agentfs was initialized with remote sync) + Pull, + /// Push remote changes (only of agentfs was initialized with remote sync) + Push, + /// Print synced database stats + Stats, + /// Checkpoint local synced db + Checkpoint, +} + #[derive(Subcommand, Debug, Clone, Copy)] pub enum CompletionsCommand { /// Install shell completions to your shell rc file diff --git a/sandbox/Cargo.lock b/sandbox/Cargo.lock index 0c36494..a9a2cee 100644 --- a/sandbox/Cargo.lock +++ b/sandbox/Cargo.lock @@ -146,6 +146,12 @@ dependencies = [ "syn 2.0.112", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atty" version = "0.2.14" @@ -163,6 +169,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -172,6 +184,29 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.10.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.112", + "which", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -217,6 +252,15 @@ dependencies = [ "bit-vec 0.4.4", ] +[[package]] +name = "branches" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e426eb5cc1900033930ec955317b302e68f19f326cc7bb0c8a86865a826cdf0c" +dependencies = [ + "rustc_version", +] + [[package]] name = "built" version = "0.7.7" @@ -280,6 +324,15 @@ dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -322,6 +375,17 @@ dependencies = [ "inout", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "3.2.25" @@ -403,6 +467,16 @@ dependencies = [ "unicode-segmentation", ] +[[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-sys" version = "0.8.7" @@ -538,6 +612,25 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -594,6 +687,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -601,7 +703,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -615,6 +717,12 @@ dependencies = [ "syn 2.0.112", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -726,6 +834,21 @@ dependencies = [ "slab", ] +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "genawaiter-macro", +] + +[[package]] +name = "genawaiter-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" + [[package]] name = "generic-array" version = "0.14.7" @@ -792,6 +915,12 @@ dependencies = [ "url", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "goblin" version = "0.10.4" @@ -863,6 +992,112 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.64" @@ -1058,6 +1293,24 @@ dependencies = [ "libc", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.17" @@ -1100,6 +1353,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.178" @@ -1177,6 +1436,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[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" @@ -1268,6 +1533,12 @@ dependencies = [ "libmimalloc-sys", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1289,6 +1560,23 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "never-say-never" version = "6.6.666" @@ -1308,6 +1596,16 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1367,6 +1665,50 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "os_str_bytes" version = "6.6.1" @@ -1500,6 +1842,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.112", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1567,6 +1919,29 @@ dependencies = [ "unarray", ] +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1820,12 +2195,27 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.36.17" @@ -1854,6 +2244,19 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.3" @@ -1917,6 +2320,15 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1943,6 +2355,35 @@ dependencies = [ "syn 2.0.112", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.10.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" version = "1.0.228" @@ -2333,6 +2774,16 @@ dependencies = [ "syn 2.0.112", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -2358,6 +2809,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.44" @@ -2447,24 +2904,37 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "turso" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f927be684ce9c612d2f11d04b9d48f4ba553fa98cf6e3bd2073c16602c8d7dc4" +checksum = "b33c17bb7f930ce5dab1fa1eb398dd8a6449418a890d9d4185162a4523535a47" dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", "mimalloc", "thiserror 2.0.17", + "tokio", "tracing", "tracing-subscriber", - "turso_core", + "turso_sdk_kit", + "turso_sync_sdk_kit", ] [[package]] name = "turso_core" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88848a55b47fde014039f36dad09f33af34ad27ed94e70161fb8cf435ea3f3" +checksum = "0c23c0ce43d01fbef7e744a67883b0ad8971e5ff8da6e5000e893eea80e23815" dependencies = [ "aegis", "aes", @@ -2472,7 +2942,9 @@ dependencies = [ "arc-swap", "bitflags 2.10.0", "bloom", + "branches", "built", + "bumpalo", "bytemuck", "cfg_block", "chrono", @@ -2495,7 +2967,7 @@ dependencies = [ "regex", "regex-syntax", "roaring", - "rustc-hash", + "rustc-hash 2.1.1", "rustix 1.1.3", "ryu", "simsimd", @@ -2515,9 +2987,9 @@ dependencies = [ [[package]] name = "turso_ext" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e03badf97da72c41c3289ac19245109096e6262017151dad23ecf7115ee433" +checksum = "946540b249d321721a8332d08ea92a583df9e3d4ebe38b91045b570d49e0dca8" dependencies = [ "chrono", "getrandom 0.3.4", @@ -2526,9 +2998,9 @@ dependencies = [ [[package]] name = "turso_macros" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681754e341a0420494203b73e067b0b69b29ccf0852d0d24bc7d5255d4441dea" +checksum = "c3b6b7fa63373cac352c7d6999965f9aaaee8f131639f6f128de698dc77a34e9" dependencies = [ "proc-macro2", "quote", @@ -2537,11 +3009,12 @@ dependencies = [ [[package]] name = "turso_parser" -version = "0.4.0-pre.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92dd528809dfb32facb949b9b5416a33ee8f856b444f882854c0835428f511dd" +checksum = "596dacab0730f96884c3e0153f705b6a3f364ef27f1b48cd57b4989a3f860db3" dependencies = [ "bitflags 2.10.0", + "memchr", "miette", "strum", "strum_macros", @@ -2549,6 +3022,73 @@ dependencies = [ "turso_macros", ] +[[package]] +name = "turso_sdk_kit" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d553324de462845c9a81131e9c9c96fca5dc79f3d5ea2a9556f4bea832d21bb8" +dependencies = [ + "bindgen", + "env_logger", + "tracing", + "tracing-appender", + "tracing-subscriber", + "turso_core", + "turso_sdk_kit_macros", +] + +[[package]] +name = "turso_sdk_kit_macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c441611414af2182470f2bbc2af3dd2178799dabbabbd2fb2162eb417a83d2d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "turso_sync_engine" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5c1acca39d882ba8546b00c8b086b8dc649c21c778c233e042972d477bca12" +dependencies = [ + "base64", + "bytes", + "genawaiter", + "http", + "libc", + "prost", + "roaring", + "serde", + "serde_json", + "thiserror 2.0.17", + "tracing", + "turso_core", + "turso_parser", + "uuid", +] + +[[package]] +name = "turso_sync_sdk_kit" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2ab8fe160a3f385364b6e7609a5a6a02b5e07749315f7e7e32733266278c54" +dependencies = [ + "bindgen", + "env_logger", + "genawaiter", + "parking_lot", + "tracing", + "tracing-appender", + "tracing-subscriber", + "turso_core", + "turso_sdk_kit", + "turso_sdk_kit_macros", + "turso_sync_engine", +] + [[package]] name = "twox-hash" version = "1.6.3" @@ -2647,7 +3187,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38290439f8459ba56c4bf15fc776463f495fefc4f0112f87a1a075540441b083" dependencies = [ - "foreign-types", + "foreign-types 0.5.0", "libc", "unwind-sys", ] @@ -2719,6 +3259,15 @@ dependencies = [ "libc", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -2779,6 +3328,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + [[package]] name = "winapi" version = "0.2.8" diff --git a/sandbox/src/syscall/file.rs b/sandbox/src/syscall/file.rs index f06beb6..dc0f69d 100644 --- a/sandbox/src/syscall/file.rs +++ b/sandbox/src/syscall/file.rs @@ -1804,7 +1804,7 @@ pub async fn handle_chmod>( use reverie::syscalls::{AtFlags, Mode, PathPtr, Syscall}; let dirfd = syscall_args.arg0 as i32; - let pathname_addr = match unsafe { PathPtr::from_ptr(syscall_args.arg1 as _) } { + let pathname_addr = match PathPtr::from_ptr(syscall_args.arg1 as _) { Some(ptr) => ptr, None => { return Ok(None); diff --git a/sdk/rust/Cargo.lock b/sdk/rust/Cargo.lock index 02fa72c..25040e3 100644 --- a/sdk/rust/Cargo.lock +++ b/sdk/rust/Cargo.lock @@ -127,6 +127,35 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn", + "which", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -229,6 +258,15 @@ dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -291,6 +329,17 @@ dependencies = [ "inout", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.53" @@ -378,6 +427,15 @@ dependencies = [ "itertools", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -439,6 +497,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -456,6 +523,25 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "errno" version = "0.3.14" @@ -560,6 +646,21 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "genawaiter-macro", +] + +[[package]] +name = "genawaiter-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" + [[package]] name = "generic-array" version = "0.14.7" @@ -616,6 +717,12 @@ dependencies = [ "url", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "half" version = "2.7.1" @@ -645,6 +752,25 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + [[package]] name = "iana-time-zone" version = "0.1.64" @@ -852,6 +978,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.178" @@ -908,6 +1040,12 @@ dependencies = [ "vcpkg", ] +[[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" @@ -935,6 +1073,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.7.6" @@ -981,6 +1128,12 @@ dependencies = [ "libmimalloc-sys", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "mio" version = "1.1.1" @@ -992,6 +1145,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1001,6 +1164,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.19" @@ -1128,7 +1297,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix", + "rustix 1.1.3", "windows-sys 0.61.2", ] @@ -1153,6 +1322,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1162,6 +1337,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.104" @@ -1190,6 +1375,29 @@ dependencies = [ "unarray", ] +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1335,12 +1543,31 @@ dependencies = [ "byteorder", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.3" @@ -1350,7 +1577,7 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.11.0", "windows-sys 0.61.2", ] @@ -1563,7 +1790,7 @@ dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", - "rustix", + "rustix 1.1.3", "windows-sys 0.61.2", ] @@ -1616,6 +1843,37 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinystr" version = "0.8.2" @@ -1675,6 +1933,18 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" +dependencies = [ + "crossbeam-channel", + "thiserror 2.0.17", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" version = "0.1.31" @@ -1713,32 +1983,35 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] [[package]] name = "turso" -version = "0.4.0-pre.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f927be684ce9c612d2f11d04b9d48f4ba553fa98cf6e3bd2073c16602c8d7dc4" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" dependencies = [ "mimalloc", "thiserror 2.0.17", "tracing", "tracing-subscriber", - "turso_core", + "turso_sdk_kit", + "turso_sync_sdk_kit", ] [[package]] name = "turso_core" -version = "0.4.0-pre.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88848a55b47fde014039f36dad09f33af34ad27ed94e70161fb8cf435ea3f3" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" dependencies = [ "aegis", "aes", @@ -1769,8 +2042,8 @@ dependencies = [ "regex", "regex-syntax", "roaring", - "rustc-hash", - "rustix", + "rustc-hash 2.1.1", + "rustix 1.1.3", "ryu", "simsimd", "strum", @@ -1789,9 +2062,8 @@ dependencies = [ [[package]] name = "turso_ext" -version = "0.4.0-pre.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e03badf97da72c41c3289ac19245109096e6262017151dad23ecf7115ee433" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" dependencies = [ "chrono", "getrandom 0.3.4", @@ -1800,9 +2072,8 @@ dependencies = [ [[package]] name = "turso_macros" -version = "0.4.0-pre.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681754e341a0420494203b73e067b0b69b29ccf0852d0d24bc7d5255d4441dea" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" dependencies = [ "proc-macro2", "quote", @@ -1811,9 +2082,8 @@ dependencies = [ [[package]] name = "turso_parser" -version = "0.4.0-pre.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92dd528809dfb32facb949b9b5416a33ee8f856b444f882854c0835428f511dd" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" dependencies = [ "bitflags", "miette", @@ -1823,6 +2093,69 @@ dependencies = [ "turso_macros", ] +[[package]] +name = "turso_sdk_kit" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" +dependencies = [ + "bindgen", + "env_logger", + "tracing", + "tracing-appender", + "tracing-subscriber", + "turso_core", + "turso_sdk_kit_macros", +] + +[[package]] +name = "turso_sdk_kit_macros" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "turso_sync_engine" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" +dependencies = [ + "base64", + "bytes", + "genawaiter", + "http", + "libc", + "prost", + "roaring", + "serde", + "serde_json", + "thiserror 2.0.17", + "tracing", + "turso_core", + "turso_parser", + "uuid", +] + +[[package]] +name = "turso_sync_sdk_kit" +version = "0.4.0-pre.18" +source = "git+https://github.com/tursodatabase/turso?rev=bd2b3314a0d860ac8bde2fe560650f7d753591eb#bd2b3314a0d860ac8bde2fe560650f7d753591eb" +dependencies = [ + "bindgen", + "env_logger", + "genawaiter", + "parking_lot", + "tracing", + "tracing-appender", + "tracing-subscriber", + "turso_core", + "turso_sdk_kit", + "turso_sdk_kit_macros", + "turso_sync_engine", +] + [[package]] name = "twox-hash" version = "2.1.2" @@ -2012,6 +2345,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + [[package]] name = "winapi-util" version = "0.1.11" @@ -2080,13 +2425,22 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets", + "windows-targets 0.53.5", ] [[package]] @@ -2098,6 +2452,22 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + [[package]] name = "windows-targets" version = "0.53.5" @@ -2105,58 +2475,106 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_aarch64_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + [[package]] name = "windows_i686_gnu" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_i686_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnu" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "windows_x86_64_msvc" version = "0.53.1" diff --git a/sdk/rust/Cargo.toml b/sdk/rust/Cargo.toml index e2a3914..8ceccc9 100644 --- a/sdk/rust/Cargo.toml +++ b/sdk/rust/Cargo.toml @@ -6,7 +6,7 @@ description = "AgentFS SDK for Rust" license = "MIT" [dependencies] -turso = "0.4.0-pre.17" +turso = { version = "0.4.0", features = ["sync"] } tokio = { version = "1", features = ["full"] } async-trait = "0.1" serde = { version = "1.0", features = ["derive"] } diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs index c67d890..3ac9317 100644 --- a/sdk/rust/src/lib.rs +++ b/sdk/rust/src/lib.rs @@ -41,6 +41,39 @@ pub struct AgentFSOptions { } impl AgentFSOptions { + /// Validates an agent ID to prevent path traversal and ensure safe filesystem operations. + /// Returns true if the ID contains only alphanumeric characters, hyphens, and underscores. + pub fn validate_agent_id(id: &str) -> bool { + !id.is_empty() + && id + .chars() + .all(|c| c.is_alphanumeric() || c == '-' || c == '_') + } + pub fn db_path(&self) -> anyhow::Result { + // Determine database path: path takes precedence over id + if let Some(path) = &self.path { + // Custom path provided directly + Ok(path.to_string()) + } else if let Some(id) = &self.id { + // Validate agent ID to prevent path traversal attacks + if !Self::validate_agent_id(id) { + anyhow::bail!( + "Invalid agent ID '{}'. Agent IDs must contain only alphanumeric characters, hyphens, and underscores.", + id + ); + } + + // Ensure .agentfs directory exists + let agentfs_dir = agentfs_dir(); + if !agentfs_dir.exists() { + std::fs::create_dir_all(agentfs_dir)?; + } + Ok(format!("{}/{}.db", agentfs_dir.display(), id)) + } else { + // No id or path = ephemeral in-memory database + Ok(":memory:".to_string()) + } + } /// Create options for a persistent agent with the given ID pub fn with_id(id: impl Into) -> Self { Self { @@ -90,7 +123,7 @@ impl AgentFSOptions { } // First, check if it's a valid agent ID with an existing database in .agentfs/ - if AgentFS::validate_agent_id(&id_or_path) { + if AgentFSOptions::validate_agent_id(&id_or_path) { let db_path = agentfs_dir().join(format!("{}.db", id_or_path)); if db_path.exists() { return Ok(Self::with_path(db_path.to_str().ok_or_else(|| { @@ -105,7 +138,7 @@ impl AgentFSOptions { Ok(Self::with_path(id_or_path)) } else { // Not a valid agent and not an existing file - if AgentFS::validate_agent_id(&id_or_path) { + if AgentFSOptions::validate_agent_id(&id_or_path) { anyhow::bail!( "Agent '{}' not found at '{}'", id_or_path, @@ -161,38 +194,9 @@ impl AgentFS { anyhow::bail!("Base path is not a directory: {}", path.display()); } } - - // Determine database path: path takes precedence over id - let db_path = if let Some(path) = options.path { - // Custom path provided directly - path - } else if let Some(id) = options.id { - // Validate agent ID to prevent path traversal attacks - if !Self::validate_agent_id(&id) { - anyhow::bail!( - "Invalid agent ID '{}'. Agent IDs must contain only alphanumeric characters, hyphens, and underscores.", - id - ); - } - - // Ensure .agentfs directory exists - let agentfs_dir = agentfs_dir(); - if !agentfs_dir.exists() { - std::fs::create_dir_all(agentfs_dir)?; - } - format!("{}/{}.db", agentfs_dir.display(), id) - } else { - // No id or path = ephemeral in-memory database - ":memory:".to_string() - }; - + let db_path = options.db_path()?; let db = Builder::new_local(&db_path).build().await?; let conn = db.connect()?; - let conn = Arc::new(conn); - - let kv = KvStore::from_connection(conn.clone()).await?; - let fs = filesystem::AgentFS::from_connection(conn.clone()).await?; - let tools = ToolCalls::from_connection(conn.clone()).await?; // Initialize overlay schema if base is provided if let Some(base_path) = options.base { @@ -201,6 +205,16 @@ impl AgentFS { OverlayFS::init_schema(&conn, &base_path_str).await?; } + Self::open_with(conn).await + } + + pub async fn open_with(conn: Connection) -> Result { + let conn = Arc::new(conn); + + let kv = KvStore::from_connection(conn.clone()).await?; + let fs = filesystem::AgentFS::from_connection(conn.clone()).await?; + let tools = ToolCalls::from_connection(conn.clone()).await?; + Ok(Self { conn, kv, @@ -428,15 +442,6 @@ impl AgentFS { Err(_) => Ok(None), // Table doesn't exist } } - - /// Validates an agent ID to prevent path traversal and ensure safe filesystem operations. - /// Returns true if the ID contains only alphanumeric characters, hyphens, and underscores. - pub fn validate_agent_id(id: &str) -> bool { - !id.is_empty() - && id - .chars() - .all(|c| c.is_alphanumeric() || c == '-' || c == '_') - } } #[cfg(test)]