<!-- Generated by SpecStory, Markdown v2.1.0 -->

# 2026-03-10 17:03:21Z

<!-- cursoride Session 7d4946a5-6831-4e4c-90f7-8e9a96fa62d5 (2026-03-10 17:03:21Z) -->

_**User**_

Update the DLM_OT_migrator_remove_original operator in T:\Dynamic-Link-Manager\ui\operators.py to:

1. **Purge actions from the original character**: Before removing the collection, find all actions associated with the original character (through animation_data, NLA strips, etc.) and remove them from bpy.data.actions

2. **Remove .rep suffix from replacement actions**: After the original is removed, find all actions on the replacement character that have ".rep" in their name and rename them to remove that suffix.

The current execute method structure:
```python
def execute(self, context):
    orig, rep = _get_migrator_pair(context)
    if not orig:
        self.report({"WARNING"}, "No original character selected")
        return {"CANCELLED"}
    if orig == rep:
        self.report({"ERROR"}, "Original and replacement cannot be the same object")
        return {"CANCELLED"}

    name = orig.name
    try:
        # Try to find and delete the collection containing the original character
        coll = collection_containing_armature(orig)
        if coll:
            coll_name = coll.name
            context.scene.dynamic_link_manager.original_character = None
            try:
                bpy.data.collections.remove(coll)
                self.report({"INFO"}, f"Removed collection: {coll_name}")
            except Exception as remove_err:
                self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
        else:
            # Fallback: just delete the armature object
            bpy.data.objects.remove(orig, do_unlink=True)
            context.scene.dynamic_link_manager.original_character = None
            self.report({"INFO"}, f"Removed original character: {name}")
    except Exception as e:
        self.report({"ERROR"}, f"Failed to remove original: {e}")
        return {"CANCELLED"}
    return {"FINISHED"}
```

Add logic to:
1. Before removing the collection, iterate through the original's animation_data (if any) and collect all actions from NLA strips and the active action
2. Remove those actions from bpy.data.actions
3. After removing the original, iterate through the replacement's animation_data and find actions with ".rep" suffix
4. Rename those actions to remove the ".rep" suffix

Make sure to handle cases where animation_data might be None.

---

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The user wants me to update an operator in a Blender addon. Let me first read the current file to understand the context and find the `DLM_OT_migrator_remove_original` operator.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: cat "T:\Dynamic-Link-Manager\ui\operators.py"</summary>

```bash
cat "T:\Dynamic-Link-Manager\ui\operators.py"
```

