tis-remove-windows-ai icon

Remove Windows AI

Paquet d’installation silencieuse pour Remove Windows AI

0-3

Remove Windows AI

Paquet WAPT qui desactive et supprime toutes les fonctionnalites IA de Windows 10/11.

Base sur RemoveWindowsAI par zoicware.

Ce que fait ce paquet

Installation

  • Tue les processus et services IA (WSAIFabricSvc, AarSvc, WorkloadsSessionHost, aihost, etc.)
  • Desactive les cles de registre (HKLM & HKCU) : Copilot, Recall, Click To Do, IA dans Edge, Office, Paint, Notepad, Windows Search
  • Desactive les politiques Copilot dans IntegratedServicesRegionPolicySet.json et Visual Assist
  • Supprime la fonctionnalite optionnelle Recall via DISM
  • Supprime les taches planifiees Recall et nettoie le cache des taches dans le registre
  • Supprime les packages Appx IA : Copilot, AIX, CoreAI, Office Hub, Writing Assistant, packages WindowsWorkload (PC Copilot+)
  • Supprime les packages CBS IA caches : AIX, Recall, Copilot, CoreAI
  • Masque les pages de parametres IA (aicomponents, appactions) dans les Parametres Windows

Desinstallation

  • Reactive les cles de registre HKLM
  • Reactive les politiques Copilot
  • Restaure les blocages registre des packages Appx (Deprovisioned/EndOfLife) via les donnees de rollback sauvegardees
  • Reaffiche les pages de parametres IA
  • Note : les packages Appx eux-memes seront restaures par Windows Update apres desinstallation

Session setup / cleanup

  • Applique et reverte les cles de registre HKCU par session utilisateur

Audit

  • Verifie toutes les cles de registre, politiques, etat de la fonctionnalite Recall, taches planifiees, packages Appx, packages CBS et visibilite des parametres

Avertissements importants

Detection antivirus

Ce paquet utilise le detournement du service TrustedInstaller pour executer des commandes avec les privileges TrustedInstaller. Cette technique modifie temporairement le binPath du service TrustedInstaller pour lancer des scripts PowerShell, puis le restaure. Certains antivirus ou solutions EDR peuvent signaler ce comportement comme suspect ou malveillant. Il peut etre necessaire d'ajouter une exclusion pour ce paquet dans votre solution de securite.

Problemes de Windows Update

Certains utilisateurs ont signale que Windows Update peut echouer ou etre bloque apres la suppression des composants IA, en particulier les packages CBS. Cela est du au fait que Windows Update peut tenter de reinstaller ou de maintenir ces composants et echouer lorsqu'ils sont absents. Si vous rencontrez des problemes de Windows Update apres l'installation de ce paquet :

  1. Essayez d'abord de desinstaller ce paquet
  2. Executez DISM /Online /Cleanup-Image /RestoreHealth
  3. Executez sfc /scannow

PC Copilot+

Sur les PC Copilot+ (ARM64 avec NPU), ce paquet supprime egalement les packages WindowsWorkload utilises par les fonctionnalites IA embarquees. Ces packages peuvent etre verrouilles par des processus en cours d'execution, c'est pourquoi le paquet tue les processus IA avant la suppression.

Reversibilite

  • Les modifications du registre sont entierement reversibles via la desinstallation/session_cleanup
  • La suppression des packages Appx est tracee dans un fichier JSON de rollback (persistent_dir/appx_rollback.json)
  • La suppression des packages CBS et de la fonctionnalite Recall n'est pas reversible sans une reparation ou reinstallation de Windows

  • package: tis-remove-windows-ai
  • name: Remove Windows AI
  • version: 0-3
  • maintainer: WAPT Team,Tranquil IT,Flavien SCHELFAUT
  • target_os: windows
  • architecture: all
  • signature_date:
  • size: 17.32 Ko

package           : tis-remove-windows-ai
version           : 0-3
architecture      : all
section           : base
priority          : optional
name              : Remove Windows AI
categories        : 
maintainer        : WAPT Team,Tranquil IT,Flavien SCHELFAUT
description       : Disables and removes Windows AI features
depends           : 
conflicts         : 
maturity          : PROD
locale            : 
target_os         : windows
min_wapt_version  : 2.5
sources           : https://github.com/zoicware/RemoveWindowsAI
installed_size    : 
impacted_process  : 
description_fr    : Désactive et supprime les fonctionnalités IA de Windows
description_pl    : Wyłącza i usuwa funkcje AI systemu Windows
description_de    : Deaktiviert und entfernt Windows-KI-Funktionen
description_es    : Desactiva y elimina las funciones de IA de Windows
description_pt    : Desativa e remove as funcionalidades de IA do Windows
description_it    : Disattiva e rimuove le funzionalità IA di Windows
description_nl    : Schakelt Windows AI-functies uit en verwijdert deze
description_ru    : Отключает и удаляет функции ИИ Windows
audit_schedule    : 
editor            : 
keywords          : 
licence           : 
homepage          : 
package_uuid      : 1c52ce7e-a980-4a25-8632-abdec2267dc1
valid_from        : 
valid_until       : 
forced_install_on : 
changelog         : 
min_os_version    : 10.0.26100
max_os_version    : 
icon_sha256sum    : 7891f1ca19ac8a9e41cb2963c0833bb3424a1dcc3f89e6ae484b1841a67063b2
signer            : Tranquil IT
signer_fingerprint: 8c5127a75392be9cc9afd0dbae1222a673072c308c14d88ab246e23832e8c6bb
signature_date    : 2026-02-23T10:07:18.000000
signed_attributes : package,version,architecture,section,priority,name,categories,maintainer,description,depends,conflicts,maturity,locale,target_os,min_wapt_version,sources,installed_size,impacted_process,description_fr,description_pl,description_de,description_es,description_pt,description_it,description_nl,description_ru,audit_schedule,editor,keywords,licence,homepage,package_uuid,valid_from,valid_until,forced_install_on,changelog,min_os_version,max_os_version,icon_sha256sum,signer,signer_fingerprint,signature_date,signed_attributes
signature         : hDlhvwYgPI0DdHR/Ugou58lC7NJAdVCxx365KdHcmLc7q+65XDDrN47KUM8q/w2UTzdgZK2EtQR7IESBXi395RRNMrEuNxoinRvOeL1t++iaK0vD5j5OuErsMRN0T/mcWwgCJZjiczTxnuPNAyXpgZAT2cezzWQLzwOxY6zmRqH0xGqt8kyJnEPEp2I3Pg6g4aao2eOWkDWx1LXPISmwYV04vXU20lDHn4p+TVZqU3JSI5YTJIpmUK4dWV1H+ed90MTL0/YCABjA18rFyGl3+DXRWebNEH0TfBThiHeSMUgQvn50epUKRCd6mMoQBlujSt2x7VYFmGjvEjslVDhplQ==

