-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathpowerskills.ps1
More file actions
129 lines (120 loc) · 3.85 KB
/
powerskills.ps1
File metadata and controls
129 lines (120 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<#
.SYNOPSIS
PowerSkills CLI — Windows capabilities for AI agents.
.DESCRIPTION
Standalone PowerShell toolkit exposing Outlook, Edge browser (CDP),
desktop automation, and system commands as structured JSON skills.
.EXAMPLE
.\powerskills.ps1 list
.\powerskills.ps1 outlook inbox --limit 10
.\powerskills.ps1 browser tabs
.\powerskills.ps1 desktop screenshot
.\powerskills.ps1 system exec --command "whoami"
#>
param(
[Parameter(Position=0)] [string]$Skill = "list",
[Parameter(Position=1)] [string]$Action = "",
[Parameter(ValueFromRemainingArguments)] [string[]]$Rest
)
$ErrorActionPreference = "Stop"
$script:SkillsRoot = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Path) "skills"
$script:ConfigPath = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Path) "config.json"
# ─── Config ───
function Get-PSConfig {
$defaults = @{
edge_debug_port = 9222
default_timeout = 30
outlook_body_max_chars = 5000
output_dir = ""
}
if (Test-Path $script:ConfigPath) {
try {
$file = Get-Content $script:ConfigPath -Raw | ConvertFrom-Json
foreach ($prop in $file.PSObject.Properties) {
$defaults[$prop.Name] = $prop.Value
}
} catch {}
}
return $defaults
}
# ─── Parse named args from Rest ───
function Parse-Args {
param([string[]]$Args_)
$parsed = @{}
$i = 0
while ($i -lt $Args_.Count) {
if ($Args_[$i] -match '^--(.+)$') {
$key = $Matches[1]
if (($i + 1) -lt $Args_.Count -and $Args_[$i+1] -notmatch '^--') {
$parsed[$key] = $Args_[$i+1]
$i += 2
} else {
$parsed[$key] = $true
$i++
}
} else {
$i++
}
}
return $parsed
}
# ─── Output helper ───
function Write-Result {
param($Data, [int]$ExitCode = 0)
$envelope = @{
status = if ($ExitCode -eq 0) { "success" } else { "error" }
exit_code = $ExitCode
data = $Data
timestamp = (Get-Date).ToString("o")
}
$envelope | ConvertTo-Json -Depth 10 -Compress
exit $ExitCode
}
function Write-Error-Result {
param([string]$Message)
Write-Result -Data @{ error = $Message } -ExitCode 1
}
# ─── Skill list ───
if ($Skill -eq "list") {
$skills = @()
foreach ($dir in (Get-ChildItem -Path $script:SkillsRoot -Directory)) {
$skillMd = Join-Path $dir.FullName "SKILL.md"
$skillPs = Join-Path $dir.FullName "$($dir.Name).ps1"
if (Test-Path $skillPs) {
$desc = ""
if (Test-Path $skillMd) {
$lines = Get-Content $skillMd -TotalCount 5
foreach ($line in $lines) {
if ($line -match '^>\s*(.+)') { $desc = $Matches[1]; break }
}
}
$skills += @{ name = $dir.Name; description = $desc; path = $skillPs }
}
}
Write-Result -Data $skills
}
# ─── Skill help ───
elseif ($Action -eq "help" -or $Action -eq "") {
$skillMd = Join-Path $script:SkillsRoot "$Skill\SKILL.md"
if (Test-Path $skillMd) {
$content = Get-Content $skillMd -Raw
Write-Result -Data @{ skill = $Skill; help = $content }
} else {
Write-Error-Result "Unknown skill: $Skill. Run: .\powerskills.ps1 list"
}
}
# ─── Dispatch to skill ───
else {
$skillScript = Join-Path $script:SkillsRoot "$Skill\$Skill.ps1"
if (-not (Test-Path $skillScript)) {
Write-Error-Result "Skill not found: $Skill"
}
$args_ = Parse-Args -Args_ $Rest
$config = Get-PSConfig
try {
$result = & $skillScript -Action $Action -Args_ $args_ -Config $config
Write-Result -Data $result
} catch {
Write-Error-Result $_.Exception.Message
}
}