```
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.

import bpy
import os
from bpy.types import Operator
from bpy.props import StringProperty, BoolProperty
from bpy.props import StringProperty, IntProperty

from ..utils import collection_containing_armature

ADDON_NAME = __package__.rsplit(".", 1)[0] if "." in __package__ else __package__


def _prefs(context):
    return context.preferences.addons.get(ADDON_NAME)


class DLM_OT_replace_linked_asset(Operator):
    bl_idname = "dlm.replace_linked_asset"
    bl_label = "Replace Linked Asset"
    bl_description = "Open file browser to replace the linked asset with another file"
    bl_options = {"REGISTER", "UNDO"}
    filepath: StringProperty(name="File Path", description="Path to the new asset file", subtype="FILE_PATH")

    def execute(self, context):
        obj = context.active_object
        if not obj:
            self.report({"ERROR"}, "No object selected")
            return {"CANCELLED"}
        if getattr(obj, "library", None):
            self.report({"INFO"}, f"Object '{obj.name}' is linked from: {obj.library.filepath}")
            return {"FINISHED"}
        if obj.data and getattr(obj.data, "library", None) and obj.data.library:
            self.report({"INFO"}, f"Object '{obj.name}' has linked data from: {obj.data.library.filepath}")
            return {"FINISHED"}
        if obj.type == "ARMATURE" and obj.data and obj.data.name in bpy.data.armatures:
            ad = bpy.data.armatures[obj.data.name]
            if getattr(ad, "library", None) and ad.library:
                self.report({"INFO"}, f"Armature '{obj.name}' data is linked from: {ad.library.filepath}")
                return {"FINISHED"}
        self.report({"ERROR"}, "Selected object is not a linked asset")
        return {"CANCELLED"}

    def invoke(self, context, event):
        context.window_manager.fileselect_add(self)
        return {"RUNNING_MODAL"}


class DLM_OT_scan_linked_assets(Operator):
    bl_idname = "dlm.scan_linked_assets"
    bl_label = "Scan Linked Libraries"
    bl_description = "Scan the current file for linked libraries and list their status"
    bl_options = {"REGISTER"}

    def execute(self, context):
        from ..ops import library

        return library.scan_linked_assets(context, self.report)


class DLM_OT_find_libraries_in_folders(Operator):
    bl_idname = "dlm.find_libraries_in_folders"
    bl_label = "Find Libraries in Folders"
    bl_description = "Search addon search paths for missing library blend files"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        from ..ops import library

        return library.find_libraries_in_folders(context, self.report, ADDON_NAME)


class DLM_OT_open_linked_file(Operator):
    bl_idname = "dlm.open_linked_file"
    bl_label = "Open Linked File"
    bl_description = "Open the selected linked blend file in a new Blender instance"
    bl_options = {"REGISTER"}
    filepath: StringProperty(name="File Path", default="")

    def execute(self, context):
        if not self.filepath:
            self.report({"ERROR"}, "No file path specified")
            return {"CANCELLED"}
        try:
            bpy.ops.wm.path_open(filepath=self.filepath)
            self.report({"INFO"}, f"Opening linked file: {self.filepath}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to open linked file: {e}")
            return {"CANCELLED"}
        return {"FINISHED"}


class DLM_OT_add_search_path(Operator):
    bl_idname = "dlm.add_search_path"
    bl_label = "Add Search Path"
    bl_description = "Add a new folder to the list of search paths for finding libraries"
    bl_options = {"REGISTER"}

    def execute(self, context):
        prefs = _prefs(context)
        if prefs:
            p = prefs.preferences.search_paths.add()
            p.path = "//"
            self.report({"INFO"}, f"Added search path: {p.path}")
        return {"FINISHED"}


class DLM_OT_remove_search_path(Operator):
    bl_idname = "dlm.remove_search_path"
    bl_label = "Remove Search Path"
    bl_description = "Remove the selected search path from the list"
    bl_options = {"REGISTER"}
    index: IntProperty(name="Index", default=0)

    def execute(self, context):
        prefs = _prefs(context)
        if prefs and prefs.preferences.search_paths and 0 &lt;= self.index &lt; len(prefs.preferences.search_paths):
            prefs.preferences.search_paths.remove(self.index)
            self.report({"INFO"}, f"Removed search path at index {self.index}")
        return {"FINISHED"}


class DLM_OT_attempt_relink(Operator):
    bl_idname = "dlm.attempt_relink"
    bl_label = "Attempt Relink"
    bl_description = "Try to relink missing libraries using the configured search paths"
    bl_options = {"REGISTER"}

    def execute(self, context):
        from ..ops import library

        return library.attempt_relink(context, self.report, ADDON_NAME)


class DLM_OT_browse_search_path(Operator):
    bl_idname = "dlm.browse_search_path"
    bl_label = "Browse Search Path"
    bl_description = "Browse to set the folder for the selected search path"
    bl_options = {"REGISTER"}
    index: IntProperty(name="Index", default=0)
    filepath: StringProperty(name="Search Path", subtype="DIR_PATH")

    def execute(self, context):
        prefs = _prefs(context)
        if prefs and prefs.preferences.search_paths and 0 &lt;= self.index &lt; len(prefs.preferences.search_paths):
            prefs.preferences.search_paths[self.index].path = self.filepath
            self.report({"INFO"}, f"Updated search path {self.index + 1}: {self.filepath}")
        return {"FINISHED"}

    def invoke(self, context, event):
        prefs = _prefs(context)
        if prefs and prefs.preferences.search_paths and 0 &lt;= self.index &lt; len(prefs.preferences.search_paths):
            self.filepath = prefs.preferences.search_paths[self.index].path
        context.window_manager.fileselect_add(self)
        return {"RUNNING_MODAL"}


class DLM_OT_reload_libraries(Operator):
    bl_idname = "dlm.reload_libraries"
    bl_label = "Reload Libraries"
    bl_description = "Reload all linked libraries (or fallback manual reload)"
    bl_options = {"REGISTER"}

    def execute(self, context):
        try:
            bpy.ops.outliner.lib_operation(type="RELOAD")
            self.report({"INFO"}, "Library reload operation completed")
        except Exception:
            try:
                for lib in bpy.data.libraries:
                    if lib.filepath and os.path.exists(bpy.path.abspath(lib.filepath)):
                        lib.reload()
                self.report({"INFO"}, "Libraries reloaded manually")
            except Exception as e:
                self.report({"ERROR"}, f"Failed to reload libraries: {e}")
                return {"CANCELLED"}
        return {"FINISHED"}


class DLM_OT_make_paths_relative(Operator):
    bl_idname = "dlm.make_paths_relative"
    bl_label = "Make Paths Relative"
    bl_description = "Convert all internal file paths to relative"
    bl_options = {"REGISTER"}

    def execute(self, context):
        try:
            bpy.ops.file.make_paths_relative()
            self.report({"INFO"}, "All file paths made relative")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to make paths relative: {e}")
            return {"CANCELLED"}
        return {"FINISHED"}


class DLM_OT_make_paths_absolute(Operator):
    bl_idname = "dlm.make_paths_absolute"
    bl_label = "Make Paths Absolute"
    bl_description = "Convert all internal file paths to absolute"
    bl_options = {"REGISTER"}

    def execute(self, context):
        try:
            bpy.ops.file.make_paths_absolute()
            self.report({"INFO"}, "All file paths made absolute")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to make paths absolute: {e}")
            return {"CANCELLED"}
        return {"FINISHED"}


class DLM_OT_relocate_single_library(Operator):
    bl_idname = "dlm.relocate_single_library"
    bl_label = "Relocate Library"
    bl_description = "Point the selected library to a new blend file and reload"
    bl_options = {"REGISTER", "UNDO"}
    target_filepath: StringProperty(name="Current Library Path", default="")
    filepath: StringProperty(name="New Library File", subtype="FILE_PATH", default="")

    def execute(self, context):
        if not self.target_filepath or not self.filepath:
            self.report({"ERROR"}, "No target or new file specified")
            return {"CANCELLED"}
        abs_match = bpy.path.abspath(self.target_filepath) if self.target_filepath else ""
        library = None
        for lib in bpy.data.libraries:
            try:
                if lib.filepath and bpy.path.abspath(lib.filepath) == abs_match:
                    library = lib
                    break
            except Exception:
                if lib.filepath == self.target_filepath:
                    library = lib
                    break
        if not library:
            self.report({"ERROR"}, "Could not resolve the selected library")
            return {"CANCELLED"}
        try:
            library.filepath = self.filepath
            library.reload()
            self.report({"INFO"}, f"Relocated to: {self.filepath}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to relocate: {e}")
            return {"CANCELLED"}
        return {"FINISHED"}

    def invoke(self, context, event):
        if self.target_filepath:
            try:
                self.filepath = bpy.path.abspath(self.target_filepath)
            except Exception:
                self.filepath = self.target_filepath
        context.window_manager.fileselect_add(self)
        return {"RUNNING_MODAL"}


def _get_migrator_pair(context):
    """Return (orig, rep) from scene props (manual or automatic). (None, None) if invalid."""
    from ..ops.migrator import get_pair_manual, get_pair_automatic

    props = getattr(context.scene, "dynamic_link_manager", None)
    if not props:
        return None, None
    use_auto = getattr(props, "migrator_mode", False)
    orig, rep = get_pair_automatic(context) if use_auto else get_pair_manual(context)
    return orig, rep


class DLM_OT_migrator_copy_attributes(Operator):
    bl_idname = "dlm.migrator_copy_attributes"
    bl_label = "CopyAttr"
    bl_description = "Copy object and armature attributes from original to replacement character"
    bl_icon = "COPY_ID"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair (set Original/Replacement or enable Automatic).")
            return {"CANCELLED"}
        try:
            from ..ops.migrator import run_copy_attr
            run_copy_attr(orig, rep)
            self.report({"INFO"}, "Copy attributes done.")
            return {"FINISHED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}


class DLM_OT_migrator_migrate_nla(Operator):
    bl_idname = "dlm.migrator_migrate_nla"
    bl_label = "MigNLA"
    bl_description = "Migrate NLA tracks and strips from original to replacement character"
    bl_icon = "NLA"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair.")
            return {"CANCELLED"}
        try:
            from ..ops.migrator import run_mig_nla
            run_mig_nla(orig, rep, report=self.report)
            return {"FINISHED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}


class DLM_OT_migrator_custom_properties(Operator):
    bl_idname = "dlm.migrator_custom_properties"
    bl_label = "MigCustProps"
    bl_description = "Copy custom properties from original to replacement character"
    bl_icon = "PROPERTIES"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair.")
            return {"CANCELLED"}
        try:
            from ..ops.migrator import run_mig_cust_props
            run_mig_cust_props(orig, rep)
            self.report({"INFO"}, "Custom properties done.")
            return {"FINISHED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}


class DLM_OT_migrator_bone_constraints(Operator):
    bl_idname = "dlm.migrator_bone_constraints"
    bl_label = "MigBoneConst"
    bl_description = "Migrate bone constraints from original to replacement armature"
    bl_icon = "CONSTRAINT_BONE"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair.")
            return {"CANCELLED"}
        try:
            from ..ops.migrator import run_mig_bone_const
            orig_to_rep = {orig: rep}
            run_mig_bone_const(orig, rep, orig_to_rep)
            self.report({"INFO"}, "Bone constraints done.")
            return {"FINISHED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}


class DLM_OT_migrator_retarget_relations(Operator):
    bl_idname = "dlm.migrator_retarget_relations"
    bl_label = "RetargRelatives"
    bl_description = "Retarget parent/child and other relations to the replacement character"
    bl_icon = "ORIENTATION_PARENT"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair.")
            return {"CANCELLED"}
        try:
            from ..ops.migrator import run_retarg_relatives
            from ..utils import descendants
            rep_descendants = descendants(rep)
            orig_to_rep = {orig: rep}
            run_retarg_relatives(orig, rep, rep_descendants, orig_to_rep)
            self.report({"INFO"}, "Retarget relations done.")
            return {"FINISHED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}


class DLM_OT_migrator_basebody_shapekeys(Operator):
    bl_idname = "dlm.migrator_basebody_shapekeys"
    bl_label = "MigBBodyShapeKeys"
    bl_description = "Migrate base body mesh shape key values from original to replacement"
    bl_icon = "SHAPEKEY_DATA"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair.")
            return {"CANCELLED"}
        try:
            from ..ops.migrator import run_mig_bbody_shapekeys
            from ..utils import descendants
            rep_descendants = descendants(rep)
            run_mig_bbody_shapekeys(orig, rep, rep_descendants, context)
            self.report({"INFO"}, "Migrate BaseBody shapekeys done.")
            return {"FINISHED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}


class DLM_OT_migrator_fk_rotations(Operator):
    bl_idname = "dlm.migrator_fk_rotations"
    bl_label = "MigFKRot"
    bl_description = "Copy FK arm and finger rotations from original to replacement (uses constraints)"
    bl_icon = "BONE_DATA"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair.")
            return {"CANCELLED"}
        try:
            from ..ops.fk_rotations import copy_fk_rotations
            ok, msg = copy_fk_rotations(context, orig, rep)
            if ok:
                self.report({"INFO"}, msg)
                return {"FINISHED"}
            else:
                self.report({"ERROR"}, msg)
                return {"CANCELLED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}


class DLM_OT_migrator_fk_rotations_bake(Operator):
    bl_idname = "dlm.migrator_fk_rotations_bake"
    bl_label = "Bake MigFKRot"
    bl_description = "Bake FK rotations to keyframes using nla.bake (similar to tweak tools)"
    bl_icon = "KEYFRAME"
    bl_options = {"REGISTER", "UNDO"}

    track_name: StringProperty(name="NLA Track", description="Optional NLA track name for frame range", default="")
    post_clean: BoolProperty(name="Post-clean", description="Clean curves after bake", default=False)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair.")
            return {"CANCELLED"}
        try:
            from ..ops.fk_rotations import bake_fk_rotations
            ok, msg = bake_fk_rotations(context, orig, rep, track_name=self.track_name or None, post_clean=self.post_clean)
            if ok:
                self.report({"INFO"}, msg)
                return {"FINISHED"}
            else:
                self.report({"ERROR"}, msg)
                return {"CANCELLED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}


class DLM_OT_migrator_fk_rotations_remove(Operator):
    bl_idname = "dlm.migrator_fk_rotations_remove"
    bl_label = "Remove MigFKRot"
    bl_description = "Remove FK rotation COPY_TRANSFORMS constraints (similar to tweak_remove_arm)"
    bl_icon = "X"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig or not rep or orig == rep:
            self.report({"ERROR"}, "No valid character pair.")
            return {"CANCELLED"}
        try:
            from ..ops.fk_rotations import remove_fk_rotations
            ok, msg = remove_fk_rotations(context, rep)
            if ok:
                self.report({"INFO"}, msg)
                return {"FINISHED"}
            else:
                self.report({"ERROR"}, msg)
                return {"CANCELLED"}
        except Exception as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}




class DLM_OT_migrator_remove_original(Operator):
    bl_idname = "dlm.migrator_remove_original"
    bl_label = "Remove Original"
    bl_description = "Delete the original character armature and its data from the scene"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name
        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}
        return {"FINISHED"}



class DLM_OT_picker_original_character(Operator):
    bl_idname = "dlm.picker_original_character"
    bl_label = "Pick Original"
    bl_description = "Set the original character armature from the active object"
    bl_options = {"REGISTER"}

    def execute(self, context):
        obj = context.active_object
        if not obj or obj.type != "ARMATURE":
            self.report({"WARNING"}, "Select an armature")
            return {"CANCELLED"}
        context.scene.dynamic_link_manager.original_character = obj
        self.report({"INFO"}, f"Original: {obj.name}")
        return {"FINISHED"}


class DLM_OT_picker_replacement_character(Operator):
    bl_idname = "dlm.picker_replacement_character"
    bl_label = "Pick Replacement"
    bl_description = "Set the replacement character armature from the active object"
    bl_options = {"REGISTER"}

    def execute(self, context):
        obj = context.active_object
        if not obj or obj.type != "ARMATURE":
            self.report({"WARNING"}, "Select an armature")
            return {"CANCELLED"}
        context.scene.dynamic_link_manager.replacement_character = obj
        self.report({"INFO"}, f"Replacement: {obj.name}")
        return {"FINISHED"}


def _tweak_poll(context):
    orig, rep = _get_migrator_pair(context)
    return orig is not None and rep is not None


class DLM_OT_tweak_add_arm(Operator):
    bl_idname = "dlm.tweak_add_arm"
    bl_label = "Add Arm Tweaks"
    bl_description = "Add tweak bone constraints to arm bones on the replacement character"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        from ..ops import tweak_tools
        tweak_tools.add_tweak_constraints(orig, rep, "arm")
        self.report({"INFO"}, "Arm tweak constraints added.")
        return {"FINISHED"}


class DLM_OT_tweak_remove_arm(Operator):
    bl_idname = "dlm.tweak_remove_arm"
    bl_label = "Remove Arm Tweaks"
    bl_description = "Remove arm tweak constraints from the replacement character"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        from ..ops import tweak_tools
        n = tweak_tools.remove_tweak_constraints(orig, rep, "arm")
        self.report({"INFO"}, f"Removed {n} arm tweak constraints.")
        return {"FINISHED"}


class DLM_OT_tweak_bake_arm(Operator):
    bl_idname = "dlm.tweak_bake_arm"
    bl_label = "Bake Arm Tweaks"
    bl_description = "Bake arm tweak constraints to keyframes and optionally remove constraints"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        props = context.scene.dynamic_link_manager
        from ..ops import tweak_tools
        ok, msg = tweak_tools.bake_tweak_constraints(
            context, orig, rep, "arm",
            getattr(props, "tweak_nla_track_name", "") or "",
            getattr(props, "tweak_bake_post_clean", False),
        )
        if ok:
            self.report({"INFO"}, msg)
            return {"FINISHED"}
        self.report({"ERROR"}, msg)
        return {"CANCELLED"}


class DLM_OT_tweak_add_leg(Operator):
    bl_idname = "dlm.tweak_add_leg"
    bl_label = "Add Leg Tweaks"
    bl_description = "Add tweak bone constraints to leg bones on the replacement character"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        from ..ops import tweak_tools
        tweak_tools.add_tweak_constraints(orig, rep, "leg")
        self.report({"INFO"}, "Leg tweak constraints added.")
        return {"FINISHED"}


class DLM_OT_tweak_remove_leg(Operator):
    bl_idname = "dlm.tweak_remove_leg"
    bl_label = "Remove Leg Tweaks"
    bl_description = "Remove leg tweak constraints from the replacement character"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        from ..ops import tweak_tools
        n = tweak_tools.remove_tweak_constraints(orig, rep, "leg")
        self.report({"INFO"}, f"Removed {n} leg tweak constraints.")
        return {"FINISHED"}


class DLM_OT_tweak_bake_leg(Operator):
    bl_idname = "dlm.tweak_bake_leg"
    bl_label = "Bake Leg Tweaks"
    bl_description = "Bake leg tweak constraints to keyframes and optionally remove constraints"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        props = context.scene.dynamic_link_manager
        from ..ops import tweak_tools
        ok, msg = tweak_tools.bake_tweak_constraints(
            context, orig, rep, "leg",
            getattr(props, "tweak_nla_track_name", "") or "",
            getattr(props, "tweak_bake_post_clean", False),
        )
        if ok:
            self.report({"INFO"}, msg)
            return {"FINISHED"}
        self.report({"ERROR"}, msg)
        return {"CANCELLED"}


class DLM_OT_tweak_add_both(Operator):
    bl_idname = "dlm.tweak_add_both"
    bl_label = "Add Arm &amp; Leg Tweaks"
    bl_description = "Add tweak bone constraints to both arm and leg bones"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        from ..ops import tweak_tools
        tweak_tools.add_tweak_constraints(orig, rep, "both")
        self.report({"INFO"}, "Arm &amp; leg tweak constraints added.")
        return {"FINISHED"}


class DLM_OT_tweak_remove_both(Operator):
    bl_idname = "dlm.tweak_remove_both"
    bl_label = "Remove Arm &amp; Leg Tweaks"
    bl_description = "Remove all arm and leg tweak constraints from the replacement character"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        from ..ops import tweak_tools
        n = tweak_tools.remove_tweak_constraints(orig, rep, "both")
        self.report({"INFO"}, f"Removed {n} tweak constraints.")
        return {"FINISHED"}


class DLM_OT_tweak_bake_both(Operator):
    bl_idname = "dlm.tweak_bake_both"
    bl_label = "Bake Arm &amp; Leg Tweaks"
    bl_description = "Bake all arm and leg tweak constraints to keyframes and optionally remove constraints"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        return _tweak_poll(context)

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        props = context.scene.dynamic_link_manager
        from ..ops import tweak_tools
        ok, msg = tweak_tools.bake_tweak_constraints(
            context, orig, rep, "both",
            getattr(props, "tweak_nla_track_name", "") or "",
            getattr(props, "tweak_bake_post_clean", False),
        )
        if ok:
            self.report({"INFO"}, msg)
            return {"FINISHED"}
        self.report({"ERROR"}, msg)
        return {"CANCELLED"}


OPERATOR_CLASSES = [
    DLM_OT_replace_linked_asset,
    DLM_OT_scan_linked_assets,
    DLM_OT_find_libraries_in_folders,
    DLM_OT_open_linked_file,
    DLM_OT_add_search_path,
    DLM_OT_remove_search_path,
    DLM_OT_browse_search_path,
    DLM_OT_attempt_relink,
    DLM_OT_reload_libraries,
    DLM_OT_make_paths_relative,
    DLM_OT_make_paths_absolute,
    DLM_OT_relocate_single_library,
    DLM_OT_migrator_remove_original,
    DLM_OT_picker_original_character,
    DLM_OT_picker_replacement_character,
    DLM_OT_migrator_copy_attributes,
    DLM_OT_migrator_migrate_nla,
    DLM_OT_migrator_custom_properties,
    DLM_OT_migrator_bone_constraints,
    DLM_OT_migrator_retarget_relations,
    DLM_OT_migrator_basebody_shapekeys,
    DLM_OT_tweak_add_arm,
    DLM_OT_tweak_remove_arm,
    DLM_OT_tweak_bake_arm,
    DLM_OT_tweak_add_leg,
    DLM_OT_tweak_remove_leg,
    DLM_OT_tweak_bake_leg,
    DLM_OT_tweak_add_both,
    DLM_OT_tweak_remove_both,
    DLM_OT_tweak_bake_both,
    DLM_OT_migrator_fk_rotations,
    DLM_OT_migrator_fk_rotations_bake,
    DLM_OT_migrator_fk_rotations_remove,
]

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
Let me search for the `DLM_OT_migrator_remove_original` class to find its exact location in the file.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: grep -n "class DLM_OT_migrator_remove_original" "T:\Dynamic-Link-Manager\ui\operators.py"</summary>

```bash
grep -n "class DLM_OT_migrator_remove_original" "T:\Dynamic-Link-Manager\ui\operators.py"
```

```
grep: C:\Users\Nathan\AppData\Local\Temp\ps-script-2b53dd81-e4c4-4b86-95b6-80c1bf76ba62.ps1:113
Line |
 113 |  grep -n "class DLM_OT_migrator_remove_original" "T:\Dynamic-Link-Mana .
     |  ~~~~
     | The term 'grep' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the
     | spelling of the name, or if a path was included, verify that the path is correct and try again.

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The grep command failed. Let me try with Select-String which is the PowerShell equivalent.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: Select-String -Pattern "class DLM_OT_migrator_remove_original" -Path "T:\Dynamic-Link-Manager\ui\operators.py" | Select-Object LineNumber</summary>

