shellmate-cli 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. shellmate/__init__.py +0 -0
  2. shellmate/adapters/__init__.py +67 -0
  3. shellmate/adapters/bash_adapter.sh +7 -0
  4. shellmate/adapters/ble_adapter.sh +350 -0
  5. shellmate/adapters/powershell_adapter.ps1 +417 -0
  6. shellmate/adapters/powershell_predictor.ps1 +97 -0
  7. shellmate/adapters/zsh_adapter.zsh +8 -0
  8. shellmate/agents/__init__.py +23 -0
  9. shellmate/agents/base.py +248 -0
  10. shellmate/agents/chain_patterns.yaml +98 -0
  11. shellmate/agents/command_chain.py +322 -0
  12. shellmate/agents/context_gatherer.py +175 -0
  13. shellmate/agents/environment.py +363 -0
  14. shellmate/agents/librarian.py +502 -0
  15. shellmate/agents/query.py +415 -0
  16. shellmate/agents/repomix_backend.py +171 -0
  17. shellmate/agents/watcher.py +266 -0
  18. shellmate/cache/__init__.py +0 -0
  19. shellmate/cache/semantic_cache.py +41 -0
  20. shellmate/cli/__init__.py +0 -0
  21. shellmate/cli/commands/__init__.py +27 -0
  22. shellmate/cli/commands/analyze.py +5 -0
  23. shellmate/cli/commands/config.py +319 -0
  24. shellmate/cli/commands/configure.py +118 -0
  25. shellmate/cli/commands/disable.py +11 -0
  26. shellmate/cli/commands/enable.py +49 -0
  27. shellmate/cli/commands/init.py +412 -0
  28. shellmate/cli/commands/install.py +242 -0
  29. shellmate/cli/commands/migrate.py +147 -0
  30. shellmate/cli/commands/status.py +31 -0
  31. shellmate/cli/commands/uninstall.py +78 -0
  32. shellmate/cli/main.py +114 -0
  33. shellmate/cli/parser.py +184 -0
  34. shellmate/cli/version.py +1 -0
  35. shellmate/completion/__init__.py +4 -0
  36. shellmate/completion/bash_adapter.py +145 -0
  37. shellmate/config/__init__.py +33 -0
  38. shellmate/config/credentials.py +120 -0
  39. shellmate/config/defaults.py +88 -0
  40. shellmate/config/manager.py +94 -0
  41. shellmate/config/paths.py +77 -0
  42. shellmate/config/secrets.py +66 -0
  43. shellmate/daemon/__init__.py +0 -0
  44. shellmate/daemon/lifecycle.py +308 -0
  45. shellmate/daemon/observability.py +82 -0
  46. shellmate/daemon/pipeline.py +119 -0
  47. shellmate/daemon/server.py +605 -0
  48. shellmate/daemon/session.py +170 -0
  49. shellmate/daemon/startup_ui.py +43 -0
  50. shellmate/environment/__init__.py +0 -0
  51. shellmate/environment/detector.py +130 -0
  52. shellmate/ipc/__init__.py +0 -0
  53. shellmate/ipc/client.py +210 -0
  54. shellmate/ipc/ps_client.py +190 -0
  55. shellmate/orchestration/__init__.py +3 -0
  56. shellmate/orchestration/analysis_graph.py +1274 -0
  57. shellmate/orchestration/state.py +35 -0
  58. shellmate/parser/__init__.py +0 -0
  59. shellmate/parser/command_parser.py +111 -0
  60. shellmate/plugins/__init__.py +0 -0
  61. shellmate/plugins/base.py +80 -0
  62. shellmate/plugins/loader.py +41 -0
  63. shellmate/providers/__init__.py +0 -0
  64. shellmate/providers/base.py +97 -0
  65. shellmate/providers/groq_command_guide.py +108 -0
  66. shellmate/providers/groq_provider.py +127 -0
  67. shellmate/providers/groq_supervisor.py +78 -0
  68. shellmate/providers/openrouter_provider.py +149 -0
  69. shellmate/providers/router.py +272 -0
  70. shellmate/providers/validate_keys.py +98 -0
  71. shellmate/providers/xai_provider.py +142 -0
  72. shellmate/rules/__init__.py +0 -0
  73. shellmate/rules/catastrophic.yaml +96 -0
  74. shellmate/rules/catastrophic_matcher.py +167 -0
  75. shellmate/rules/definitions/__init__.py +0 -0
  76. shellmate/rules/definitions/file_deletion.yaml +54 -0
  77. shellmate/rules/definitions/filesystem.yaml +43 -0
  78. shellmate/rules/definitions/network_execution.yaml +46 -0
  79. shellmate/rules/definitions/permissions.yaml +54 -0
  80. shellmate/rules/definitions/process_control.yaml +37 -0
  81. shellmate/rules/definitions/system_destruction.yaml +67 -0
  82. shellmate/rules/engine.py +200 -0
  83. shellmate/sanitizer/__init__.py +0 -0
  84. shellmate/sanitizer/typo_detector.py +114 -0
  85. shellmate/ui/__init__.py +10 -0
  86. shellmate/ui/analysis.py +164 -0
  87. shellmate/ui/annotations.py +232 -0
  88. shellmate/ui/banner.py +49 -0
  89. shellmate/ui/progress.py +126 -0
  90. shellmate/ui/runtime/__init__.py +15 -0
  91. shellmate/ui/runtime/console_factory.py +65 -0
  92. shellmate/ui/runtime/live_scene.py +116 -0
  93. shellmate/ui/runtime/motion_policy.py +69 -0
  94. shellmate/ui/runtime/tokens.py +47 -0
  95. shellmate/ui/scenes/__init__.py +24 -0
  96. shellmate/ui/scenes/enable.py +316 -0
  97. shellmate/ui/scenes/help.py +53 -0
  98. shellmate/ui/scenes/stages.py +128 -0
  99. shellmate/ui/scenes/status.py +181 -0
  100. shellmate/ui/status.py +3 -0
  101. shellmate_cli-3.0.0.dist-info/METADATA +352 -0
  102. shellmate_cli-3.0.0.dist-info/RECORD +106 -0
  103. shellmate_cli-3.0.0.dist-info/WHEEL +5 -0
  104. shellmate_cli-3.0.0.dist-info/entry_points.txt +3 -0
  105. shellmate_cli-3.0.0.dist-info/licenses/LICENSE +21 -0
  106. shellmate_cli-3.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,417 @@