# -*- coding: utf-8 -*-
from setuphelpers import *
from setupdevhelpers import *
import fnmatch
import json
import time
import tempfile
import re

"""
Inspired by https://github.com/zoicware/RemoveWindowsAI

Implemented feature :
- Disable Registry Keys
- Remove AI Appx Packages
- Disable Copilot policies
- Remove Recall Optional Feature
- Remove Recall Tasks
- Disable Rewrite AI Feature in Notepad
- Hide AI Components
- Remove AI Packages in CBS
"""

DEBUG = False

AI_PACKAGES = [
    'MicrosoftWindows.Client.AIX',
    'MicrosoftWindows.Client.CoPilot',
    'Microsoft.Windows.Ai.Copilot.Provider',
    'Microsoft.Copilot',
    'Microsoft.MicrosoftOfficeHub',
    'MicrosoftWindows.Client.CoreAI',
    'Microsoft.Edge.GameAssist',
    'Microsoft.Office.ActionsServer',
    'aimgr',
    'Microsoft.WritingAssistant',
    # AI component packages on Copilot+ PCs
    'MicrosoftWindows.*.Voiess',
    'MicrosoftWindows.*.Speion',
    'MicrosoftWindows.*.Livtop',
    'MicrosoftWindows.*.InpApp',
    'MicrosoftWindows.*.Filons',
    'WindowsWorkload.Data.Analysis.Stx.*',
    'WindowsWorkload.Manager.*',
    'WindowsWorkload.PSOnnxRuntime.Stx.*',
    'WindowsWorkload.PSTokenizer.Stx.*',
    'WindowsWorkload.QueryBlockList.*',
    'WindowsWorkload.QueryProcessor.Data.*',
    'WindowsWorkload.QueryProcessor.Stx.*',
    'WindowsWorkload.SemanticText.Data.*',
    'WindowsWorkload.SemanticText.Stx.*',
    'WindowsWorkload.Data.ContentExtraction.Stx.*',
    'WindowsWorkload.ScrRegDetection.Data.*',
    'WindowsWorkload.ScrRegDetection.Stx.*',
    'WindowsWorkload.TextRecognition.Stx.*',
    'WindowsWorkload.Data.ImageSearch.Stx.*',
    'WindowsWorkload.ImageContentModeration.*',
    'WindowsWorkload.ImageContentModeration.Data.*',
    'WindowsWorkload.ImageSearch.Data.*',
    'WindowsWorkload.ImageSearch.Stx.*',
    'WindowsWorkload.ImageTextSearch.Data.*',
    'WindowsWorkload.PSTokenizerShared.Data.*',
    'WindowsWorkload.PSTokenizerShared.Stx.*',
    'WindowsWorkload.ImageTextSearch.Stx.*',
]

AI_PROCESSES = [
    'ai.exe', 'aihost.exe', 'aicontext.exe', 'aimgr.exe',
    'Copilot.exe', 'ClickToDo.exe', 'aixhost.exe',
    'WorkloadsSessionHost.exe', 'WorkloadsSessionManager.exe',
    'WebViewHost.exe', 'AppActions.exe',
]

AI_SERVICES = ['WSAIFabricSvc', 'AarSvc']

AI_TASKS = [
    r'\Microsoft\Windows\WindowsAI\Recall\InitialConfiguration',
    r'\Microsoft\Windows\WindowsAI\Recall\PolicyConfiguration',
    r'\Microsoft\Office\Office Actions Server',
]


def run_powershell(cmd, **kwargs):
    from setuphelpers_windows import run_powershell as _run_powershell
    cmd = "$ProgressPreference = 'SilentlyContinue'; " + cmd
    return _run_powershell(cmd, **kwargs)


def ensure_list_powershell(result):
    """Ensure run_powershell result is always a list"""
    if not result:
        return []
    return [result] if isinstance(result, dict) else result


def get_installed_appx():
    """Returns list of installed Appx packages (all users) with Name, PackageFullName, PackageFamilyName, UserSIDs"""
    return ensure_list_powershell(run_powershell(
        r'Get-AppxPackage -AllUsers | Select-Object Name, PackageFullName, PackageFamilyName, '
        r'@{N="UserSIDs";E={($_.PackageUserInformation | ForEach-Object { $_.UserSecurityId.Sid }) -join ","}}'
    ))


def get_provisioned_appx():
    """Returns list of provisioned Appx packages with DisplayName, PackageName"""
    return ensure_list_powershell(run_powershell(
        'Get-AppxProvisionedPackage -Online | Select-Object DisplayName, PackageName'
    ))


def find_matching_ai_packages(packages, key='PackageFullName'):
    """Returns packages matching any AI_PACKAGES pattern on the given key"""
    return [pkg for pkg in packages if any(fnmatch.fnmatch(pkg.get(key, ''), f'*{p}*') for p in AI_PACKAGES)]