```bash
Select-String -Pattern "class DLM_OT_migrator_remove_original" -Path "T:\Dynamic-Link-Manager\ui\operators.py" | Select-Object LineNumber
```

```


```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The output is empty, which is strange. Let me try a different approach - using Python to find the line number.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); [print(i+1, line.strip()) for i, line in enumerate(lines) if 'DLM_OT_migrator_remove_original' in line]"</summary>

```bash
python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); [print(i+1, line.strip()) for i, line in enumerate(lines) if 'DLM_OT_migrator_remove_original' in line]"
```

```
492 class DLM_OT_migrator_remove_original(Operator):
768 DLM_OT_migrator_remove_original,

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The class starts at line 492. Let me read the section around that line to see the full class definition.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[491:540]))"</summary>

```bash
python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[491:540]))"
```

```
class DLM_OT_migrator_remove_original(Operator):
    bl_idname = "dlm.migrator_remove_original"
    bl_label = "Remove Original"
    bl_description = "Delete the original character armature and its data from the scene"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name
        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}
        return {"FINISHED"}



class DLM_OT_picker_original_character(Operator):
    bl_idname = "dlm.picker_original_character"
    bl_label = "Pick Original"
    bl_description = "Set the original character armature from the active object"
    bl_options = {"REGISTER"}

    def execute(self, context):
        obj = context.active_object
        if not obj or obj.type != "ARMATURE":


