MCPcopy Create free account
hub / github.com/ScriptedAlchemy/tracedecay / generate_skill_bundle

Function generate_skill_bundle

build.rs:364–409  ·  view source on GitHub ↗

Generates `$OUT_DIR/plugin_bundle_generated.rs`: a recursive manifest of every file under `plugin/skills/` (SKILL.md *and* any `references/`, `scripts/`, `assets/` support files), embedded via `include_str!` at compile time. Moving embedding off a hand-maintained flat list lets skills ship support files without a matching table edit; the coverage tests assert the generated set equals the on-disk t

()

Source from the content-addressed store, hash-verified

362/// generated slice serves Claude, Codex, and Cursor (Cursor filters out the
363/// `tracedecay-*` dispatcher skills at compose time).
364fn generate_skill_bundle() {
365 let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR");
366 let skills_root = Path::new(&manifest_dir).join("plugin/skills");
367 println!("cargo::rerun-if-changed=plugin/skills");
368
369 let mut code = String::new();
370 code.push_str(
371 "// @generated by build.rs (generate_skill_bundle). Do not edit.\n\
372 /// Every file under `plugin/skills/` (SKILL.md + support files), embedded\n\
373 /// recursively at compile time. `relative` is the deploy path (identical to\n\
374 /// the `plugin/`-relative source path).\n\
375 pub const GENERATED_SKILL_FILES: &[PluginFile] = &[\n",
376 );
377 for relative in collect_files_relative(&skills_root) {
378 // rerun on each individual file so edits re-trigger codegen even if the
379 // directory mtime does not change.
380 println!("cargo::rerun-if-changed=plugin/skills/{relative}");
381 // Every embedded file goes through `include_str!`, which only accepts
382 // UTF-8. A binary support file (e.g. `assets/*.png`) would otherwise
383 // fail to compile with an opaque "stream did not contain valid UTF-8"
384 // error pointing at the generated file, not the offending asset. Guard
385 // it here with a clear message; binary support files are not embeddable
386 // yet (add `include_bytes!` handling when that becomes a requirement).
387 let abs = skills_root.join(&relative);
388 if !is_probably_utf8_text(&abs) {
389 panic!(
390 "plugin/skills/{relative} is not a UTF-8 text file. The skill bundle codegen \
391 embeds every file via include_str!, so binary support files (e.g. images) are \
392 not embeddable yet. Remove the binary file or add include_bytes! support to \
393 build.rs (generate_skill_bundle)."
394 );
395 }
396 let deploy = format!("skills/{relative}");
397 let source = format!("skills/{relative}");
398 code.push_str(&format!(
399 " PluginFile {{ relative: {deploy:?}, contents: include_str!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/plugin/{source}\")) }},\n"
400 ));
401 }
402 code.push_str("];\n");
403
404 let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR");
405 let out_path = Path::new(&out_dir).join("plugin_bundle_generated.rs");
406 if let Err(e) = fs::write(&out_path, code) {
407 panic!("failed to write {}: {e}", out_path.display());
408 }
409}
410
411fn main() {
412 generate_skill_bundle();

Callers 1

mainFunction · 0.85

Calls 3

collect_files_relativeFunction · 0.85
is_probably_utf8_textFunction · 0.85
writeFunction · 0.85

Tested by

no test coverage detected