1
+ # ShellMate PowerShell Adapter - PSReadLine two-phase annotations
2
+ # Install: add to $PROFILE -> . <path-to>/adapters/powershell_adapter.ps1
3
+ # Encoding: ASCII-safe strings for Windows PowerShell 5.1 compatibility
4
+
5
+ $script:ShellMateRoot = Split-Path -Parent $PSScriptRoot
6
+ if (-not $script:ShellMateRoot) {
7
+ $script:ShellMateRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
8
+ $script:ShellMateRoot = Split-Path -Parent $script:ShellMateRoot
9
+ }
10
+
11
+ $script:SMTimer = $null
12
+ $script:ShellMateLastDangerous = $null
13
+ $script:ShellMateNeedsConfirm = $null
14
+ $script:ShellMatePython = $null
15
+ $script:SMConsequenceShown = $null # command for which consequence was shown
16
+ $script:SMConsequenceRequireConfirm = $null # command needing second Enter
17
+ $script:SMConsequenceConfirmArmed = $null # set after first Enter blocked
18
+ $script:SMConsequenceJob = $null # background job fetching consequence
19
+
20
+ function Get-ShellMatePython {
21
+ if ($script:ShellMatePython) { return $script:ShellMatePython }
22
+ $candidates = @("python", "python3", "py")
23
+ foreach ($c in $candidates) {
24
+ $cmd = Get-Command $c -ErrorAction SilentlyContinue
25
+ if ($cmd) {
26
+ $script:ShellMatePython = $cmd.Source
27
+ return $script:ShellMatePython
28
+ }
29
+ }
30
+ return $null
31
+ }
32
+
33
+ function Show-ShellMateAnnotation {
34
+ param(
35
+ [string]$Text,
36
+ [string]$Severity = "MEDIUM"
37
+ )
38
+ if ([string]::IsNullOrWhiteSpace($Text)) { return }
39
+
40
+ $ESC = [char]27
41
+ $color = switch ($Severity) {
42
+ "CRITICAL" { "${ESC}[91m" }
43
+ "HIGH" { "${ESC}[91m" }
44
+ "blocking" { "${ESC}[91m" }
45
+ default { "${ESC}[93m" }
46
+ }
47
+ $reset = "${ESC}[0m"
48
+
49
+ # Fallback for legacy consoles without VT
50
+ if (-not $env:TERM -and $PSVersionTable.PSVersion.Major -le 5) {
51
+ Write-Host ""
52
+ Write-Host $Text -ForegroundColor Red
53
+ return
54
+ }
55
+
56
+ # Save cursor, move down 1, clear line, write, restore - target <2ms
57
+ [Console]::Write("${ESC}[s${ESC}[1B${ESC}[2K${color}${Text}${reset}${ESC}[u")
58
+ }
59
+
60
+ function Show-ShellMateConsequence {
61
+ param(
62
+ [string]$WhatHappens,
63
+ [string]$Scope,
64
+ [string]$Reversible,
65
+ [string]$SuggestedFix = "",
66
+ [string]$Severity = "MEDIUM"
67
+ )
68
+ $ESC = [char]27
69
+ $color = if ($Severity -in @("HIGH","CRITICAL","blocking")) { "${ESC}[91m" } `
70
+ elseif ($Severity -in @("SAFE","LOW")) { "${ESC}[92m" } `
71
+ else { "${ESC}[93m" }
72
+ $reset = "${ESC}[0m"
73
+ $dim = "${ESC}[90m"
74
+
75
+ $line1 = "${color} -> ${WhatHappens}${reset}"
76
+ $line2 = "${color} -> Reversible: ${Reversible} | ${Scope}${reset}"
77
+ $line3 = if ($SuggestedFix) { "${dim} -> Safe alt: ${SuggestedFix}${reset}" } else { "" }
78
+
79
+ # Save cursor, write 3 lines below prompt, restore
80
+ [Console]::Write("${ESC}[s")
81
+ [Console]::Write("${ESC}[1B${ESC}[2K${line1}")
82
+ [Console]::Write("${ESC}[2B${ESC}[2K${line2}")
83
+ if ($line3) { [Console]::Write("${ESC}[3B${ESC}[2K${line3}") }
84
+ [Console]::Write("${ESC}[u")
85
+ }
86
+
87
+ function Clear-ShellMateConsequence {
88
+ $ESC = [char]27
89
+ [Console]::Write("${ESC}[s${ESC}[1B${ESC}[2K${ESC}[2B${ESC}[2K${ESC}[3B${ESC}[2K${ESC}[u")
90
+ }
91
+
92
+ function Invoke-ShellMateConsequenceAsync {
93
+ param([string]$Command)
94
+
95
+ # Show placeholder immediately
96
+ $ESC = [char]27
97
+ [Console]::Write("${ESC}[s${ESC}[1B${ESC}[2K${ESC}[90m [?] Analyzing...${ESC}[0m${ESC}[u")
98
+
99
+ # Stop any previous consequence job
100
+ if ($script:SMConsequenceJob) {
101
+ Stop-Job $script:SMConsequenceJob -ErrorAction SilentlyContinue
102
+ Remove-Job $script:SMConsequenceJob -Force -ErrorAction SilentlyContinue
103
+ $script:SMConsequenceJob = $null
104
+ }
105
+
106
+ $py = Get-ShellMatePython
107
+ $client = Get-ShellMateClientPath
108
+ $capturedCmd = $Command
109
+
110
+ $script:SMConsequenceJob = Start-Job -ScriptBlock {
111
+ param($py, $client, $cmd)
112
+ try {
113
+ $raw = & $py $client $cmd 2>$null | Out-String
114
+ if ($raw) { return ($raw | ConvertFrom-Json) }
115
+ } catch {}
116
+ return $null
117
+ } -ArgumentList $py, $client, $capturedCmd
118
+ }
119
+
120
+ function Invoke-ShellMateInstantCheck {
121
+ param([string]$Command)
122
+ $py = Get-ShellMatePython
123
+ if (-not $py) { return $null }
124
+
125
+ $matcher = Join-Path $script:ShellMateRoot "rules\catastrophic_matcher.py"
126
+ if (-not (Test-Path $matcher)) {
127
+ $matcher = Join-Path $PSScriptRoot "..\rules\catastrophic_matcher.py"
128
+ }
129
+
130
+ try {
131
+ $json = & $py $matcher $Command 2>$null | Out-String
132
+ if ($json) {
133
+ return ($json | ConvertFrom-Json)
134
+ }
135
+ } catch {}
136
+ return $null
137
+ }
138
+
139
+ function Start-ShellMateDebounce {
140
+ param([string]$Command)
141
+
142
+ if ($script:SMTimer) {
143
+ $script:SMTimer.Stop()
144
+ $script:SMTimer.Dispose()
145
+ $script:SMTimer = $null
146
+ }
147
+
148
+ $py = Get-ShellMatePython
149
+ if (-not $py) { return }
150
+
151
+ $client = Join-Path $script:ShellMateRoot "ipc\ps_client.py"
152
+ if (-not (Test-Path $client)) {
153
+ $client = Join-Path $PSScriptRoot "..\ipc\ps_client.py"
154
+ }
155
+
156
+ $script:SMTimer = [System.Timers.Timer]::new(300)
157
+ $script:SMTimer.AutoReset = $false
158
+ $capturedCmd = $Command
159
+ $capturedPy = $py
160
+ $capturedClient = $client
161
+ $script:SMTimer.add_Elapsed({
162
+ try {
163
+ $raw = & $capturedPy $capturedClient $capturedCmd 2>$null | Out-String
164
+ if ($raw) {
165
+ $result = $raw | ConvertFrom-Json
166
+ if ($result.annotation) {
167
+ $sev = if ($result.severity) { $result.severity } else { "MEDIUM" }
168
+ Show-ShellMateAnnotation -Text $result.annotation -Severity $sev
169
+ }
170
+ }
171
+ } catch {}
172
+ }.GetNewClosure())
173
+ $script:SMTimer.Start()
174
+ }
175
+
176
+ function Stop-ShellMateDebounce {
177
+ if ($script:SMTimer) {
178
+ $script:SMTimer.Stop()
179
+ $script:SMTimer.Dispose()
180
+ $script:SMTimer = $null
181
+ }
182
+ }
183
+
184
+ # Enter key interception - Tier 1 instant block, Tier 2 accept + debounce
185
+ try {
186
+ Set-PSReadLineKeyHandler -Key Enter -ScriptBlock {
187
+ param($key, $arg)
188
+
189
+ $command = $null
190
+ $cursor = $null
191
+ [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$command, [ref]$cursor)
192
+
193
+ if ([string]::IsNullOrWhiteSpace($command)) {
194
+ [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
195
+ return
196
+ }
197
+
198
+ # Tier 1: Instant catastrophic check
199
+ $instant = Invoke-ShellMateInstantCheck -Command $command
200
+ if ($instant -and $instant.matched) {
201
+ $msg = if ($instant.message) { $instant.message } else { "BLOCKING - dangerous command" }
202
+ Show-ShellMateAnnotation -Text ("[!] BLOCKING - " + $msg) -Severity blocking
203
+
204
+ # Double-tap confirm: first Enter blocks, second allows
205
+ if ($script:ShellMateLastDangerous -ne $command) {
206
+ $script:ShellMateLastDangerous = $command
207
+ $script:ShellMateNeedsConfirm = $command
208
+ return # Suppress Enter
209
+ }
210
+ # Second Enter - allow through
211
+ $script:ShellMateLastDangerous = $null
212
+ $script:ShellMateNeedsConfirm = $null
213
+ }
214
+
215
+ Stop-ShellMateDebounce
216
+
217
+ # Consequence gate: HIGH/CRITICAL commands need second Enter after preview
218
+ if ($script:SMConsequenceRequireConfirm -and $script:SMConsequenceRequireConfirm -eq $command) {
219
+ if ($script:SMConsequenceConfirmArmed -ne $command) {
220
+ $script:SMConsequenceConfirmArmed = $command
221
+ Show-ShellMateAnnotation -Text "[Press Enter again to execute]" -Severity blocking
222
+ return # Suppress first Enter
223
+ }
224
+ $script:SMConsequenceRequireConfirm = $null
225
+ $script:SMConsequenceConfirmArmed = $null
226
+ # Second Enter — allow execution
227
+ } else {
228
+ $script:SMConsequenceConfirmArmed = $null
229
+ }
230
+ Clear-ShellMateConsequence
231
+ $script:SMConsequenceShown = $null
232
+
233
+ Start-ShellMateDebounce $command
234
+ [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
235
+ }
236
+ } catch {
237
+ Write-Verbose "ShellMate: PSReadLine Enter hook unavailable: $_"
238
+ }
239
+
240
+ # Also expose analysis helper for non-PSReadLine hosts
241
+ function Invoke-ShellMateAnalysis {
242
+ param([string]$Command)
243
+ if ([string]::IsNullOrWhiteSpace($Command)) { return }
244
+
245
+ $instant = Invoke-ShellMateInstantCheck -Command $Command
246
+ if ($instant -and $instant.matched) {
247
+ Show-ShellMateAnnotation -Text ("[!] BLOCKING - " + $instant.message) -Severity blocking
248
+ return
249
+ }
250
+
251
+ $py = Get-ShellMatePython
252
+ $client = Join-Path $script:ShellMateRoot "ipc\ps_client.py"
253
+ if ($py -and (Test-Path $client)) {
254
+ try {
255
+ $raw = & $py $client $Command 2>$null | Out-String
256
+ $result = $raw | ConvertFrom-Json
257
+ if ($result.annotation) {
258
+ Show-ShellMateAnnotation -Text $result.annotation -Severity $result.severity
259
+ }
260
+ } catch {}
261
+ }
262
+ }
263
+
264
+ function Get-ShellMateClientPath {
265
+ $client = Join-Path $script:ShellMateRoot "ipc\ps_client.py"
266
+ if (-not (Test-Path $client)) {
267
+ $client = Join-Path $PSScriptRoot "..\ipc\ps_client.py"
268
+ }
269
+ return $client
270
+ }
271
+
272
+ function Invoke-ShellMateComplete {
273
+ param([string]$Prefix)
274
+ $py = Get-ShellMatePython
275
+ $client = Get-ShellMateClientPath
276
+ if (-not $py -or -not (Test-Path $client)) { return @() }
277
+ try {
278
+ $raw = & $py $client "--complete" $Prefix 2>$null | Out-String
279
+ if (-not $raw) { return @() }
280
+ $result = $raw | ConvertFrom-Json
281
+ if ($result.completions) { return @($result.completions) }
282
+ } catch {}
283
+ return @()
284
+ }
285
+
286
+ # --- Step 3.5: Ghost text (PS 7.2+ predictor) or Tab fallback (PS 5.1) ---
287
+ $script:ShellMatePredictorRegistered = $false
288
+ $script:SMLastSuggestion = $null
289
+ $script:SMLastPrefix = $null
290
+
291
+ $psrl = Get-Module PSReadLine -ErrorAction SilentlyContinue
292
+ $canPredict = (
293
+ $PSVersionTable.PSVersion -ge [Version]"7.2" -and
294
+ $null -ne $psrl -and
295
+ $psrl.Version -ge [Version]"2.1"
296
+ )
297
+
298
+ if ($canPredict) {
299
+ $predictorFile = Join-Path $PSScriptRoot "powershell_predictor.ps1"
300
+ if (Test-Path $predictorFile) {
301
+ # Guard against predictor load/compile failures (e.g. prediction-API
302
+ # drift across PS builds) so the adapter still loads and the Tab
303
+ # ghost-text fallback below can engage instead of spewing errors.
304
+ try { . $predictorFile } catch { Write-Verbose "ShellMate: predictor load failed: $_" }
305
+ }
306
+ }
307
+
308
+ # Path B: Tab override ghost-text when predictor is unavailable
309
+ if (-not $script:ShellMatePredictorRegistered) {
310
+ try {
311
+ Set-PSReadLineKeyHandler -Key Tab -ScriptBlock {
312
+ param($key, $arg)
313
+ $line = $null; $cursor = $null
314
+ [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
315
+ if ($null -eq $line) { $line = "" }
316
+ $prefix = if ($cursor -gt 0 -and $cursor -le $line.Length) { $line.Substring(0, $cursor) } else { $line }
317
+
318
+ # Second Tab: suggestion cached → accept + show consequence
319
+ if ($script:SMLastPrefix -eq $prefix -and $script:SMLastSuggestion) {
320
+ $accepted = $script:SMLastSuggestion
321
+ [Microsoft.PowerShell.PSConsoleReadLine]::Replace(0, $line.Length, $accepted)
322
+ $script:SMLastSuggestion = $null
323
+ $script:SMLastPrefix = $null
324
+ $script:SMConsequenceShown = $accepted
325
+
326
+ # Fetch consequence in background
327
+ Invoke-ShellMateConsequenceAsync -Command $accepted
328
+
329
+ # Poll job for up to 1.5s then render
330
+ $deadline = [DateTime]::Now.AddSeconds(1.5)
331
+ while ([DateTime]::Now -lt $deadline) {
332
+ Start-Sleep -Milliseconds 80
333
+ if ($script:SMConsequenceJob -and $script:SMConsequenceJob.State -ne 'Running') {
334
+ $result = Receive-Job $script:SMConsequenceJob -ErrorAction SilentlyContinue
335
+ Remove-Job $script:SMConsequenceJob -Force -ErrorAction SilentlyContinue
336
+ $script:SMConsequenceJob = $null
337
+ if ($result) {
338
+ $cp = $result.consequence_preview
339
+ if ($cp) {
340
+ $rev = if ($cp.reversible) { "Yes" } else { "No" }
341
+ $sev = if ($result.severity) { $result.severity } else { "MEDIUM" }
342
+ Show-ShellMateConsequence `
343
+ -WhatHappens $cp.what_happens `
344
+ -Scope $cp.scope `
345
+ -Reversible $rev `
346
+ -SuggestedFix $cp.suggested_fix `
347
+ -Severity $sev
348
+ if ($sev -in @("HIGH","CRITICAL","blocking")) {
349
+ $script:SMConsequenceRequireConfirm = $accepted
350
+ }
351
+ }
352
+ }
353
+ break
354
+ }
355
+ }
356
+ return
357
+ }
358
+
359
+ # First Tab: get completions, show ghost text
360
+ $script:SMLastSuggestion = $null
361
+ $script:SMLastPrefix = $null
362
+ try {
363
+ $completions = @(Invoke-ShellMateComplete -Prefix $prefix)
364
+ $suggestion = $completions | Select-Object -First 1
365
+ if ($suggestion -and $suggestion -ne $prefix) {
366
+ $script:SMLastSuggestion = [string]$suggestion
367
+ $script:SMLastPrefix = $prefix
368
+ $ESC = [char]27
369
+ $suffix = ([string]$suggestion).Substring([Math]::Min($prefix.Length, ([string]$suggestion).Length))
370
+ if ($suffix) {
371
+ [Console]::Write("${ESC}[90m${suffix}${ESC}[0m")
372
+ [Console]::Write("${ESC}[$($suffix.Length)D")
373
+ }
374
+ return
375
+ }
376
+ } catch {}
377
+ [Microsoft.PowerShell.PSConsoleReadLine]::MenuComplete()
378
+ }
379
+ } catch {
380
+ Write-Verbose "ShellMate: Tab ghost-text handler unavailable: $_"
381
+ }
382
+ }
383
+
384
+ # --- Step 3.6: Native argument completer (optional augment) ---
385
+ # Requires -CommandName; bare -Native prompts interactively in PS and hangs sourcing.
386
+ # Tab handler + predictor already cover ShellMate completions — skip global native
387
+ # registration unless a curated command list is provided via env.
388
+ $smNativeCmds = $env:SM_NATIVE_COMPLETERS
389
+ if ($smNativeCmds) {
390
+ $names = @($smNativeCmds -split '[,; ]+' | Where-Object { $_ })
391
+ if ($names.Count -gt 0) {
392
+ try {
393
+ Register-ArgumentCompleter -Native -CommandName $names -ScriptBlock {
394
+ param(
395
+ [string]$wordToComplete,
396
+ [System.Management.Automation.Language.CommandAst]$commandAst,
397
+ [int]$cursorPosition
398
+ )
399
+
400
+ $fullLine = $commandAst.Extent.Text
401
+ try {
402
+ $completions = @(Invoke-ShellMateComplete -Prefix $fullLine)
403
+ foreach ($c in $completions) {
404
+ [System.Management.Automation.CompletionResult]::new(
405
+ [string]$c,
406
+ [string]$c,
407
+ "ParameterValue",
408
+ ("ShellMate: " + [string]$c)
409
+ )
410
+ }
411
+ } catch {}
412
+ }
413
+ } catch {
414
+ Write-Verbose "ShellMate: ArgumentCompleter registration unavailable: $_"
415
+ }
416
+ }
417
+ }
@@ -0,0 +1,97 @@
1
+ # ShellMate PowerShell Prediction Source (PS 7.2+ / PSReadLine 2.1+)
2
+ # Sourced only when version checks pass — keeps powershell_adapter.ps1 parseable on 5.1
3
+
4
+ class ShellMatePredictor : System.Management.Automation.Subsystem.Prediction.ICommandPredictor {
5
+ [System.Guid] $Id = [System.Guid]::new("d8f1b5a2-4c3e-4f7d-9a8b-1e2f3c4d5e6f")
6
+ [string] $Name = "ShellMate"
7
+ [string] $Description = "Context-aware command suggestions"
8
+ [string] $PythonPath
9
+ [string] $ClientPath
10
+
11
+ ShellMatePredictor([string]$PythonPath, [string]$ClientPath) {
12
+ $this.PythonPath = $PythonPath
13
+ $this.ClientPath = $ClientPath
14
+ }
15
+
16
+ [bool] CanAcceptFeedback(
17
+ [System.Management.Automation.Subsystem.Prediction.PredictionClient] $client,
18
+ [System.Management.Automation.Subsystem.Prediction.PredictorFeedbackKind] $feedback
19
+ ) { return $false }
20
+
21
+ [void] OnSuggestionDisplayed(
22
+ [System.Management.Automation.Subsystem.Prediction.PredictionClient] $client,
23
+ [uint] $session,
24
+ [int] $countOrIndex
25
+ ) {}
26
+
27
+ [void] OnSuggestionAccepted(
28
+ [System.Management.Automation.Subsystem.Prediction.PredictionClient] $client,
29
+ [uint] $session,
30
+ [string] $acceptedSuggestion
31
+ ) {}
32
+
33
+ [void] OnCommandLineAccepted(
34
+ [System.Management.Automation.Subsystem.Prediction.PredictionClient] $client,
35
+ [System.Collections.Generic.IReadOnlyList[string]] $history
36
+ ) {}
37
+
38
+ [void] OnCommandLineExecuted(
39
+ [System.Management.Automation.Subsystem.Prediction.PredictionClient] $client,
40
+ [string] $commandLine,
41
+ [bool] $success
42
+ ) {}
43
+
44
+ [System.Management.Automation.Subsystem.Prediction.SuggestionPackage] GetSuggestion(
45
+ [System.Management.Automation.Subsystem.Prediction.PredictionClient] $client,
46
+ [System.Management.Automation.Subsystem.Prediction.PredictionContext] $context,
47
+ [System.Threading.CancellationToken] $cancellationToken
48
+ ) {
49
+ $input = $context.InputAst.Extent.Text
50
+ if ([string]::IsNullOrWhiteSpace($input) -or $input.Length -lt 3) {
51
+ return [System.Management.Automation.Subsystem.Prediction.SuggestionPackage]::new(@())
52
+ }
53
+
54
+ try {
55
+ if (-not $this.PythonPath -or -not (Test-Path $this.ClientPath)) {
56
+ return [System.Management.Automation.Subsystem.Prediction.SuggestionPackage]::new(@())
57
+ }
58
+ $raw = & $this.PythonPath $this.ClientPath "--complete" $input 2>$null | Out-String
59
+ if (-not $raw) {
60
+ return [System.Management.Automation.Subsystem.Prediction.SuggestionPackage]::new(@())
61
+ }
62
+ $result = $raw | ConvertFrom-Json
63
+ if (-not $result.completions) {
64
+ return [System.Management.Automation.Subsystem.Prediction.SuggestionPackage]::new(@())
65
+ }
66
+ $suggestions = @(
67
+ $result.completions | ForEach-Object {
68
+ [System.Management.Automation.Subsystem.Prediction.PredictiveSuggestion]::new([string]$_)
69
+ }
70
+ )
71
+ return [System.Management.Automation.Subsystem.Prediction.SuggestionPackage]::new($suggestions)
72
+ } catch {
73
+ return [System.Management.Automation.Subsystem.Prediction.SuggestionPackage]::new(@())
74
+ }
75
+ }
76
+ }
77
+
78
+ $py = Get-ShellMatePython
79
+ $client = Join-Path $script:ShellMateRoot "ipc\ps_client.py"
80
+ if (-not (Test-Path $client)) {
81
+ $client = Join-Path $PSScriptRoot "..\ipc\ps_client.py"
82
+ }
83
+
84
+ if ($py -and (Test-Path $client)) {
85
+ try {
86
+ $predictor = [ShellMatePredictor]::new($py, $client)
87
+ [System.Management.Automation.Subsystem.SubsystemManager]::RegisterSubsystem(
88
+ [System.Management.Automation.Subsystem.SubsystemKind]::CommandPredictor,
89
+ $predictor
90
+ )
91
+ Set-PSReadLineOption -PredictionSource Plugin -PredictionViewStyle InlineView -ErrorAction SilentlyContinue
92
+ $script:ShellMatePredictorRegistered = $true
93
+ } catch {
94
+ Write-Verbose "ShellMate: predictor registration failed: $_"
95
+ $script:ShellMatePredictorRegistered = $false
96
+ }
97
+ }
@@ -0,0 +1,8 @@
1
+ #!/bin/zsh
2
+ # ShellMate Zsh Adapter - Deprecated
3
+ # Interception mode has been removed - use bash with ble.sh for autocomplete mode
4
+ # This file is kept for backward compatibility only
5
+
6
+ echo "⚠️ ShellMate: zsh interception mode is deprecated."
7
+ echo " For autocomplete mode, use bash with ble.sh"
8
+ echo " Run: sm migrate-to-autocomplete"
@@ -0,0 +1,23 @@
1
+ from shellmate.agents.base import (
2
+ Agent,
3
+ AgentRequest,
4
+ AgentResponse,
5
+ AgentStatus,
6
+ AgentManager,
7
+ get_agent_manager,
8
+ )
9
+ from shellmate.agents.watcher import WatcherAgent, get_watcher_agent
10
+ from shellmate.agents.librarian import LibrarianAgent, get_librarian_agent
11
+
12
+ __all__ = [
13
+ "Agent",
14
+ "AgentRequest",
15
+ "AgentResponse",
16
+ "AgentStatus",
17
+ "AgentManager",
18
+ "get_agent_manager",
19
+ "WatcherAgent",
20
+ "get_watcher_agent",
21
+ "LibrarianAgent",
22
+ "get_librarian_agent",
23
+ ]