```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
Now I can see the current `execute` method. I need to update it to:
1. Before removing the collection, purge actions from the original character
2. After removing the original, rename actions with ".rep" suffix on the replacement

Let me create the updated execute method. The class runs from line 492 to about 530.

Now I'll write the updated code. I need to:
1. Collect all actions from the original's animation_data (active action, NLA strips)
2. Remove those actions from bpy.data.actions
3. After removing the original, find all actions on the replacement with ".rep" suffix and rename them

Let me write the updated file.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

Now I'll update the `DLM_OT_migrator_remove_original` operator with the requested functionality.

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python << 'EOF'
import re

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    content = f.read()

# Find the execute method of DLM_OT_migrator_remove_original and replace it
old_execute = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name
        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}
        return {"FINISHED"}'''

new_execute = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name
        
        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)
        
        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({"WARNING"}, f"Could not remove action {action_name}: {e}")
        
        if removed_actions:
            self.report({"INFO"}, f"Removed {len(removed_actions)} action(s) from original")
        
        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}
        
        # Rename replacement actions with ".rep" suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and ".rep" in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace(".rep", "")
                rep.animation_data.action.name = new_name
                renamed_actions.append(f"{old_name} -> {new_name}")
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and ".rep" in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace(".rep", "")
                        strip.action.name = new_name
                        renamed_actions.append(f"{old_name} -> {new_name}")
            if renamed_actions:
                self.report({"INFO"}, f"Renamed {len(renamed_actions)} replacement action(s)")
        
        return {"FINISHED"}'''

if old_execute in content:
    content = content.replace(old_execute, new_execute)
    with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
        f.write(content)
    print("Successfully updated DLM_OT_migrator_remove_original.execute()")
else:
    print("Could not find the exact method to replace. Checking...")
    # Try to find it with a simpler pattern
    if "def execute(self, context):" in content and "orig, rep = _get_migrator_pair(context)" in content:
        print("Found execute method with migrator pair pattern")
    else:
        print("Pattern not found")
EOF</summary>

```bash
python << 'EOF'
import re

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    content = f.read()