def get_active_user_sids():
    """Returns list of active user SIDs from loaded HKU hives"""
    return [sid for sid in reg_enum_subkeys(reg_openkey_noredir(HKEY_USERS, ''))
            if sid.startswith('S-1-5-21') and '_Classes' not in sid]


def kill_ai_processes():
    """Kill AI processes and stop AI services to unlock packages"""
    for svc in AI_SERVICES:
        if service_is_running(svc):
            service_stop(svc)

    killalltasks(ensure_list(AI_PROCESSES))


def set_ai_settings_visibility(hide=True):
    """Hide or unhide AI components and App Actions pages in Windows Settings"""
    SETTINGS_PAGE_KEY = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer'
    AI_PAGES_TO_HIDE = 'aicomponents;appactions;'

    existing = registry_readstring(HKEY_LOCAL_MACHINE, SETTINGS_PAGE_KEY, 'SettingsPageVisibility')

    if hide:
        if existing and 'showonly' in existing:
            print('SettingsPageVisibility contains "showonly", skipping')
            return

        if not existing:
            registry_setstring(HKEY_LOCAL_MACHINE, SETTINGS_PAGE_KEY, 'SettingsPageVisibility', f'hide:{AI_PAGES_TO_HIDE}')
        elif AI_PAGES_TO_HIDE not in existing:
            sep = '' if existing.endswith(';') else ';'
            registry_setstring(HKEY_LOCAL_MACHINE, SETTINGS_PAGE_KEY, 'SettingsPageVisibility', f'{existing}{sep}{AI_PAGES_TO_HIDE}')
    else:
        if not existing:
            return
        if existing == f'hide:{AI_PAGES_TO_HIDE}':
            registry_delete(HKEY_LOCAL_MACHINE, SETTINGS_PAGE_KEY, 'SettingsPageVisibility')
        else:
            registry_setstring(HKEY_LOCAL_MACHINE, SETTINGS_PAGE_KEY, 'SettingsPageVisibility', existing.replace(AI_PAGES_TO_HIDE, ''))

    print(f'AI components {"hidden" if hide else "unhidden"} in Settings')


def run_as_trustedinstaller(command):
    """Execute a command as TrustedInstaller by hijacking the TI service binPath."""

    ti_service = 'TrustedInstaller'
    ti_default_bin = rf'{os.environ["SystemRoot"]}\servicing\TrustedInstaller.exe'

    # Stop TrustedInstaller if running
    try:
        if service_is_running(ti_service):
            service_stop(ti_service)
    except Exception:
        run('taskkill /im trustedinstaller.exe /f', accept_returncodes=[0, 128, 1])

    # Swap binPath to our command, start, then revert
    run(f'sc.exe config {ti_service} binPath="{command}"')
    run(f'sc.exe start {ti_service}', accept_returncodes=[0, 1056, 1053])
    time.sleep(2)
    run(f'sc.exe config {ti_service} binPath="{ti_default_bin}"')

    # Stop again to clean up
    try:
        if service_is_running(ti_service):
            service_stop(ti_service)
    except Exception:
        run('taskkill /im trustedinstaller.exe /f', accept_returncodes=[0, 128, 1])


def run_powershell_as_ti(ps_commands):
    """Run PowerShell command(s) as TrustedInstaller via a temp script file."""
    if isinstance(ps_commands, list):
        script_content = '\n'.join(ps_commands)
    else:
        script_content = ps_commands

    script_path = makepath(tempfile.gettempdir(), 'wapt_ti_script.ps1')
    log_path = makepath(tempfile.gettempdir(), 'wapt_ti_script.log')

    if DEBUG:
        script_content = re.sub(r'-E(?:rrorAction|A)\s+(?:SilentlyContinue|0)', '-EA Continue', script_content)
        print("Script RUN as Trusted Installer: \n" + script_content)
        script_content = f'Start-Transcript -Path "{log_path}" -Force\n{script_content}\nStop-Transcript'

    with open(script_path, 'w', encoding='utf-8') as f:
        f.write(script_content)

    try:
        run_as_trustedinstaller(f'cmd.exe /c powershell.exe -win hidden -nop -ep bypass -file "{script_path}"')
    finally:
        if isfile(log_path):
            with open(log_path, 'r', encoding='utf-8', errors='ignore') as f:
                log_content = f.read().strip()
            if log_content:
                print(f'TrustedInstaller output:\n{log_content}')
            remove_file(log_path)
        if isfile(script_path):
            remove_file(script_path)


