skills: 9 skill-uri de agent ROA (COMUN\skills) + legare si rutare
- leaga_skills.ps1: expune skill-urile in ~/.claude/skills prin symlink (citit si de Claude Code, si de opencode), fara copiere - rutare zona->skill in reguli_lucru pct. 7, README, AGENTS.md; skill-ul devine proprietarul procedurii, docurile raman referinta conditionata - rec_skills.md: decizia, inventarul si cum se adauga un skill nou
This commit is contained in:
162
utile/leaga_skills.ps1
Normal file
162
utile/leaga_skills.ps1
Normal file
@@ -0,0 +1,162 @@
|
||||
# leaga_skills.ps1 - expune folderul canonic de agent-skills al ROA catre agenti, fara sa dubleze fisiere.
|
||||
# Creeaza cate un link de director (symlink) pentru fiecare skill din sursa in folderul global
|
||||
# %USERPROFILE%\.claude\skills. Atat Claude Code cat si opencode citesc %USERPROFILE%\.claude\skills\<nume>\SKILL.md,
|
||||
# deci un singur set de link-uri serveste ambele gazde.
|
||||
# Link-urile de director cer Developer Mode pe Windows sau o consola de administrator (mklink /D).
|
||||
# Utilizare:
|
||||
# powershell -File COMUN\utile\leaga_skills.ps1 # leaga toate skill-urile
|
||||
# powershell -File COMUN\utile\leaga_skills.ps1 -DryRun # doar listeaza ce ar face
|
||||
# powershell -File COMUN\utile\leaga_skills.ps1 -Force # inlocuieste si link-urile care arata in alta parte
|
||||
param(
|
||||
[string]$Source = (Join-Path $PSScriptRoot '..\skills'),
|
||||
[string]$Target = (Join-Path $env:USERPROFILE '.claude\skills'),
|
||||
[switch]$DryRun,
|
||||
[switch]$Force
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Normalize-Cale {
|
||||
param([string]$Cale)
|
||||
if (-not $Cale) { return '' }
|
||||
([System.IO.Path]::GetFullPath($Cale)).TrimEnd('\')
|
||||
}
|
||||
|
||||
function Ia-TintaLink {
|
||||
# PowerShell 5.1 da Target ca string, PowerShell 7 ca lista de string-uri
|
||||
param($Item)
|
||||
$t = $Item.Target
|
||||
if ($t -is [array]) { return ($t | Select-Object -First 1) }
|
||||
return $t
|
||||
}
|
||||
|
||||
function Sterge-Link {
|
||||
# sterge doar link-ul (reparse point), niciodata continutul din tinta
|
||||
param([string]$Link)
|
||||
try {
|
||||
if (Test-Path -LiteralPath $Link -PathType Container) {
|
||||
[System.IO.Directory]::Delete($Link, $false)
|
||||
} else {
|
||||
Remove-Item -LiteralPath $Link -Force
|
||||
}
|
||||
return $true
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Creeaza-Link {
|
||||
# intoarce $true la succes; $script:EroareLink primeste mesajul la esec
|
||||
param([string]$Link, [string]$Dir)
|
||||
$script:EroareLink = ''
|
||||
try {
|
||||
New-Item -ItemType SymbolicLink -Path $Link -Target $Dir -ErrorAction Stop | Out-Null
|
||||
return $true
|
||||
} catch {
|
||||
$script:EroareLink = $_.Exception.Message
|
||||
}
|
||||
$r = & cmd /c mklink /D "$Link" "$Dir" 2>&1
|
||||
if ($LASTEXITCODE -eq 0) { return $true }
|
||||
$script:EroareLink = (($r | ForEach-Object { [string]$_ }) -join ' ').Trim()
|
||||
return $false
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Source -PathType Container)) {
|
||||
Write-Output ('leaga_skills: nu gasesc folderul sursa ' + $Source + ' - nimic de facut.')
|
||||
exit 0
|
||||
}
|
||||
$skilluri = @(Get-ChildItem -LiteralPath $Source -Directory | Sort-Object Name)
|
||||
if ($skilluri.Count -eq 0) {
|
||||
Write-Output ('leaga_skills: ' + $Source + ' nu contine niciun subfolder de skill - nimic de facut.')
|
||||
exit 0
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Target -PathType Container)) {
|
||||
if ($DryRun) {
|
||||
Write-Output ('DryRun - as crea folderul tinta ' + $Target)
|
||||
} else {
|
||||
New-Item -ItemType Directory -Force -Path $Target | Out-Null
|
||||
Write-Output ('creat folderul tinta ' + $Target)
|
||||
}
|
||||
}
|
||||
|
||||
$creat = 0; $ok = 0; $atentionat = 0; $anuntPrivilegii = $false
|
||||
|
||||
foreach ($s in $skilluri) {
|
||||
$dir = $s.FullName
|
||||
$link = Join-Path $Target $s.Name
|
||||
$item = Get-Item -LiteralPath $link -Force -ErrorAction SilentlyContinue
|
||||
|
||||
if (-not $item) {
|
||||
if ($DryRun) {
|
||||
Write-Output (' ar crea ' + $s.Name + ' -> ' + $dir)
|
||||
$creat++
|
||||
continue
|
||||
}
|
||||
if (Creeaza-Link -Link $link -Dir $dir) {
|
||||
Write-Output (' creat ' + $s.Name + ' -> ' + $dir)
|
||||
$creat++
|
||||
} else {
|
||||
Write-Output (' EROARE ' + $s.Name + ' - ' + $script:EroareLink)
|
||||
$atentionat++
|
||||
if (-not $anuntPrivilegii) {
|
||||
Write-Output ' Link-urile de director cer Windows Developer Mode (Settings > Privacy & security > For developers)'
|
||||
Write-Output ' sau o consola PowerShell pornita ca administrator. Alternativ, copiaza manual folderele de skill.'
|
||||
$anuntPrivilegii = $true
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if ($item.LinkType) {
|
||||
$actual = Normalize-Cale (Ia-TintaLink $item)
|
||||
if ($actual -eq (Normalize-Cale $dir)) {
|
||||
Write-Output (' ok ' + $s.Name + ' (link deja corect)')
|
||||
$ok++
|
||||
continue
|
||||
}
|
||||
Write-Output ('Atentie: ' + $link + ' arata catre ' + $actual + ', nu catre ' + $dir)
|
||||
if (-not $Force) {
|
||||
Write-Output (' sarit ' + $s.Name + ' - ruleaza cu -Force ca sa il inlocuiesc.')
|
||||
$atentionat++
|
||||
continue
|
||||
}
|
||||
if ($DryRun) {
|
||||
Write-Output (' ar lega ' + $s.Name + ' (inlocuieste link-ul gresit) -> ' + $dir)
|
||||
$creat++
|
||||
continue
|
||||
}
|
||||
if (-not (Sterge-Link -Link $link)) {
|
||||
Write-Output (' EROARE ' + $s.Name + ' - nu pot sterge link-ul vechi.')
|
||||
$atentionat++
|
||||
continue
|
||||
}
|
||||
if (Creeaza-Link -Link $link -Dir $dir) {
|
||||
Write-Output (' refacut ' + $s.Name + ' -> ' + $dir)
|
||||
$creat++
|
||||
} else {
|
||||
Write-Output (' EROARE ' + $s.Name + ' - ' + $script:EroareLink)
|
||||
$atentionat++
|
||||
if (-not $anuntPrivilegii) {
|
||||
Write-Output ' Link-urile de director cer Windows Developer Mode (Settings > Privacy & security > For developers)'
|
||||
Write-Output ' sau o consola PowerShell pornita ca administrator.'
|
||||
$anuntPrivilegii = $true
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
# nume ocupat de un director/fisier real - nu il atingem niciodata
|
||||
$tip = 'fisier'
|
||||
if ($item.PSIsContainer) { $tip = 'director real' }
|
||||
Write-Output (' sarit ' + $s.Name + ' - ' + $tip + ' exista deja la ' + $link + '; nu il sterg si nu il suprascriu.')
|
||||
$atentionat++
|
||||
}
|
||||
|
||||
Write-Output ''
|
||||
if ($DryRun) {
|
||||
Write-Output ('leaga_skills (DryRun): ' + $creat + ' de creat, ' + $ok + ' ok, ' + $atentionat + ' atentionari')
|
||||
} else {
|
||||
Write-Output ('leaga_skills: ' + $creat + ' create, ' + $ok + ' ok, ' + $atentionat + ' atentionari')
|
||||
}
|
||||
exit 0
|
||||
Reference in New Issue
Block a user