# Find the execute method of DLM_OT_migrator_remove_original and replace it
old_execute = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name
        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}
        return {"FINISHED"}'''

new_execute = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name
        
        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)
        
        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({"WARNING"}, f"Could not remove action {action_name}: {e}")
        
        if removed_actions:
            self.report({"INFO"}, f"Removed {len(removed_actions)} action(s) from original")
        
        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}
        
        # Rename replacement actions with ".rep" suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and ".rep" in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace(".rep", "")
                rep.animation_data.action.name = new_name
                renamed_actions.append(f"{old_name} -> {new_name}")
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and ".rep" in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace(".rep", "")
                        strip.action.name = new_name
                        renamed_actions.append(f"{old_name} -> {new_name}")
            if renamed_actions:
                self.report({"INFO"}, f"Renamed {len(renamed_actions)} replacement action(s)")
        
        return {"FINISHED"}'''

if old_execute in content:
    content = content.replace(old_execute, new_execute)
    with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
        f.write(content)
    print("Successfully updated DLM_OT_migrator_remove_original.execute()")
else:
    print("Could not find the exact method to replace. Checking...")
    # Try to find it with a simpler pattern
    if "def execute(self, context):" in content and "orig, rep = _get_migrator_pair(context)" in content:
        print("Found execute method with migrator pair pattern")
    else:
        print("Pattern not found")
EOF
```

```
ParserError: C:\Users\Nathan\AppData\Local\Temp\ps-script-d040911e-4c0f-41ff-9831-b28ea8c72fe3.ps1:113
Line |
 113 |  python &lt;&lt; 'EOF'
     |          ~
     | Missing file specification after redirection operator.

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
PowerShell doesn't support heredoc syntax. Let me write the Python script to a file first, then run it.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: Set-Content -Path "update_script.py" -Value @"
import re

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    content = f.read()

old_execute = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({'WARNING'}, 'No original character selected')
            return {'CANCELLED'}
        if orig == rep:
            self.report({'ERROR'}, 'Original and replacement cannot be the same object')
            return {'CANCELLED'}

        name = orig.name
        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({'INFO'}, f'Removed collection: {coll_name}')
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({'WARNING'}, f'Collection {coll_name} removal issue: {remove_err}')
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({'INFO'}, f'Removed original character: {name}')
        except Exception as e:
            self.report({'ERROR'}, f'Failed to remove original: {e}')
            return {'CANCELLED'}
        return {'FINISHED'}'''

new_execute = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({'WARNING'}, 'No original character selected')
            return {'CANCELLED'}
        if orig == rep:
            self.report({'ERROR'}, 'Original and replacement cannot be the same object')
            return {'CANCELLED'}

        name = orig.name

        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)

        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({'WARNING'}, f'Could not remove action {action_name}: {e}')

        if removed_actions:
            self.report({'INFO'}, f'Removed {len(removed_actions)} action(s) from original')

        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({'INFO'}, f'Removed collection: {coll_name}')
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({'WARNING'}, f'Collection {coll_name} removal issue: {remove_err}')
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({'INFO'}, f'Removed original character: {name}')
        except Exception as e:
            self.report({'ERROR'}, f'Failed to remove original: {e}')
            return {'CANCELLED'}

        # Rename replacement actions with '.rep' suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and '.rep' in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace('.rep', '')
                rep.animation_data.action.name = new_name
                renamed_actions.append(f'{old_name} -> {new_name}')
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and '.rep' in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace('.rep', '')
                        strip.action.name = new_name
                        renamed_actions.append(f'{old_name} -> {new_name}')
            if renamed_actions:
                self.report({'INFO'}, f'Renamed {len(renamed_actions)} replacement action(s)')

        return {'FINISHED'}'''