def set_registry_keys_hklm(disable=True):
    """Apply or revert Windows AI registry keys in HKLM"""

    if disable:
        registry_deletekey(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsAI', 'LastConfiguration')

    # Windows Copilot and WindowsAI policies
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsCopilot', 'TurnOffWindowsCopilot', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableAIDataAnalysis', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'AllowRecallEnablement', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableClickToDo', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'TurnOffSavingSnapshots', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableSettingsAgent', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableAgentConnectors', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableAgentWorkspaces', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableRemoteAgentConnectors', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\Shell\Copilot\BingChat', 'IsUserEligible', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\Shell\Copilot', 'IsCopilotAvailable', 0 if disable else 1)
    registry_setstring(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\Shell\Copilot', 'CopilotDisabledReason', 'FeatureIsDisabled' if disable else ' ')

    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\Capabilities\systemAIModels', 'RecordUsageData', 0 if disable else 1)

    # Copilot in Edge
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'CopilotCDPPageContext', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'CopilotPageContext', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'HubsSidebarEnabled', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'EdgeEntraCopilotPageContext', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'Microsoft365CopilotChatIconEnabled', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'EdgeHistoryAISearchEnabled', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'ComposeInlineEnabled', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'GenAILocalFoundationalModelSettings', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'BuiltInAIAPIsEnabled', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'AIGenThemesEnabled', 0 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'DevToolsGenAiSettings', 2 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Edge', 'ShareBrowsingHistoryWithCopilotSearchAllowed', 0 if disable else 1)

    # AI in Office
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\training\general', 'disabletraining', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\training\specific\adaptivefloatie', 'disabletrainingofadaptivefloatie', 1 if disable else 0)

    # Office AI content safety
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\contentsafety\general', 'disablecontentsafety', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\contentsafety\specific\alternativetext', 'disablecontentsafety', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\contentsafety\specific\imagequestionandanswering', 'disablecontentsafety', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\contentsafety\specific\promptassistance', 'disablecontentsafety', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\contentsafety\specific\rewrite', 'disablecontentsafety', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\contentsafety\specific\summarization', 'disablecontentsafety', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\contentsafety\specific\summarizationwithreferences', 'disablecontentsafety', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\office\16.0\common\ai\contentsafety\specific\texttotable', 'disablecontentsafety', 1 if disable else 0)

    # Additional keys
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings', 'AutoOpenCopilotLargeScreens', 0 if disable else 1)
    registry_setstring(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\generativeAI', 'Value', 'Deny' if disable else 'Allow')
    registry_setstring(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\systemAIModels', 'Value', 'Deny' if disable else 'Allow')
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'LetAppsAccessGenerativeAI', 2 if disable else 1)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'LetAppsAccessSystemAIModels', 2 if disable else 1)

    # AI actions (Feature Management)
    fm_base = r'SYSTEM\ControlSet001\Control\FeatureManagement\Overrides\8'
    fm_ids_state1 = ['1853569164', '4098520719', '929719951', '1546588812', '203105932', '2381287564',
                     '3189581453', '3552646797', '3389499533', '4027803789', '450471565', '2283032206', '502943886']
    for fm_id in fm_ids_state1:
        registry_set(HKEY_LOCAL_MACHINE, makepath(fm_base, fm_id), 'EnabledState', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, makepath(fm_base, '1646260367'), 'EnabledState', 2 if disable else 0)

    # Copilot ads in Settings
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\Microsoft\Windows\CloudContent', 'DisableConsumerAccountStateContent', 1 if disable else 0)

    # AI image creator in Paint
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Paint', 'DisableImageCreator', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Paint', 'DisableCocreator', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Paint', 'DisableGenerativeFill', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Paint', 'DisableGenerativeErase', 1 if disable else 0)
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Paint', 'DisableRemoveBackground', 1 if disable else 0)

    # Notepad AI
    registry_set(HKEY_LOCAL_MACHINE, r'SOFTWARE\Policies\WindowsNotepad', 'DisableAIFeatures', 1 if disable else 0)


def apply_hku_keys(sid, disable=True):
    """Apply HKU AI registry keys for a given user SID"""

    if disable:
        # Delete user Copilot keys
        registry_delete(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\Shell\Copilot'), 'CopilotLogonTelemetryTime')
        registry_deletekey(HKEY_USERS, makepath(sid, r'Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\Microsoft.Copilot_8wekyb3d8bbwe'), 'Copilot.StartupTaskId')
        registry_deletekey(HKEY_USERS, makepath(sid, r'Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe'), 'WebViewHostStartupId')
        registry_delete(HKEY_USERS, makepath(sid, r'Software\Microsoft\Copilot'), 'WakeApp')

    # Windows Copilot and WindowsAI policies
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsCopilot'), 'TurnOffWindowsCopilot', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI'), 'DisableAIDataAnalysis', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI'), 'AllowRecallEnablement', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI'), 'DisableClickToDo', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI'), 'TurnOffSavingSnapshots', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI'), 'DisableSettingsAgent', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI'), 'DisableAgentConnectors', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI'), 'DisableAgentWorkspaces', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI'), 'DisableRemoteAgentConnectors', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Microsoft\Windows\Shell\Copilot\BingChat'), 'IsUserEligible', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Microsoft\Windows\Shell\Copilot'), 'IsCopilotAvailable', 0 if disable else 1)
    registry_setstring(HKEY_USERS, makepath(sid, r'SOFTWARE\Microsoft\Windows\Shell\Copilot'), 'CopilotDisabledReason', 'FeatureIsDisabled' if disable else ' ')

    # Microphone access to Copilot
    registry_setstring(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone\Microsoft.Copilot_8wekyb3d8bbwe'), 'Value', 'Deny' if disable else 'Prompt')
    registry_setstring(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe'), 'Value', 'Deny' if disable else 'Prompt')
    registry_setstring(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\systemAIModels'), 'Value', 'Deny' if disable else 'Prompt')

    # Voice activation and Copilot button
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Speech_OneCore\Settings\VoiceActivation\UserPreferenceForAllApps'), 'AgentActivationEnabled', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'), 'ShowCopilotButton', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\input\Settings'), 'InsightsEnabled', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\Shell\ClickToDo'), 'DisableClickToDo', 1 if disable else 0)

    # Copilot in Windows Search
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\Explorer'), 'DisableSearchBoxSuggestions', 1 if disable else 0)

    # AI in Office (user settings)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Policies\Microsoft\office\16.0\common\privacy'), 'controllerconnectedservicesenabled', 2 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Policies\Microsoft\office\16.0\common\privacy'), 'usercontentdisabled', 2 if disable else 1)

    # Copilot in Word, Excel, OneNote
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Office\16.0\Word\Options'), 'EnableCopilot', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Office\16.0\Excel\Options'), 'EnableCopilot', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Office\16.0\OneNote\Options\Copilot'), 'CopilotEnabled', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Office\16.0\OneNote\Options\Copilot'), 'CopilotNotebooksEnabled', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Office\16.0\OneNote\Options\Copilot'), 'CopilotSkittleEnabled', 0 if disable else 1)

    # Additional keys
    registry_set(HKEY_USERS, makepath(sid, r'SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsCopilot'), 'AllowCopilotRuntime', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband\AuxilliaryPins'), 'CopilotPWAPin', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband\AuxilliaryPins'), 'RecallPin', 0 if disable else 1)

    # Copilot background access
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications\Microsoft.Copilot_8wekyb3d8bbwe'), 'DisabledByUser', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications\Microsoft.Copilot_8wekyb3d8bbwe'), 'Disabled', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications\Microsoft.Copilot_8wekyb3d8bbwe'), 'SleepDisabled', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe'), 'DisabledByUser', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe'), 'Disabled', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe'), 'SleepDisabled', 1 if disable else 0)

    # Ask Copilot (taskbar search)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'), 'TaskbarCompanion', 0 if disable else 1)

    branded_choice = 'Search' if disable else 'App'
    branded_aumid = ' ' if disable else 'Microsoft.Copilot_8wekyb3d8bbwe!App'
    run_powershell_as_ti([
        f'Set-ItemProperty -Path "Registry::HKU\\{sid}\\Software\\Microsoft\\Windows\\Shell\\BrandedKey" -Name "BrandedKeyChoiceType" -Value "{branded_choice}" -Force -EA 0',
        f'Set-ItemProperty -Path "Registry::HKU\\{sid}\\Software\\Microsoft\\Windows\\Shell\\BrandedKey" -Name "AppAumid" -Value "{branded_aumid}" -Force -EA 0',
    ])

    registry_setstring(HKEY_USERS, makepath(sid, r'SOFTWARE\Policies\Microsoft\Windows\CopilotKey'), 'SetCopilotHardwareKey', ' ' if disable else 'Microsoft.Copilot_8wekyb3d8bbwe!App')

    # Recall customized homepage
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\SettingSync\WindowsSettingHandlers'), 'A9HomeContentEnabled', 0 if disable else 1)

    # Typing data harvesting for AI training
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\InputPersonalization'), 'RestrictImplicitInkCollection', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\InputPersonalization'), 'RestrictImplicitTextCollection', 1 if disable else 0)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\InputPersonalization\TrainedDataStore'), 'HarvestContacts', 0 if disable else 1)
    registry_set(HKEY_USERS, makepath(sid, r'Software\Microsoft\Windows\CurrentVersion\CPSS\Store\InkingAndTypingPersonalization'), 'Value', 0 if disable else 1)

    # Office Hub startup
    registry_set(HKEY_USERS, makepath(sid, r'Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe\WebViewHostStartupId'), 'State', 1 if disable else 2)


