MigrateEntityStorage migrates legacy prompt entities to instruction storage idempotently. It reads prompts.json, converts each entity's Kind from "prompt" to "instruction", and writes them to instructions.json. The prompts.json file is left untouched. If instructions.json already exists or prompts.j
()
| 200 | // prompts.json file is left untouched. If instructions.json already exists or |
| 201 | // prompts.json does not exist, no migration is performed. |
| 202 | func MigrateEntityStorage() error { |
| 203 | dir := pathutil.ConfigDir() |
| 204 | oldPath := filepath.Join(dir, "prompts.json") |
| 205 | newPath := filepath.Join(dir, "instructions.json") |
| 206 | |
| 207 | if _, err := os.Stat(newPath); err == nil { |
| 208 | return nil |
| 209 | } |
| 210 | |
| 211 | raw, err := os.ReadFile(oldPath) |
| 212 | if err != nil { |
| 213 | if os.IsNotExist(err) { |
| 214 | return nil |
| 215 | } |
| 216 | return fmt.Errorf("entities: read %s: %w", oldPath, err) |
| 217 | } |
| 218 | if len(raw) == 0 { |
| 219 | return nil |
| 220 | } |
| 221 | |
| 222 | entitiesByName := map[string]Entity{} |
| 223 | if err := json.Unmarshal(raw, &entitiesByName); err != nil { |
| 224 | return fmt.Errorf("entities: parse %s: %w", oldPath, err) |
| 225 | } |
| 226 | for name, entity := range entitiesByName { |
| 227 | entity.Kind = KindInstruction |
| 228 | entitiesByName[name] = entity |
| 229 | } |
| 230 | |
| 231 | if err := os.MkdirAll(dir, 0o755); err != nil { |
| 232 | return fmt.Errorf("entities: mkdir %s: %w", dir, err) |
| 233 | } |
| 234 | data, err := json.MarshalIndent(entitiesByName, "", " ") |
| 235 | if err != nil { |
| 236 | return fmt.Errorf("entities: marshal migrated instructions: %w", err) |
| 237 | } |
| 238 | data = append(data, '\n') |
| 239 | if err := os.WriteFile(newPath, data, 0o600); err != nil { |
| 240 | return fmt.Errorf("entities: write %s: %w", newPath, err) |
| 241 | } |
| 242 | return nil |
| 243 | } |