if old_execute in content:
    content = content.replace(old_execute, new_execute)
    with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
        f.write(content)
    print('Successfully updated DLM_OT_migrator_remove_original.execute()')
else:
    print('Could not find the exact method to replace')
"@</summary>

```bash
Set-Content -Path "update_script.py" -Value @"
import re

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    content = f.read()

old_execute = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({'WARNING'}, 'No original character selected')
            return {'CANCELLED'}
        if orig == rep:
            self.report({'ERROR'}, 'Original and replacement cannot be the same object')
            return {'CANCELLED'}

        name = orig.name
        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({'INFO'}, f'Removed collection: {coll_name}')
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({'WARNING'}, f'Collection {coll_name} removal issue: {remove_err}')
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({'INFO'}, f'Removed original character: {name}')
        except Exception as e:
            self.report({'ERROR'}, f'Failed to remove original: {e}')
            return {'CANCELLED'}
        return {'FINISHED'}'''

new_execute = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({'WARNING'}, 'No original character selected')
            return {'CANCELLED'}
        if orig == rep:
            self.report({'ERROR'}, 'Original and replacement cannot be the same object')
            return {'CANCELLED'}

        name = orig.name

        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)

        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({'WARNING'}, f'Could not remove action {action_name}: {e}')

        if removed_actions:
            self.report({'INFO'}, f'Removed {len(removed_actions)} action(s) from original')

        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({'INFO'}, f'Removed collection: {coll_name}')
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({'WARNING'}, f'Collection {coll_name} removal issue: {remove_err}')
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({'INFO'}, f'Removed original character: {name}')
        except Exception as e:
            self.report({'ERROR'}, f'Failed to remove original: {e}')
            return {'CANCELLED'}

        # Rename replacement actions with '.rep' suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and '.rep' in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace('.rep', '')
                rep.animation_data.action.name = new_name
                renamed_actions.append(f'{old_name} -> {new_name}')
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and '.rep' in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace('.rep', '')
                        strip.action.name = new_name
                        renamed_actions.append(f'{old_name} -> {new_name}')
            if renamed_actions:
                self.report({'INFO'}, f'Renamed {len(renamed_actions)} replacement action(s)')

        return {'FINISHED'}'''

if old_execute in content:
    content = content.replace(old_execute, new_execute)
    with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
        f.write(content)
    print('Successfully updated DLM_OT_migrator_remove_original.execute()')
else:
    print('Could not find the exact method to replace')
"@
```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The script was created. Now let's run it.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python update_script.py</summary>

```bash
python update_script.py
```

```
Could not find the exact method to replace

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The exact match failed, likely due to different quote styles. Let me check the actual file content more carefully.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(repr(lines[501]))"</summary>

```bash
python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(repr(lines[501]))"
```

```
'            return {"CANCELLED"}\n'

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The file uses double quotes. Let me create a simpler approach - read the file, and use line numbers to replace the specific section.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: Set-Content -Path "update_script2.py" -Value @"
with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    lines = f.readlines()

# Find the execute method within DLM_OT_migrator_remove_original (starts at line 492)
# The method starts at line 497 (0-indexed: 496)
# We need to find where it ends

start_line = 496  # def execute(self, context) - 0-indexed

# Find the end of the method (next method definition at same indentation or end of class)
end_line = None
for i in range(start_line + 1, len(lines)):
    line = lines[i]
    # Check for next class or method at class level (no indent)
    if line.startswith('class ') or (line.startswith('def ') and not line.startswith('        def')):
        if not line.startswith('        '):  # Same or less indentation as class
            end_line = i
            break

if end_line is None:
    end_line = len(lines)

print(f'Method starts at line {start_line + 1}, ends at line {end_line}')

# Build the new execute method
new_method = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({'WARNING'}, 'No original character selected')
            return {'CANCELLED'}
        if orig == rep:
            self.report({'ERROR'}, 'Original and replacement cannot be the same object')
            return {'CANCELLED'}

        name = orig.name

        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)

        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({'WARNING'}, f'Could not remove action {action_name}: {{e}}')

        if removed_actions:
            self.report({'INFO'}, f'Removed {{len(removed_actions)}} action(s) from original')

        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({'INFO'}, f'Removed collection: {{coll_name}}')
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({'WARNING'}, f'Collection {{coll_name}} removal issue: {{remove_err}}')
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({'INFO'}, f'Removed original character: {{name}}')
        except Exception as e:
            self.report({'ERROR'}, f'Failed to remove original: {{e}}')
            return {'CANCELLED'}

        # Rename replacement actions with '.rep' suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and '.rep' in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace('.rep', '')
                rep.animation_data.action.name = new_name
                renamed_actions.append(f'{{old_name}} -> {{new_name}}')
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and '.rep' in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace('.rep', '')
                        strip.action.name = new_name
                        renamed_actions.append(f'{{old_name}} -> {{new_name}}')
            if renamed_actions:
                self.report({'INFO'}, f'Renamed {{len(renamed_actions)}} replacement action(s)')

        return {'FINISHED'}

'''

# Replace single quotes with double quotes for Blender Python convention
new_method = new_method.replace(\"'\", '\"')

# Construct new file content
new_lines = lines[:start_line] + [new_method] + lines[end_line:]

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
    f.writelines(new_lines)

print('Updated DLM_OT_migrator_remove_original.execute()')
"@</summary>

```bash
Set-Content -Path "update_script2.py" -Value @"
with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    lines = f.readlines()

# Find the execute method within DLM_OT_migrator_remove_original (starts at line 492)
# The method starts at line 497 (0-indexed: 496)
# We need to find where it ends

start_line = 496  # def execute(self, context) - 0-indexed

# Find the end of the method (next method definition at same indentation or end of class)
end_line = None
for i in range(start_line + 1, len(lines)):
    line = lines[i]
    # Check for next class or method at class level (no indent)
    if line.startswith('class ') or (line.startswith('def ') and not line.startswith('        def')):
        if not line.startswith('        '):  # Same or less indentation as class
            end_line = i
            break

if end_line is None:
    end_line = len(lines)

print(f'Method starts at line {start_line + 1}, ends at line {end_line}')

# Build the new execute method
new_method = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({'WARNING'}, 'No original character selected')
            return {'CANCELLED'}
        if orig == rep:
            self.report({'ERROR'}, 'Original and replacement cannot be the same object')
            return {'CANCELLED'}

        name = orig.name

        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)

        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({'WARNING'}, f'Could not remove action {action_name}: {{e}}')

        if removed_actions:
            self.report({'INFO'}, f'Removed {{len(removed_actions)}} action(s) from original')

        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({'INFO'}, f'Removed collection: {{coll_name}}')
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({'WARNING'}, f'Collection {{coll_name}} removal issue: {{remove_err}}')
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({'INFO'}, f'Removed original character: {{name}}')
        except Exception as e:
            self.report({'ERROR'}, f'Failed to remove original: {{e}}')
            return {'CANCELLED'}

        # Rename replacement actions with '.rep' suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and '.rep' in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace('.rep', '')
                rep.animation_data.action.name = new_name
                renamed_actions.append(f'{{old_name}} -> {{new_name}}')
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and '.rep' in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace('.rep', '')
                        strip.action.name = new_name
                        renamed_actions.append(f'{{old_name}} -> {{new_name}}')
            if renamed_actions:
                self.report({'INFO'}, f'Renamed {{len(renamed_actions)}} replacement action(s)')

        return {'FINISHED'}

'''

