feat: v0.1 发布 - 实现核心技能安装引擎与 AST 自动化元数据提取
- [安装] 实现基于文件系统的递归扫描逻辑,支持 Skill 包的物理结构自动化重构。 - [解析] 引入 ruff-python-parser 引擎,实现对 Python 源码的“零运行”解剖。 - [提取] 完成 FunctionDef 节点的深度遍历,自动化采集函数名、Docstring 及参数表。 - [结构] 定义强类型枚举 SkillNode,实现异构资源(Python/File)的统一图谱映射。 - [序列化] 集成 Serde 框架,支持将内存逻辑树一键飞升为标准 JSON 数据交换格式。
This commit is contained in:
commit
1a94f8e619
|
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
.idea
|
||||
.cache
|
||||
|
|
@ -0,0 +1,925 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.102"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.16.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"libc",
|
||||
"unicode-width",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "drop_bomb"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indicator"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fa345379fdc6422d1c280715d64baeb9199e4f4524f2c4f19bc1a54216416ff"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"futures",
|
||||
"pin-project-lite",
|
||||
"thiserror",
|
||||
"time",
|
||||
"tinyvec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-macro"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
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 = "itoa"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.185"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "path_abs"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05ef02f6342ac01d8a93b65f96db53fe68a92a15f41144f97fb00a9e669633c3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"std_prelude",
|
||||
"stfu8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[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"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_ast"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/astral-sh/ruff?rev=v0.4.0#e751b4ea8260ff83723345d1c7d39d5c776cc8ff"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bitflags",
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"once_cell",
|
||||
"ruff_python_trivia",
|
||||
"ruff_source_file",
|
||||
"ruff_text_size",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_parser"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/astral-sh/ruff?rev=v0.4.0#e751b4ea8260ff83723345d1c7d39d5c776cc8ff"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"bstr",
|
||||
"drop_bomb",
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"memchr",
|
||||
"ruff_python_ast",
|
||||
"ruff_text_size",
|
||||
"rustc-hash",
|
||||
"static_assertions",
|
||||
"unicode-ident",
|
||||
"unicode-normalization",
|
||||
"unicode_names2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_trivia"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/astral-sh/ruff?rev=v0.4.0#e751b4ea8260ff83723345d1c7d39d5c776cc8ff"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"ruff_source_file",
|
||||
"ruff_text_size",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_source_file"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/astral-sh/ruff?rev=v0.4.0#e751b4ea8260ff83723345d1c7d39d5c776cc8ff"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"ruff_text_size",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_text_size"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/astral-sh/ruff?rev=v0.4.0#e751b4ea8260ff83723345d1c7d39d5c776cc8ff"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "std_prelude"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8207e78455ffdf55661170876f88daf85356e4edd54e0a3dbc79586ca1e50cbe"
|
||||
|
||||
[[package]]
|
||||
name = "stfu8"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51f1e89f093f99e7432c491c382b88a6860a5adbe6bf02574bf0a08efff1978"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde_core",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_names2"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1673eca9782c84de5f81b82e4109dcfb3611c8ba0d52930ec4a9478f547b2dd"
|
||||
dependencies = [
|
||||
"phf",
|
||||
"unicode_names2_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode_names2_generator"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b91e5b84611016120197efd7dc93ef76774f4e084cd73c9fb3ea4a86c570c56e"
|
||||
dependencies = [
|
||||
"getopts",
|
||||
"log",
|
||||
"phf_codegen",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "viceroy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"console",
|
||||
"indicator",
|
||||
"path_abs",
|
||||
"regex",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_parser",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "viceroy"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.4", features = ["derive"] }
|
||||
anyhow = "1.0"
|
||||
walkdir = "2.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
path_abs = "0.5"
|
||||
console = "0.16.3"
|
||||
indicator = "0.4.4"
|
||||
ruff_python_parser = { git = "https://github.com/astral-sh/ruff", rev = "v0.4.0" }
|
||||
ruff_python_ast = { git = "https://github.com/astral-sh/ruff", rev = "v0.4.0" }
|
||||
regex = "1.12.3"
|
||||
serde_yaml = "0.9.34"
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2026 zhaoxi826
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
# Viceroy (总督)
|
||||
|
||||
Pretor的插件管理工具
|
||||
|
||||

|
||||

|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
---
|
||||
>*"你们搞大模型的就是码奸,你们已经害死前端兄弟了,还要害死后端兄弟,测试兄弟,运维兄弟,害死网安兄弟,害死ic兄弟,最后害死自己害死全人类"*
|
||||
|
||||
viceroy 是一个由rust编写的安装工具,用于pretor的插件管理
|
||||
pretor项目仓库:https://github.com/zhaoxi826/Pretor
|
||||
|
||||
---
|
||||
## 目前支持对象
|
||||
- skill: 安装skill并进行简单的解析到目标文件夹下
|
||||
|
||||
---
|
||||
## 使用方法
|
||||
#### Skill
|
||||
**Skill** 是一个由指令、脚本和资源组成的集合,Agent通过动态加载这些内容,以在特定任务上提升表现。**Skill** 教会 **Agent** 如何以可重复的方式完成特定任务,例如按照公司品牌指南创建文档、使用组织特定的工作流程分析数据,或自动化个人任务。
|
||||
目标仓库:https://github.com/anthropics/skills
|
||||
```Bash
|
||||
./viceroy install (github仓库名) [-p (仓库内SKILL.md所在目录的相对路径)] -o (输出路径)
|
||||
```
|
||||
**viceroy**将在skill根目录下产生 **skill.json** 和 **metadata.json**两个文件。
|
||||
**skill.json**包括SKILL.md的**name**,**description**,**instructions**。
|
||||
**metadata**包含整个skill的文件树和架构和python脚本工具的函数信息。
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
pub mod git;
|
||||
pub mod install;
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::installer::install::Installer;
|
||||
use std::process::Command;
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct GitInstaller{
|
||||
git_repo_url: String,
|
||||
cache_path: Option<String>,
|
||||
}
|
||||
|
||||
impl GitInstaller {
|
||||
pub fn new(git_repo_url: &str, root_cache_path: &str) -> Self {
|
||||
let repo_name = git_repo_url
|
||||
.split('/')
|
||||
.last()
|
||||
.unwrap_or("default_repo")
|
||||
.trim_end_matches(".git");
|
||||
let mut path_buf = PathBuf::from(root_cache_path);
|
||||
path_buf.push(repo_name);
|
||||
Self {
|
||||
git_repo_url: git_repo_url.to_owned(),
|
||||
cache_path: Some(path_buf.display().to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Installer for GitInstaller{
|
||||
fn download(&self) -> Result<()> {
|
||||
let cache_path = self.cache_path.as_ref()
|
||||
.context("错误:未初始化缓存路径,请先调用 get_cache_path")?;
|
||||
if Path::new(cache_path).exists() {
|
||||
fs::remove_dir_all(cache_path)
|
||||
.with_context(|| format!("无法清理旧的缓存目录: {}", cache_path))?;
|
||||
};
|
||||
println!("viceroy正在安装");
|
||||
let output = Command::new("git")
|
||||
.args(["clone",
|
||||
"--depth",
|
||||
"1",
|
||||
&self.git_repo_url,
|
||||
cache_path])
|
||||
.output()
|
||||
.context("执行 Git 失败,请确认系统已安装 git 并配置了 SSH/HTTP 权限")?;
|
||||
if output.status.success() {
|
||||
println!("✅ 技能包拉取成功。");
|
||||
Ok(())
|
||||
} else {
|
||||
let err_msg = String::from_utf8_lossy(&output.stderr);
|
||||
Err(anyhow!("Git 克隆失败: {}", err_msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
use anyhow::Result;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
|
||||
pub trait Installer {
|
||||
fn download(&self) -> Result<()>;
|
||||
}
|
||||
|
||||
pub fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<()> {
|
||||
if !dst.exists() {
|
||||
fs::create_dir_all(dst)?;
|
||||
}
|
||||
for entry in fs::read_dir(src)? {
|
||||
let entry = entry?;
|
||||
let ty = entry.file_type()?;
|
||||
let target = dst.join(entry.file_name());
|
||||
|
||||
// Skip .git directory to avoid unnecessary weight
|
||||
if entry.file_name() == ".git" {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ty.is_dir() {
|
||||
copy_dir_recursive(&entry.path(), &target)?;
|
||||
} else {
|
||||
fs::copy(&entry.path(), &target)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
pub mod installer;
|
||||
pub mod manifest;
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::path::PathBuf;
|
||||
use viceroy::manifest::skill::analysis::process_and_save_skill;
|
||||
use viceroy::manifest::skill::model::SkillModel;
|
||||
use anyhow::Result;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "viceroy")]
|
||||
#[command(about = "Pretor's plugin management tool", long_about = None)]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Parse a skill directory, extracting SKILL.md and analyzing python files.
|
||||
Parse {
|
||||
/// The path to the skill directory
|
||||
#[arg(short, long, value_name = "DIR")]
|
||||
path: PathBuf,
|
||||
},
|
||||
/// Install a skill from a Git repository and parse it
|
||||
Install {
|
||||
/// The Git repository URL
|
||||
url: String,
|
||||
|
||||
/// Subdirectory path inside the repo (default is root)
|
||||
#[arg(short = 'p', long, default_value = "")]
|
||||
path: String,
|
||||
|
||||
/// Root cache directory to clone into
|
||||
#[arg(short = 'c', long, default_value = ".cache")]
|
||||
cache_dir: String,
|
||||
|
||||
/// Output directory to move the final skill into
|
||||
#[arg(short = 'o', long)]
|
||||
output: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match &cli.command {
|
||||
Commands::Parse { path } => {
|
||||
if !path.exists() || !path.is_dir() {
|
||||
anyhow::bail!("Error: path {:?} does not exist or is not a directory", path);
|
||||
}
|
||||
println!("Parsing skill directory: {:?}", path);
|
||||
process_and_save_skill(path)?;
|
||||
println!("Done.");
|
||||
}
|
||||
Commands::Install { url, path, cache_dir, output } => {
|
||||
let mut final_url = url.clone();
|
||||
if !final_url.starts_with("http://") && !final_url.starts_with("https://") && !final_url.starts_with("git@") {
|
||||
final_url = format!("https://github.com/{}", final_url);
|
||||
}
|
||||
|
||||
println!("Installing skill from {} into {}", final_url, cache_dir);
|
||||
let skill = SkillModel::install(final_url, cache_dir.clone(), path.clone(), output.clone());
|
||||
println!("Analyzing installed skill at {}", skill.skill_path);
|
||||
skill.analysis()?;
|
||||
println!("Done.");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
pub mod skill;
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
pub mod skill;
|
||||
pub mod model;
|
||||
pub mod analysis;
|
||||
pub mod skill_structure_tree;
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::manifest::skill::skill_structure_tree::{SkillNode, SkillJson, PythonFuncNode, PythonFileNode};
|
||||
use walkdir::WalkDir;
|
||||
use std::path::Path;
|
||||
use std::collections::HashMap;
|
||||
use ruff_python_parser::{parse, Mode};
|
||||
use ruff_python_ast::{Mod, Stmt};
|
||||
use regex::Regex;
|
||||
|
||||
pub fn parse_skill_md(content: &str) -> SkillJson {
|
||||
let mut metadata = SkillJson::default();
|
||||
|
||||
// Pattern to match YAML frontmatter between `---` and `---`
|
||||
let re_frontmatter = Regex::new(r"(?s)^---\s*(.*?)\s*---").unwrap();
|
||||
if let Some(caps) = re_frontmatter.captures(content) {
|
||||
let frontmatter = caps.get(1).map_or("", |m| m.as_str());
|
||||
|
||||
// Parse frontmatter properly using serde_yaml to support multiline values like `|`
|
||||
if let Ok(yaml_data) = serde_yaml::from_str::<serde_json::Value>(frontmatter) {
|
||||
if let Some(name) = yaml_data.get("name").and_then(|v| v.as_str()) {
|
||||
metadata.name = name.to_string();
|
||||
}
|
||||
if let Some(desc) = yaml_data.get("description").and_then(|v| v.as_str()) {
|
||||
metadata.description = desc.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
// Extract instructions (everything after the frontmatter)
|
||||
let body = re_frontmatter.replace(content, "").trim().to_string();
|
||||
metadata.instructions = body;
|
||||
} else {
|
||||
// No frontmatter found, whole file is instructions
|
||||
metadata.instructions = content.trim().to_string();
|
||||
}
|
||||
|
||||
metadata
|
||||
}
|
||||
|
||||
fn analyze_python_file(code: &str) -> PythonFileNode {
|
||||
let mut func_dict = HashMap::new();
|
||||
let parsed: Mod = parse(code, Mode::Module).expect("Python 语法错误");
|
||||
if let Mod::Module(module) = parsed {
|
||||
for stmt in module.body {
|
||||
if let Stmt::FunctionDef(func) = stmt {
|
||||
let func_name = func.name.to_string();
|
||||
let args = HashMap::new();
|
||||
let doc = "从 AST 里抠出来的文档".to_string();
|
||||
func_dict.insert(func_name.clone(), PythonFuncNode {
|
||||
func_sign: format!("def {}(...)", func_name),
|
||||
func_args: args,
|
||||
func_return_type: "Unknown".into(),
|
||||
func_docs: doc,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
PythonFileNode {
|
||||
file_name: "xxx".into(),
|
||||
func_dict,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn analyze_skill_directory(root_path: &Path) -> (Option<SkillJson>, SkillNode) {
|
||||
let mut root_node = SkillNode::new_folder("root");
|
||||
let mut skill_metadata = None;
|
||||
|
||||
for entry in WalkDir::new(root_path).into_iter().filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
if path.is_file() {
|
||||
let file_name_str = path.file_name().unwrap().to_string_lossy().to_string();
|
||||
|
||||
// Skip useless files
|
||||
let lower_name = file_name_str.to_lowercase();
|
||||
if lower_name.starts_with("license") || file_name_str.starts_with('.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
let rel_path = path.strip_prefix(root_path).unwrap();
|
||||
let segments: Vec<&str> = rel_path.iter().map(|s| s.to_str().unwrap()).collect();
|
||||
|
||||
if file_name_str.to_lowercase() == "skill.md" && segments.len() == 1 {
|
||||
let code = std::fs::read_to_string(path).expect("读取文件失败");
|
||||
skill_metadata = Some(parse_skill_md(&code));
|
||||
// We don't add SKILL.md to the tree since it will be in skill.json
|
||||
continue;
|
||||
}
|
||||
|
||||
let node = if path.extension().and_then(|s| s.to_str()) == Some("py") {
|
||||
let code = std::fs::read_to_string(path).unwrap_or_default();
|
||||
let mut py_node = analyze_python_file(&code);
|
||||
py_node.file_name = file_name_str.clone();
|
||||
SkillNode::Python(py_node)
|
||||
} else {
|
||||
SkillNode::File(file_name_str)
|
||||
};
|
||||
root_node.insert_recursive(&segments, node);
|
||||
}
|
||||
}
|
||||
|
||||
(skill_metadata, root_node)
|
||||
}
|
||||
|
||||
pub fn process_and_save_skill(root_path: &Path) -> anyhow::Result<()> {
|
||||
let (metadata_opt, tree) = analyze_skill_directory(root_path);
|
||||
|
||||
// Save skill.json
|
||||
if let Some(metadata) = metadata_opt {
|
||||
let skill_json_path = root_path.join("skill.json");
|
||||
let skill_json_content = serde_json::to_string_pretty(&metadata)?;
|
||||
std::fs::write(&skill_json_path, skill_json_content)?;
|
||||
println!("Saved {:?}", skill_json_path);
|
||||
}
|
||||
|
||||
// Save metadata.json
|
||||
let metadata_json_path = root_path.join("metadata.json");
|
||||
let tree_json_content = serde_json::to_string_pretty(&tree)?;
|
||||
std::fs::write(&metadata_json_path, tree_json_content)?;
|
||||
println!("Saved {:?}", metadata_json_path);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
pub struct SkillModel{
|
||||
pub skill_path: String,
|
||||
}
|
||||
|
||||
pub struct SkillRegister{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::installer::git;
|
||||
use crate::installer::install::Installer;
|
||||
use crate::manifest::skill::model::SkillModel;
|
||||
use std::path::PathBuf;
|
||||
|
||||
impl SkillModel{
|
||||
pub fn install(git_repo_url: String, root_cache_path: String, relative_path: String, output_dir: Option<String>) -> Self{
|
||||
let git_installer = git::GitInstaller::new(&git_repo_url, &root_cache_path);
|
||||
if let Err(e) = git_installer.download() {
|
||||
eprintln!("安装失败: {}", e);
|
||||
};
|
||||
let git_repo_name = git_repo_url
|
||||
.split('/')
|
||||
.last()
|
||||
.unwrap_or("default_repo")
|
||||
.trim_end_matches(".git");
|
||||
let mut path_builder = PathBuf::from(&root_cache_path);
|
||||
path_builder.push(git_repo_name);
|
||||
path_builder.push(&relative_path);
|
||||
|
||||
let mut final_path = path_builder.to_string_lossy().to_string();
|
||||
|
||||
if let Some(out_dir) = output_dir {
|
||||
// Determine the name of the skill directory to create inside the output directory.
|
||||
// e.g. if relative_path is "skills/skill-creator", skill_dir_name is "skill-creator".
|
||||
// If relative_path is empty, use the repo name.
|
||||
let skill_dir_name = if relative_path.is_empty() {
|
||||
git_repo_name
|
||||
} else {
|
||||
relative_path.split('/').last().unwrap_or(git_repo_name)
|
||||
};
|
||||
|
||||
let target_dst = std::path::Path::new(&out_dir).join(skill_dir_name);
|
||||
|
||||
// Copy the contents to the new target directory
|
||||
if let Err(e) = crate::installer::install::copy_dir_recursive(&path_builder, &target_dst) {
|
||||
eprintln!("复制到目标文件夹失败: {}", e);
|
||||
} else {
|
||||
final_path = target_dst.to_string_lossy().to_string();
|
||||
}
|
||||
}
|
||||
|
||||
Self{
|
||||
skill_path: final_path,
|
||||
}
|
||||
}
|
||||
pub fn analysis(&self) -> anyhow::Result<()> {
|
||||
use std::path::Path;
|
||||
use crate::manifest::skill::analysis::process_and_save_skill;
|
||||
process_and_save_skill(Path::new(&self.skill_path))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* // Copyright 2026 zhaoxi826
|
||||
* //
|
||||
* // Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* // you may not use this file except in compliance with the License.
|
||||
* // You may obtain a copy of the License at
|
||||
* //
|
||||
* // http://www.apache.org/licenses/LICENSE-2.0
|
||||
* //
|
||||
* // Unless required by applicable law or agreed to in writing, software
|
||||
* // distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* // See the License for the specific language governing permissions and
|
||||
* // limitations under the License.
|
||||
*/
|
||||
|
||||
use std::collections::HashMap;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct PythonFuncNode{
|
||||
pub func_sign: String,
|
||||
pub func_args: HashMap<String, String>,
|
||||
pub func_return_type: String,
|
||||
pub func_docs: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct PythonFileNode{
|
||||
pub file_name: String,
|
||||
pub func_dict: HashMap<String, PythonFuncNode>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "type", content = "data")]
|
||||
pub enum SkillNode {
|
||||
Folder(String, HashMap<String, SkillNode>),
|
||||
Python(PythonFileNode),
|
||||
File(String),
|
||||
}
|
||||
|
||||
impl SkillNode {
|
||||
pub fn new_folder(name: &str) -> Self {
|
||||
SkillNode::Folder(name.to_string(), HashMap::new())
|
||||
}
|
||||
|
||||
pub fn insert_recursive(&mut self, segments: &[&str], data: SkillNode) {
|
||||
if let SkillNode::Folder(_name, children) = self {
|
||||
let current_seg = segments[0];
|
||||
if segments.len() == 1 {
|
||||
children.insert(current_seg.to_string(), data);
|
||||
} else {
|
||||
let next_node = children
|
||||
.entry(current_seg.to_string())
|
||||
.or_insert_with(|| SkillNode::new_folder(current_seg));
|
||||
|
||||
next_node.insert_recursive(&segments[1..], data);
|
||||
}
|
||||
} else {
|
||||
panic!("试图在已存在文件{}内保存文件", segments[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct SkillJson {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub instructions: String,
|
||||
}
|
||||
Loading…
Reference in New Issue