def set_registry_keys_hku(disable=True):
    """Apply or revert HKU AI registry keys for all active users"""
    for sid in get_active_user_sids():
        print(f'{"Disabling" if disable else "Enabling"} HKU AI keys for {sid}')
        apply_hku_keys(sid, disable=disable)


def remove_ai_appx_packages():
    """Removes AI-related Appx packages (Copilot, AIX, CoreAI, etc.)"""

    store = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore'
    user_sids = ['S-1-5-18']

    for profile in get_local_profiles():
        sid = profile.get('sid', '')
        if sid.startswith('S-1-5-21') and sid not in user_sids:
            user_sids.append(sid)

    # Get provisioned and installed packages
    provisioned = get_provisioned_appx()
    appx_all = get_installed_appx()

    appx_by_name = {pkg['Name']: pkg for pkg in appx_all if pkg.get('Name')}

    def ensure_reg_key(path):
        try:
            with reg_openkey_noredir(HKEY_LOCAL_MACHINE, path, create_if_missing=True):
                pass
        except Exception:
            pass

    rollback_file = makepath(persistent_dir, 'appx_rollback.json')
    if isfile(rollback_file):
        with open(rollback_file, 'r') as f:
            rollback = json.load(f)
    else:
        rollback = {
            'deprovisioned_keys': [],
            'endoflife_keys': [],
            'removed_packages': [],
            'deprovisioned_packages': [],
        }

    ti_commands = []

    print('Removing AI Appx packages...')

    # Remove provisioned packages
    for prov in find_matching_ai_packages(provisioned, key='PackageName'):
        pkg_name = prov.get('PackageName', '')
        display_name = prov.get('DisplayName', '')

        pkg_family = appx_by_name.get(display_name, {}).get('PackageFamilyName', '')
        if pkg_family:
            ensure_reg_key(makepath(store, 'Deprovisioned', pkg_family))
            rollback['deprovisioned_keys'].append(makepath(store, 'Deprovisioned', pkg_family))
            ti_commands.append(f'Set-NonRemovableAppsPolicy -Online -PackageFamilyName "{pkg_family}" -NonRemovable 0 -EA 0')

            for sid in user_sids:
                eol_key = makepath(store, 'EndOfLife', sid, pkg_name)
                ensure_reg_key(eol_key)
                rollback['endoflife_keys'].append(eol_key)

        ti_commands.append(f'Remove-AppxProvisionedPackage -PackageName "{pkg_name}" -Online -AllUsers -EA 0')
        rollback['deprovisioned_packages'].append({'PackageName': pkg_name, 'DisplayName': display_name})
        print(f'Deprovisioned: {display_name}')

    # Remove installed packages
    for pkg in find_matching_ai_packages(appx_all, key='PackageFullName'):
        full_name = pkg.get('PackageFullName', '')
        pkg_family = pkg.get('PackageFamilyName', '')
        
        if pkg_family:
            ensure_reg_key(makepath(store, 'Deprovisioned', pkg_family))
            rollback['deprovisioned_keys'].append(makepath(store, 'Deprovisioned', pkg_family))
            ti_commands.append(f'Set-NonRemovableAppsPolicy -Online -PackageFamilyName "{pkg_family}" -NonRemovable 0 -EA 0')

        # Remove from InboxApplications
        if reg_key_exists(HKEY_LOCAL_MACHINE, makepath(store, 'InboxApplications', full_name)):
            ti_commands.append(f'Remove-Item "HKLM:\\{makepath(store, "InboxApplications", full_name)}" -Recurse -Force -EA 0')

        # Mark EndOfLife and remove per user
        pkg_user_sids = [s for s in (pkg.get('UserSIDs', '')).split(',') if s]
        for sid in pkg_user_sids:

            if sid not in user_sids:
                user_sids.append(sid)

            eol_key = makepath(store, 'EndOfLife', sid, full_name)
            ensure_reg_key(eol_key)
            rollback['endoflife_keys'].append(eol_key)
            ti_commands.append(f'Remove-AppxPackage -Package "{full_name}" -User "{sid}" -EA 0')

        ti_commands.append(f'Remove-AppxPackage -Package "{full_name}" -AllUsers -EA 0')
        rollback['removed_packages'].append({'PackageFullName': full_name, 'PackageFamilyName': pkg_family, 'UserSIDs': pkg_user_sids})
        print(f'Removed: {full_name}')

    if ti_commands:
        run_powershell_as_ti(ti_commands)

    rollback['deprovisioned_keys'] = list(set(rollback['deprovisioned_keys']))
    rollback['endoflife_keys'] = list(set(rollback['endoflife_keys']))

    # Save rollback data
    with open(rollback_file, 'w') as f:
        json.dump(rollback, f, indent=2)
    print(f'Rollback data saved to {rollback_file}')