# Replace single quotes with double quotes for Blender Python convention
new_method = new_method.replace(\"'\", '\"')

# Construct new file content
new_lines = lines[:start_line] + [new_method] + lines[end_line:]

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
    f.writelines(new_lines)

print('Updated DLM_OT_migrator_remove_original.execute()')
"@
```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
Let me run this script.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python update_script2.py</summary>

```bash
python update_script2.py
```

```
  File "T:\Dynamic-Link-Manager\update_script2.py", line 108
    new_method = new_method.replace(\"'\", '\"')
                                     ^
SyntaxError: unexpected character after line continuation character

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The escaping is getting complicated. Let me take a simpler approach - create a Python file that contains the logic directly without complex escaping.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: Set-Content -Path "do_update.py" -Value @"
with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    lines = f.readlines()

start_line = 496  # def execute(self, context) - 0-indexed

# Find the end of the method
end_line = None
for i in range(start_line + 1, len(lines)):
    line = lines[i]
    if line.startswith('class ') or (line.startswith('def ') and not line.startswith('        ')):
        end_line = i
        break

if end_line is None:
    end_line = len(lines)

print(f'Method: lines {start_line+1} to {end_line}')

new_method = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name

        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)

        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({"WARNING"}, f"Could not remove action {action_name}: {e}")

        if removed_actions:
            self.report({"INFO"}, f"Removed {len(removed_actions)} action(s) from original")

        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}

        # Rename replacement actions with ".rep" suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and ".rep" in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace(".rep", "")
                rep.animation_data.action.name = new_name
                renamed_actions.append(f"{old_name} -> {new_name}")
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and ".rep" in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace(".rep", "")
                        strip.action.name = new_name
                        renamed_actions.append(f"{old_name} -> {new_name}")
            if renamed_actions:
                self.report({"INFO"}, f"Renamed {len(renamed_actions)} replacement action(s)")

        return {"FINISHED"}

'''

new_lines = lines[:start_line] + [new_method] + lines[end_line:]

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
    f.writelines(new_lines)

print('Successfully updated DLM_OT_migrator_remove_original.execute()')
"@</summary>

```bash
Set-Content -Path "do_update.py" -Value @"
with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    lines = f.readlines()

start_line = 496  # def execute(self, context) - 0-indexed

# Find the end of the method
end_line = None
for i in range(start_line + 1, len(lines)):
    line = lines[i]
    if line.startswith('class ') or (line.startswith('def ') and not line.startswith('        ')):
        end_line = i
        break

if end_line is None:
    end_line = len(lines)

print(f'Method: lines {start_line+1} to {end_line}')

new_method = '''    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name

        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)

        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({"WARNING"}, f"Could not remove action {action_name}: {e}")

        if removed_actions:
            self.report({"INFO"}, f"Removed {len(removed_actions)} action(s) from original")

        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}

        # Rename replacement actions with ".rep" suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and ".rep" in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace(".rep", "")
                rep.animation_data.action.name = new_name
                renamed_actions.append(f"{old_name} -> {new_name}")
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and ".rep" in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace(".rep", "")
                        strip.action.name = new_name
                        renamed_actions.append(f"{old_name} -> {new_name}")
            if renamed_actions:
                self.report({"INFO"}, f"Renamed {len(renamed_actions)} replacement action(s)")

        return {"FINISHED"}

