using System.IO; using System.Text; using UnityEditor.Build; using UnityEditor.Build.Reporting; using UnityEngine; using OnDeviceAgent.AgentCore; namespace OnDeviceAgent.AgentCore.Editor { // StreamingAssets directories can't be enumerated at runtime on Android/WebGL (compressed APK/bundle), // so FileStreamingAssetReader discovers skill folders from a per-"skills"-dir manifest (dir_manifest.txt) // instead. Regenerate those manifests before every build so on-device skill discovery always matches the // folders actually shipped, no hand-maintenance or drift. public sealed class SkillsManifestPreprocessor : IPreprocessBuildWithReport { public int callbackOrder => 0; public void OnPreprocessBuild(BuildReport report) => GenerateAll(); static void GenerateAll() { var root = Application.streamingAssetsPath; if (!Directory.Exists(root)) return; // StreamingAssets is copied to the player from disk as-is, so writing the manifest here (before // the copy step) is enough, no AssetDatabase.Refresh needed (and it's unsafe mid-build). foreach (var skillsDir in Directory.GetDirectories(root, "skills", SearchOption.AllDirectories)) WriteManifest(skillsDir); } // Lists the immediate subdirectory names of one "skills" folder. Only rewrites on change so we don't // churn the build's StreamingAssets on every build. static void WriteManifest(string skillsDir) { var sb = new StringBuilder(); sb.AppendLine("# auto-generated by SkillsManifestPreprocessor, one skill folder name per line."); sb.AppendLine("# Regenerated before each build; hand-edits are overwritten."); foreach (var sub in Directory.GetDirectories(skillsDir)) sb.AppendLine(Path.GetFileName(sub)); var manifestPath = Path.Combine(skillsDir, FileStreamingAssetReader.DirManifestFile); var next = sb.ToString(); if (File.Exists(manifestPath) && File.ReadAllText(manifestPath) == next) return; File.WriteAllText(manifestPath, next); Debug.Log("[SkillsManifest] wrote " + manifestPath); } } }