def disable_copilot_policies():
    """Disables CoPilot/Recall/AI policies in IntegratedServicesRegionPolicySet.json and VisualAssist"""

    # IntegratedServicesRegionPolicySet.json
    json_path = makepath(os.environ['SystemRoot'], 'System32', 'IntegratedServicesRegionPolicySet.json')
    if isfile(json_path):
        print(f'Disabling CoPilot policies in {json_path}')

        run_powershell_as_ti([
            f'takeown /f "{json_path}"',
            f'icacls "{json_path}" /grant *S-1-5-32-544:F /t',
        ])

        with open(json_path, 'r', encoding='utf-8') as f:
            data = json.load(f)

        modified = 0
        for policy in data.get('policies', []):
            comment = policy.get('$comment', '')
            if 'CoPilot' in comment:
                policy['defaultState'] = 'disabled'
                modified += 1
            elif 'A9' in comment:
                policy['defaultState'] = 'enabled'
                modified += 1
            elif 'Manage Recall' in comment:
                policy['defaultState'] = 'disabled'
                modified += 1
            elif 'Settings Agent' in comment:
                policy['defaultState'] = 'enabled'
                modified += 1

        with open(json_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
        print(f'{modified} CoPilot policies disabled')

    # VisualAssist
    va_path = makepath(os.environ['SystemRoot'], 'SystemApps', 'MicrosoftWindows.Client.CBS_cw5n1h2txyewy', 'VisualAssist', 'VisualAssistActions.json')
    if isfile(va_path):
        print('Disabling Generative AI in Visual Assist...')
        run_powershell_as_ti([
            f'takeown /f "{va_path}"',
            f'icacls "{va_path}" /grant *S-1-5-32-544:F /t',
        ])

        with open(va_path, 'r', encoding='utf-8') as f:
            data = json.load(f)

        modified = False
        for action in data.get('actions', []):
            if isinstance(action, dict) and 'usesGenerativeAI' in action:
                action['usesGenerativeAI'] = False
                modified = True
        if modified:
            with open(va_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=2, ensure_ascii=False)
        print('Visual Assist Generative AI disabled')


def enable_copilot_policies():
    """Re-enables CoPilot/Recall/AI policies in IntegratedServicesRegionPolicySet.json and VisualAssist"""

    json_path = makepath(os.environ['SystemRoot'], 'System32', 'IntegratedServicesRegionPolicySet.json')
    if isfile(json_path):
        print(f'Re-enabling CoPilot policies in {json_path}')
        run_powershell_as_ti([
            f'takeown /f "{json_path}"',
            f'icacls "{json_path}" /grant *S-1-5-32-544:F /t',
        ])

        with open(json_path, 'r', encoding='utf-8') as f:
            data = json.load(f)

        for policy in data.get('policies', []):
            comment = policy.get('$comment', '')
            if 'CoPilot' in comment:
                policy['defaultState'] = 'enabled'
            elif 'A9' in comment:
                policy['defaultState'] = 'disabled'
            elif 'Manage Recall' in comment:
                policy['defaultState'] = 'enabled'
            elif 'Settings Agent' in comment:
                policy['defaultState'] = 'disabled'

        with open(json_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
        print('CoPilot policies re-enabled')

    va_path = makepath(os.environ['SystemRoot'], 'SystemApps', 'MicrosoftWindows.Client.CBS_cw5n1h2txyewy', 'VisualAssist', 'VisualAssistActions.json')
    if isfile(va_path):
        print('Re-enabling Generative AI in Visual Assist...')
        run_powershell_as_ti([
            f'takeown /f "{va_path}"',
            f'icacls "{va_path}" /grant *S-1-5-32-544:F /t',
        ])

        with open(va_path, 'r', encoding='utf-8') as f:
            data = json.load(f)

        for action in data.get('actions', []):
            if isinstance(action, dict) and 'usesGenerativeAI' in action:
                action['usesGenerativeAI'] = True
        with open(va_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
        print('Visual Assist Generative AI re-enabled')


def restore_ai_appx_packages():
    """Restores AI Appx packages by removing Deprovisioned/EndOfLife registry blocks"""

    rollback_file = makepath(persistent_dir, 'appx_rollback.json')
    if isfile(rollback_file):
        print('No rollback data found, skipping Appx restore')
        return

    with open(rollback_file, 'r') as f:
        rollback = json.load(f)

    # Remove Deprovisioned keys
    for key_path in rollback.get('deprovisioned_keys', []):
        try:
            parent, child = key_path.rsplit('\\', 1)
            registry_deletekey(HKEY_LOCAL_MACHINE, parent, child)
            print(f'Removed Deprovisioned key: {child}')
        except Exception:
            pass

    # Remove EndOfLife keys
    for key_path in rollback.get('endoflife_keys', []):
        try:
            parent, child = key_path.rsplit('\\', 1)
            registry_deletekey(HKEY_LOCAL_MACHINE, parent, child)
            print(f'Removed EndOfLife key: {child}')
        except Exception:
            pass

    remove_file(rollback_file)
    print('Appx rollback complete. Packages will be restored by Windows Update.')


def remove_recall_feature():
    """Removes the Recall optional feature from Windows"""
    print('Removing Recall Optional Feature...')
    try:
        state = run_powershell("(Get-WindowsOptionalFeature -Online -FeatureName 'Recall' -EA Stop).State", output_format='text')
        if state and state.strip() and 'DisabledWithPayloadRemoved' not in state:
            try:
                run_powershell("Disable-WindowsOptionalFeature -Online -FeatureName 'Recall' -Remove -NoRestart -EA Stop", output_format='text')
            except Exception:
                run('dism.exe /Online /Disable-Feature /FeatureName:Recall /Remove /NoRestart /Quiet', accept_returncodes=[0, 87])
        else:
            print('Recall already removed')
    except Exception:
        # Fallback to dism if PowerShell cmdlet not available
        result = run('dism.exe /Online /Get-FeatureInfo /FeatureName:Recall',accept_returncodes=[0, 87])
        if 'Disabled with Payload Removed' not in result:
            run('dism.exe /Online /Disable-Feature /FeatureName:Recall /Remove /NoRestart /Quiet', accept_returncodes=[0, 87])
        else:
            print('Recall already removed')


def remove_recall_tasks():
    """Removes and disables Recall and Office Actions Server scheduled tasks"""
    print('Removing Recall Scheduled Tasks...')

    ti_command = [
        f'Get-ScheduledTask -TaskPath "*WindowsAI*" -EA 0 | Disable-ScheduledTask -EA 0',
        f'Get-ScheduledTask -TaskName "*Office Actions Server*" -EA 0 | Disable-ScheduledTask -EA 0',
        rf'Remove-Item "{os.environ["SystemRoot"]}\System32\Tasks\Microsoft\Windows\WindowsAI" -Recurse -Force -EA 0',
        rf'Remove-Item "{os.environ["SystemRoot"]}\System32\Tasks\Microsoft\Office\Office Actions Server" -Force -EA 0',
    ]

    # Clean task cache registry entries
    cache_base = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache'
    for task_name in AI_TASKS:
        task_id = registry_readstring(HKEY_LOCAL_MACHINE, makepath(cache_base, 'Tree', task_name.lstrip('\\')), 'Id')
        if task_id:
            ti_command.append(f'Remove-Item "HKLM:\\{cache_base}\\Tasks\\{task_id}" -Recurse -Force -EA 0')

    tasks_to_delete = [
        r'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Windows\WindowsAI',
        r'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Office\Office Actions Server',
    ]
    for path in tasks_to_delete:
        ti_command.append(f'Remove-Item "{path}" -Recurse -Force -EA 0')

    run_powershell_as_ti(ti_command)
    print('Recall Scheduled Tasks removed')


def remove_ai_cbs_packages():
    """Removes hidden AI CBS packages (AIX, Recall, Copilot, CoreAI) via DISM"""

    CBS_AI_PATTERNS = ['AIX', 'Recall', 'Copilot', 'CoreAI']
    cbs_path = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages'
    servicing_dir = makepath(os.environ['SystemRoot'], 'servicing', 'Packages')

    print('Removing Additional Hidden AI CBS Packages...')

    ti_commands = []
    subkeys = reg_enum_subkeys(reg_openkey_noredir(HKEY_LOCAL_MACHINE, cbs_path))
    for pkg_name in subkeys:
        # Check if package matches AI patterns
        if not any(p in pkg_name for p in CBS_AI_PATTERNS):
            continue

        pkg_key = makepath(cbs_path, pkg_name)
        visibility = registry_get(HKEY_LOCAL_MACHINE, pkg_key, 'Visibility')

        # Only process hidden packages
        if visibility != 2:
            continue

        # Unhide the package for removal
        registry_set(HKEY_LOCAL_MACHINE, pkg_key, 'Visibility', 1)
        registry_set(HKEY_LOCAL_MACHINE, pkg_key, 'DefVis', 2)

        # Remove Owners and Updates subkeys to allow removal
        if reg_key_exists(HKEY_LOCAL_MACHINE, makepath(pkg_key, 'Owners')):
            registry_deletekey(HKEY_LOCAL_MACHINE, pkg_key, 'Owners', force=True, recursive=True)
        if reg_key_exists(HKEY_LOCAL_MACHINE, makepath(pkg_key, 'Updates')):
            registry_deletekey(HKEY_LOCAL_MACHINE, pkg_key, 'Updates', force=True, recursive=True)

        ti_commands.append(f'dism.exe /Online /Remove-Package /PackageName:{pkg_name} /NoRestart /Quiet')
        ti_commands.append(f'Remove-Item "{makepath(servicing_dir, f"*{pkg_name}*")}" -Force -EA 0')

        print(f'Removed CBS: {pkg_name}')

    if ti_commands:
        run_powershell_as_ti(ti_commands)


def install():
    kill_ai_processes()
    set_registry_keys_hklm(disable=True)
    disable_copilot_policies()
    remove_recall_feature()
    remove_recall_tasks()
    remove_ai_appx_packages()
    remove_ai_cbs_packages()
    set_ai_settings_visibility(hide=True)
    set_registry_keys_hku(disable=True)


def uninstall():
    set_registry_keys_hklm(disable=False)
    enable_copilot_policies()
    restore_ai_appx_packages()
    set_ai_settings_visibility(hide=False)
    set_registry_keys_hku(disable=False)


def audit():

    audit_status = 'OK'

    # TrustedInstaller service binPath
    ti_expected = rf'{os.environ["SystemRoot"]}\servicing\TrustedInstaller.exe'
    ti_binpath = registry_readstring(HKEY_LOCAL_MACHINE, r'SYSTEM\CurrentControlSet\Services\TrustedInstaller', 'ImagePath')
    if ti_binpath and ti_binpath.strip() != ti_expected:
        print(f'TrustedInstaller binPath not restored: {ti_binpath}')
        audit_status = 'ERROR'

    # Registry keys HKLM
    registry_checks = [
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsCopilot', 'TurnOffWindowsCopilot', 1),
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableAIDataAnalysis', 1),
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'AllowRecallEnablement', 0),
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableClickToDo', 1),
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'TurnOffSavingSnapshots', 1),
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableSettingsAgent', 1),
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableAgentConnectors', 1),
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableAgentWorkspaces', 1),
        (r'SOFTWARE\Policies\Microsoft\Windows\WindowsAI', 'DisableRemoteAgentConnectors', 1),
        (r'SOFTWARE\Microsoft\Windows\Shell\Copilot', 'IsCopilotAvailable', 0),
        (r'SOFTWARE\Policies\Microsoft\Edge', 'HubsSidebarEnabled', 0),
        (r'SOFTWARE\Policies\Microsoft\Edge', 'CopilotCDPPageContext', 0),
        (r'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'LetAppsAccessGenerativeAI', 2),
        (r'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'LetAppsAccessSystemAIModels', 2),
        (r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Paint', 'DisableImageCreator', 1),
        (r'SOFTWARE\Policies\WindowsNotepad', 'DisableAIFeatures', 1),
    ]

    for path, name, expected in registry_checks:
        val = registry_get(HKEY_LOCAL_MACHINE, path, name)
        if val != expected:
            print(f'{name} not configured (expected {expected}, got {val})')
            audit_status = 'ERROR'

    # Copilot policies in IntegratedServicesRegionPolicySet.json
    json_path = makepath(os.environ['SystemRoot'], 'System32', 'IntegratedServicesRegionPolicySet.json')
    if isfile(json_path):
        with open(json_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        for policy in data.get('policies', []):
            comment = policy.get('$comment', '')
            if 'CoPilot' in comment and policy.get('defaultState') != 'disabled':
                print(f'CoPilot policy still enabled: {comment}')
                audit_status = 'ERROR'
            elif 'Manage Recall' in comment and policy.get('defaultState') != 'disabled':
                print(f'Recall policy still enabled: {comment}')
                audit_status = 'ERROR'

    # Recall optional feature
    state = run_powershell("(Get-WindowsOptionalFeature -Online -FeatureName 'Recall' -EA Stop).State", output_format='text')
    if state and state.strip() and 'DisabledWithPayloadRemoved' not in state and 'Disabled' not in state:
        print(f'Recall feature still present: {state.strip()}')
        audit_status = 'ERROR'

    # Recall scheduled tasks
    for task_name in AI_TASKS:
        if task_exists(task_name):
            print(f'AI task still exists: {task_name}')
            audit_status = 'ERROR'

    # AI Appx packages
    remaining_installed = find_matching_ai_packages(get_installed_appx(), key='PackageFullName')
    for pkg in remaining_installed:
        print(f'AI package still installed: {pkg["PackageFullName"]}')
        audit_status = 'ERROR'

    remaining_provisioned = find_matching_ai_packages(get_provisioned_appx(), key='PackageName')
    for prov in remaining_provisioned:
        print(f'AI package still provisioned: {prov["PackageName"]}')
        audit_status = 'ERROR'

    # AI CBS packages
    CBS_AI_PATTERNS = ['AIX', 'Recall', 'Copilot', 'CoreAI']
    cbs_path = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages'
    subkeys = reg_enum_subkeys(reg_openkey_noredir(HKEY_LOCAL_MACHINE, cbs_path))
    for pkg_name in subkeys:
        if any(p in pkg_name for p in CBS_AI_PATTERNS):
            visibility = registry_get(HKEY_LOCAL_MACHINE, makepath(cbs_path, pkg_name), 'Visibility')
            if visibility == 2:
                print(f'Hidden AI CBS package still present: {pkg_name}')
                audit_status = 'ERROR'

    # Settings visibility
    SETTINGS_PAGE_KEY = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer'
    AI_PAGES_TO_HIDE = 'aicomponents;appactions;'
    existing = registry_readstring(HKEY_LOCAL_MACHINE, SETTINGS_PAGE_KEY, 'SettingsPageVisibility')
    if not existing or AI_PAGES_TO_HIDE not in existing:
        print('AI settings pages not hidden')
        audit_status = 'ERROR'

    return audit_status

c84b1911368f715a4f5cc145ac034c80ff2446a8a600a79709062591f9b61441 : WAPT/README.md
67dda6ec6cde7b488fe89cd0df3fc267bc6f5a253b884e3e5113701fb0bc1d38 : WAPT/README_fr.md
38d056ab130f7bf7c481c12636a4e9959de36561d3dfcbe54c6e3571bc0c1dc3 : WAPT/certificate.crt
359d13a8c18f67efaa65f8b4dc5fb7ba22af195dffb141ba006c946c77d2fc90 : WAPT/control
7891f1ca19ac8a9e41cb2963c0833bb3424a1dcc3f89e6ae484b1841a67063b2 : WAPT/icon.png
4a078464913c49e588d192dd31779dd2eec4609859b02382eccb3b788699723a : luti.json
2da68a11fe50c990376600e895bc64d7c83a79b55c8c27fcd45e755c9108b464 : setup.py