'''

new_lines = lines[:start_line] + [new_method] + lines[end_line:]

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
    f.writelines(new_lines)

print('Successfully updated DLM_OT_migrator_remove_original.execute()')
"@
```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
Now let me run this simpler script.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python do_update.py</summary>

```bash
python do_update.py
```

```
Method: lines 497 to 531
Successfully updated DLM_OT_migrator_remove_original.execute()

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The update was successful. Let me verify the changes by reading the updated section.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[491:570]))"</summary>

```bash
python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[491:570]))"
```

```
class DLM_OT_migrator_remove_original(Operator):
    bl_idname = "dlm.migrator_remove_original"
    bl_label = "Remove Original"
    bl_description = "Delete the original character armature and its data from the scene"
    bl_options = {"REGISTER", "UNDO"}
    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name

        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)

        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({"WARNING"}, f"Could not remove action {action_name}: {e}")

        if removed_actions:
            self.report({"INFO"}, f"Removed {len(removed_actions)} action(s) from original")

        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}

        # Rename replacement actions with ".rep" suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and ".rep" in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace(".rep", "")
                rep.animation_data.action.name = new_name
                renamed_actions.append(f"{old_name} -&gt; {new_name}")
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and ".rep" in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace(".rep", "")
                        strip.action.name = new_name
                        renamed_actions.append(f"{old_name} -&gt; {new_name}")


```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
I notice the indentation is off - the `def execute` line doesn't have a blank line before it and is missing one level of indentation. Let me check if this is a problem by looking at more of the output.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[560:580]))"</summary>

```bash
python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[560:580]))"
```

```
                rep.animation_data.action.name = new_name
                renamed_actions.append(f"{old_name} -&gt; {new_name}")
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and ".rep" in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace(".rep", "")
                        strip.action.name = new_name
                        renamed_actions.append(f"{old_name} -&gt; {new_name}")
            if renamed_actions:
                self.report({"INFO"}, f"Renamed {len(renamed_actions)} replacement action(s)")

        return {"FINISHED"}

class DLM_OT_picker_original_character(Operator):
    bl_idname = "dlm.picker_original_character"
    bl_label = "Pick Original"
    bl_description = "Set the original character armature from the active object"
    bl_options = {"REGISTER"}


```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
I notice there's a missing blank line before `def execute(self, context):`. Let me fix that formatting issue.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python -c "
with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    content = f.read()

# Fix the missing blank line before def execute
content = content.replace('bl_options = {\"REGISTER\", \"UNDO\"}\n    def execute', 'bl_options = {\"REGISTER\", \"UNDO\"}\n\n    def execute')

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
    f.write(content)

print('Fixed formatting')
"</summary>

```bash
python -c "
with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    content = f.read()

# Fix the missing blank line before def execute
content = content.replace('bl_options = {\"REGISTER\", \"UNDO\"}\n    def execute', 'bl_options = {\"REGISTER\", \"UNDO\"}\n\n    def execute')

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
    f.write(content)

print('Fixed formatting')
"
```

```
  File "&lt;string&gt;", line 6
    content = content.replace('bl_options = {\
                              ^
SyntaxError: unterminated string literal (detected at line 6)

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
Let me try a different approach - write a small fix script to a file.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: Set-Content -Path "fix_format.py" -Value @"
with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    content = f.read()

# Fix the missing blank line before def execute
content = content.replace('bl_options = {\"REGISTER\", \"UNDO\"}\n    def execute', 'bl_options = {\"REGISTER\", \"UNDO\"}\n\n    def execute')

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
    f.write(content)

print('Fixed formatting')
"@</summary>

```bash
Set-Content -Path "fix_format.py" -Value @"
with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'r') as f:
    content = f.read()

# Fix the missing blank line before def execute
content = content.replace('bl_options = {\"REGISTER\", \"UNDO\"}\n    def execute', 'bl_options = {\"REGISTER\", \"UNDO\"}\n\n    def execute')

with open(r'T:\Dynamic-Link-Manager\ui\operators.py', 'w') as f:
    f.write(content)

print('Fixed formatting')
"@
```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
Let me run the fix script.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python fix_format.py</summary>

```bash
python fix_format.py
```

```
Fixed formatting

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
Now let me verify the final result.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[491:575]))"</summary>

```bash
python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[491:575]))"
```

```
class DLM_OT_migrator_remove_original(Operator):
    bl_idname = "dlm.migrator_remove_original"
    bl_label = "Remove Original"
    bl_description = "Delete the original character armature and its data from the scene"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        orig, rep = _get_migrator_pair(context)
        if not orig:
            self.report({"WARNING"}, "No original character selected")
            return {"CANCELLED"}
        if orig == rep:
            self.report({"ERROR"}, "Original and replacement cannot be the same object")
            return {"CANCELLED"}

        name = orig.name

        # Collect actions from original character before removal
        actions_to_remove = set()
        if orig.animation_data:
            # Active action
            if orig.animation_data.action:
                actions_to_remove.add(orig.animation_data.action)
            # NLA strips
            for track in orig.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action:
                        actions_to_remove.add(strip.action)

        # Remove collected actions from bpy.data.actions
        removed_actions = []
        for action in actions_to_remove:
            action_name = action.name
            try:
                bpy.data.actions.remove(action)
                removed_actions.append(action_name)
            except Exception as e:
                self.report({"WARNING"}, f"Could not remove action {action_name}: {e}")

        if removed_actions:
            self.report({"INFO"}, f"Removed {len(removed_actions)} action(s) from original")

        try:
            # Try to find and delete the collection containing the original character
            coll = collection_containing_armature(orig)
            if coll:
                coll_name = coll.name  # Store name BEFORE removal (RNA invalidates after remove)
                context.scene.dynamic_link_manager.original_character = None
                try:
                    bpy.data.collections.remove(coll)
                    self.report({"INFO"}, f"Removed collection: {coll_name}")
                except Exception as remove_err:
                    # Collection may have already been removed by another process
                    self.report({"WARNING"}, f"Collection {coll_name} removal issue: {remove_err}")
            else:
                # Fallback: just delete the armature object
                bpy.data.objects.remove(orig, do_unlink=True)
                context.scene.dynamic_link_manager.original_character = None
                self.report({"INFO"}, f"Removed original character: {name}")
        except Exception as e:
            self.report({"ERROR"}, f"Failed to remove original: {e}")
            return {"CANCELLED"}

        # Rename replacement actions with ".rep" suffix
        if rep and rep.animation_data:
            renamed_actions = []
            # Active action
            if rep.animation_data.action and ".rep" in rep.animation_data.action.name:
                old_name = rep.animation_data.action.name
                new_name = old_name.replace(".rep", "")
                rep.animation_data.action.name = new_name
                renamed_actions.append(f"{old_name} -&gt; {new_name}")
            # NLA strips
            for track in rep.animation_data.nla_tracks:
                for strip in track.strips:
                    if strip.action and ".rep" in strip.action.name:
                        old_name = strip.action.name
                        new_name = old_name.replace(".rep", "")
                        strip.action.name = new_name
                        renamed_actions.append(f"{old_name} -&gt; {new_name}")
            if renamed_actions:
                self.report({"INFO"}, f"Renamed {len(renamed_actions)} replacement action(s)")

        return {"FINISHED"}


```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The update is complete. Let me also verify the next class is still intact.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[575:585]))"</summary>

```bash
python -c "with open(r'T:\Dynamic-Link-Manager\ui\operators.py') as f: lines = f.readlines(); print(''.join(lines[575:585]))"
```

```

class DLM_OT_picker_original_character(Operator):
    bl_idname = "dlm.picker_original_character"
    bl_label = "Pick Original"
    bl_description = "Set the original character armature from the active object"
    bl_options = {"REGISTER"}

    def execute(self, context):
        obj = context.active_object
        if not obj or obj.type != "ARMATURE":


```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
The update is complete and properly formatted. Let me clean up the temporary files.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2">
<details><summary>Tool use: **run_terminal_command_v2** • Run command: Remove-Item -Path "update_script.py", "update_script2.py", "do_update.py", "fix_format.py" -ErrorAction SilentlyContinue; Write-Host "Cleaned up temporary files"</summary>

```bash
Remove-Item -Path "update_script.py", "update_script2.py", "do_update.py", "fix_format.py" -ErrorAction SilentlyContinue; Write-Host "Cleaned up temporary files"
```

```
Cleaned up temporary files

```
</details>
</tool-use>

<tool-use data-tool-type="shell" data-tool-name="run_terminal_command_v2"><details>
<summary>Tool use: **run_terminal_command_v2**</summary>

</details></tool-use>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

<think><details><summary>Thought Process</summary>
All done. Let me summarize the changes I made.</details></think>

_**Agent (accounts/fireworks/models/kimi-k2p5)**_

Done. I've updated the `DLM_OT_migrator_remove_original` operator in `T:\Dynamic-Link-Manager\ui\operators.py`.

The changes to the `execute` method:

**1. Purge actions from original character (before removal):**
- Collects actions from `orig.animation_data.action` (active action)
- Collects actions from all NLA track strips
- Removes each collected action from `bpy.data.actions`
- Reports the count of removed actions

**2. Rename replacement actions (after original removal):**
- Checks if replacement has animation data
- Renames the active action if it has `.rep` suffix
- Renames actions in all NLA strips with `.rep` suffix
- Reports the count of renamed actions

The logic safely handles cases where `animation_data` is `None` and wraps action removal in try/except to report warnings for any actions that can't be removed.
