oh-aicoding-tool 0.1.2 → 0.1.5
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.
- package/README.md +79 -80
- package/bin/cli.js +257 -384
- package/package.json +27 -55
- package/CODEX_LANGFUSE_PLAN.md +0 -62
- package/bin/langfuse-cli.js +0 -718
- package/codex_langfuse_notify.py +0 -591
- package/langfuse_hook.py +0 -603
- package/opencode-ohai-report/.claude/commands/report-ai-issue.md +0 -60
- package/opencode-ohai-report/.opencode/commands/report-ai-issue.md +0 -30
- package/opencode-ohai-report/.opencode/plugins/oh-ai-report.ts +0 -569
- package/opencode-ohai-report/README.md +0 -45
- package/opencode-ohai-report/bin/cli.js +0 -421
- package/opencode-ohai-report/docs/opencode-ai-issue-collection-architecture.md +0 -313
- package/opencode-ohai-report/docs/opencode-ai-issue-collection-best-practices.md +0 -476
- package/opencode-ohai-report/docs/opencode-ai-issue-collection-phase1-summary.md +0 -405
- package/opencode-ohai-report/examples/issue_output.json +0 -4
- package/opencode-ohai-report/package.json +0 -40
- package/opencode-ohai-report/scripts/claude_report_hook.py +0 -257
- package/opencode-ohai-report/scripts/create_issue.py +0 -34
- package/opencode-ohai-report/scripts/install-claude-plugin.ps1 +0 -254
- package/opencode-ohai-report/scripts/install-opencode-plugin.ps1 +0 -264
- package/opencode-ohai-report/scripts/install-opencode-plugin.sh +0 -218
- package/opencode-ohai-report/scripts/merge-claude-settings.py +0 -99
- package/opencode-ohai-report/tools/ohai-report/README.md +0 -151
- package/opencode-ohai-report/tools/ohai-report/examples/issue-input.json +0 -26
- package/opencode-ohai-report/tools/ohai-report/ohai_report/__init__.py +0 -5
- package/opencode-ohai-report/tools/ohai-report/ohai_report/__main__.py +0 -9
- package/opencode-ohai-report/tools/ohai-report/ohai_report/cli.py +0 -319
- package/opencode-ohai-report/tools/ohai-report/ohai_report/git_context.py +0 -32
- package/opencode-ohai-report/tools/ohai-report/ohai_report/gitcode_defaults.py +0 -14
- package/opencode-ohai-report/tools/ohai-report/ohai_report/issue_markdown.py +0 -313
- package/opencode-ohai-report/tools/ohai-report/ohai_report/metadata.py +0 -360
- package/opencode-ohai-report/tools/ohai-report/ohai_report/observability/__init__.py +0 -1
- package/opencode-ohai-report/tools/ohai-report/ohai_report/observability/langfuse.py +0 -38
- package/opencode-ohai-report/tools/ohai-report/ohai_report/payload.py +0 -64
- package/opencode-ohai-report/tools/ohai-report/ohai_report/schema.py +0 -80
- package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/__init__.py +0 -1
- package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/base.py +0 -15
- package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/gitcode.py +0 -405
- package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/local.py +0 -21
- package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/webhook.py +0 -354
- package/opencode-ohai-report/tools/ohai-report/ohai_report/webhook_defaults.py +0 -9
- package/opencode-ohai-report/tools/ohai-report/ohai_report/workspace.py +0 -61
- package/opencode-ohai-report/tools/ohai-report/ohai_report.py +0 -10
- package/opencode-ohai-report/tools/ohai-report/schemas/report_issue.schema.json +0 -166
- package/scripts/codex-langfuse-check.mjs +0 -101
- package/scripts/codex-langfuse-setup.mjs +0 -181
- package/scripts/langfuse-check.mjs +0 -90
- package/scripts/langfuse-setup.mjs +0 -278
- package/scripts/opencode-langfuse-check.mjs +0 -94
- package/scripts/opencode-langfuse-run.mjs +0 -96
- package/scripts/opencode-langfuse-setup.mjs +0 -478
- package/scripts/resolve-opencode-cli.mjs +0 -58
- package/setup-langfuse.bat +0 -163
- package/setup-langfuse.sh +0 -130
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"""将示例或自定义 JSON(title + body/content)推送到 Webhook。
|
|
2
|
-
|
|
3
|
-
默认读取仓库根下 `examples/issue_output.json`。成功时标准输出**最后一行**为一行 JSON
|
|
4
|
-
(含 `issue_id`、`webhook_url` 等),与 `ohai_report.py create --sink webhook --json` 对齐。
|
|
5
|
-
|
|
6
|
-
POST 请求体中 `labels` 为**逗号分隔的 JSON 字符串**(如 ``"bug,critical"``),并与完整 ``create`` 一致自动带上
|
|
7
|
-
``tool:`` / ``model:`` / ``level:`` / ``category:`` 维度前缀(由 JSON 中非 title/body/content 字段推导)。
|
|
8
|
-
|
|
9
|
-
完整采集请使用:
|
|
10
|
-
|
|
11
|
-
python tools/ohai-report/ohai_report.py create --sink webhook --metadata auto ...
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
from __future__ import annotations
|
|
15
|
-
|
|
16
|
-
import sys
|
|
17
|
-
from pathlib import Path
|
|
18
|
-
|
|
19
|
-
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
20
|
-
sys.path.insert(0, str(REPO_ROOT / "tools" / "ohai-report"))
|
|
21
|
-
|
|
22
|
-
from ohai_report.sinks.webhook import push_legacy_issue_json_file
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def main() -> int:
|
|
26
|
-
if len(sys.argv) > 1:
|
|
27
|
-
path = Path(sys.argv[1]).resolve()
|
|
28
|
-
else:
|
|
29
|
-
path = REPO_ROOT / "examples" / "issue_output.json"
|
|
30
|
-
return push_legacy_issue_json_file(path)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if __name__ == "__main__":
|
|
34
|
-
sys.exit(main())
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
#Requires -Version 5.1
|
|
2
|
-
<#
|
|
3
|
-
.SYNOPSIS
|
|
4
|
-
Install oh-ai-report plugin and /report-ai-issue into Claude Code global config.
|
|
5
|
-
|
|
6
|
-
.DESCRIPTION
|
|
7
|
-
Target: %USERPROFILE%\.claude\ (per Claude Code docs)
|
|
8
|
-
- commands\report-ai-issue.md
|
|
9
|
-
- hooks\ohai-report-hook.py (unless -SkipHook)
|
|
10
|
-
- updates settings.json to register the hook (unless -SkipHook)
|
|
11
|
-
|
|
12
|
-
Email: displays the current saved value on each run and asks whether to update
|
|
13
|
-
it; the default answer keeps the existing value. Checks the Claude email file
|
|
14
|
-
first, then the OpenCode email file as a fallback.
|
|
15
|
-
|
|
16
|
-
Env: sets user-level OHAI_REPORT_CLI (same as OpenCode install; use -SkipEnv to leave unchanged).
|
|
17
|
-
|
|
18
|
-
.PARAMETER DryRun
|
|
19
|
-
Print actions only; do not copy files or change env.
|
|
20
|
-
|
|
21
|
-
.PARAMETER SkipEmail
|
|
22
|
-
Do not prompt for email (assumes opencode plugin already installed it).
|
|
23
|
-
|
|
24
|
-
.PARAMETER SkipEnv
|
|
25
|
-
Do not set OHAI_REPORT_CLI.
|
|
26
|
-
|
|
27
|
-
.PARAMETER SkipHook
|
|
28
|
-
Skip hook script and settings.json merge.
|
|
29
|
-
#>
|
|
30
|
-
param(
|
|
31
|
-
[switch]$DryRun,
|
|
32
|
-
[switch]$SkipEmail,
|
|
33
|
-
[switch]$SkipEnv,
|
|
34
|
-
[switch]$SkipHook
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
$ErrorActionPreference = "Stop"
|
|
38
|
-
|
|
39
|
-
function Test-OhaiCompanyEmail {
|
|
40
|
-
param([Parameter(Mandatory)][AllowEmptyString()][string]$Value)
|
|
41
|
-
$t = $Value.Trim()
|
|
42
|
-
if ($t.Length -lt 5) { return $false }
|
|
43
|
-
try {
|
|
44
|
-
$null = [mailaddress]$t
|
|
45
|
-
return ($t -eq ([mailaddress]$t).Address)
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
return $false
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function Get-OhaiSavedEmail {
|
|
53
|
-
param([Parameter(Mandatory)][string[]]$Paths)
|
|
54
|
-
foreach ($path in $Paths) {
|
|
55
|
-
if (-not (Test-Path -LiteralPath $path)) {
|
|
56
|
-
continue
|
|
57
|
-
}
|
|
58
|
-
try {
|
|
59
|
-
$raw = Get-Content -LiteralPath $path -Raw
|
|
60
|
-
$j = $raw | ConvertFrom-Json -ErrorAction SilentlyContinue
|
|
61
|
-
$e = if ($j.user_email) { $j.user_email } elseif ($j.userEmail) { $j.userEmail } else { "" }
|
|
62
|
-
if (Test-OhaiCompanyEmail $e) {
|
|
63
|
-
return [pscustomobject]@{ Email = $e.Trim(); Path = $path }
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch { }
|
|
67
|
-
}
|
|
68
|
-
return $null
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function Read-OhaiEmailUpdate {
|
|
72
|
-
param(
|
|
73
|
-
[Parameter(Mandatory)][AllowEmptyString()][string]$CurrentEmail,
|
|
74
|
-
[Parameter(Mandatory)][string]$EmailPath
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
$display = if ($CurrentEmail) { $CurrentEmail } else { "(not set)" }
|
|
78
|
-
Write-Host ('Current company email: ' + $display) -ForegroundColor Cyan
|
|
79
|
-
|
|
80
|
-
if ([Console]::IsInputRedirected) {
|
|
81
|
-
$fromEnv = [Environment]::GetEnvironmentVariable('OHAI_INSTALL_USER_EMAIL', 'Process')
|
|
82
|
-
if (Test-OhaiCompanyEmail $fromEnv) {
|
|
83
|
-
Write-Host 'Non-interactive install: updating email from OHAI_INSTALL_USER_EMAIL.' -ForegroundColor Yellow
|
|
84
|
-
return $fromEnv.Trim()
|
|
85
|
-
}
|
|
86
|
-
Write-Host 'Non-interactive install: keeping current email; set OHAI_INSTALL_USER_EMAIL to update.' -ForegroundColor Yellow
|
|
87
|
-
return ""
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
$answer = (Read-Host 'Update company email? [y/N]').Trim().ToLowerInvariant()
|
|
91
|
-
if ($answer -ne 'y' -and $answer -ne 'yes') {
|
|
92
|
-
Write-Host 'Keeping current company email.' -ForegroundColor Yellow
|
|
93
|
-
return ""
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
while ($true) {
|
|
97
|
-
$line = Read-Host 'Company email'
|
|
98
|
-
if (Test-OhaiCompanyEmail $line) {
|
|
99
|
-
return $line.Trim()
|
|
100
|
-
}
|
|
101
|
-
Write-Host 'Invalid Company email. Examples: xxxxx@huawei.com or xxxxx@h-partners.com' -ForegroundColor Red
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function Resolve-OhaiPythonCommand {
|
|
106
|
-
foreach ($candidate in @("python", "python3", "py")) {
|
|
107
|
-
if (-not (Get-Command $candidate -ErrorAction SilentlyContinue)) {
|
|
108
|
-
continue
|
|
109
|
-
}
|
|
110
|
-
& $candidate --version *> $null
|
|
111
|
-
if ($LASTEXITCODE -eq 0) {
|
|
112
|
-
return $candidate
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
throw 'Python was not found. Install Python or add python.exe to PATH.'
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
|
119
|
-
$CommandSrc = Join-Path $RepoRoot ".claude\commands\report-ai-issue.md"
|
|
120
|
-
$CliPy = Join-Path $RepoRoot "tools\ohai-report\ohai_report.py"
|
|
121
|
-
$HookSrc = Join-Path $RepoRoot "scripts\claude_report_hook.py"
|
|
122
|
-
$MergeSettingsPy = Join-Path $RepoRoot "scripts\merge-claude-settings.py"
|
|
123
|
-
$cliResolved = if (Test-Path -LiteralPath $CliPy) { (Resolve-Path $CliPy).Path } else { "" }
|
|
124
|
-
$cliHint = if ($cliResolved) { $cliResolved } else { '(ohai_report.py not found in this repo)' }
|
|
125
|
-
|
|
126
|
-
if (-not (Test-Path -LiteralPath $CommandSrc)) {
|
|
127
|
-
throw ('Command source not found: ' + $CommandSrc + ' (run from repo checkout)')
|
|
128
|
-
}
|
|
129
|
-
if (-not (Test-Path -LiteralPath $MergeSettingsPy)) {
|
|
130
|
-
throw ('Settings merge helper not found: ' + $MergeSettingsPy + ' (run from repo checkout)')
|
|
131
|
-
}
|
|
132
|
-
if (-not (Test-Path -LiteralPath $HookSrc)) {
|
|
133
|
-
throw ('Hook source not found: ' + $HookSrc + ' (run from repo checkout)')
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
$ClaudeRoot = Join-Path $env:USERPROFILE ".claude"
|
|
137
|
-
$CommandsDir = Join-Path $ClaudeRoot "commands"
|
|
138
|
-
$HooksDir = Join-Path $ClaudeRoot "hooks"
|
|
139
|
-
$DestCommand = Join-Path $CommandsDir "report-ai-issue.md"
|
|
140
|
-
$DestHook = Join-Path $HooksDir "ohai-report-hook.py"
|
|
141
|
-
$SettingsPath = Join-Path $ClaudeRoot "settings.json"
|
|
142
|
-
|
|
143
|
-
# Email: Claude-specific location
|
|
144
|
-
$emailJsonDir = Join-Path $env:USERPROFILE ".claude\ohai-report"
|
|
145
|
-
$emailJsonPath = Join-Path $emailJsonDir "email.json"
|
|
146
|
-
$opencodeEmailJsonPath = Join-Path $env:USERPROFILE ".config\opencode\ohai-report\email.json"
|
|
147
|
-
|
|
148
|
-
Write-Host ""
|
|
149
|
-
Write-Host "=== Claude Code oh-ai-report install ===" -ForegroundColor Cyan
|
|
150
|
-
Write-Host ('Repo root: ' + $RepoRoot)
|
|
151
|
-
Write-Host ('Claude global config: ' + $ClaudeRoot)
|
|
152
|
-
Write-Host ""
|
|
153
|
-
|
|
154
|
-
# ---------- Email (reuse or prompt) ----------
|
|
155
|
-
$userEmailToSave = ""
|
|
156
|
-
if (-not $SkipEmail) {
|
|
157
|
-
$savedEmail = Get-OhaiSavedEmail -Paths @($emailJsonPath, $opencodeEmailJsonPath)
|
|
158
|
-
if ($savedEmail) {
|
|
159
|
-
Write-Host ('Email file: ' + $savedEmail.Path) -ForegroundColor Cyan
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
Write-Host ('Email file: ' + $emailJsonPath) -ForegroundColor Cyan
|
|
163
|
-
}
|
|
164
|
-
$currentEmail = if ($savedEmail) { $savedEmail.Email } else { "" }
|
|
165
|
-
$userEmailToSave = Read-OhaiEmailUpdate -CurrentEmail $currentEmail -EmailPath $emailJsonPath
|
|
166
|
-
|
|
167
|
-
if ($userEmailToSave) {
|
|
168
|
-
# Save to Claude-specific location
|
|
169
|
-
if ($DryRun) {
|
|
170
|
-
Write-Host ('[DryRun] write ' + $emailJsonPath) -ForegroundColor Yellow
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
New-Item -ItemType Directory -Force -Path $emailJsonDir | Out-Null
|
|
174
|
-
$obj = [ordered]@{ user_email = $userEmailToSave }
|
|
175
|
-
$json = ($obj | ConvertTo-Json -Compress)
|
|
176
|
-
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
|
|
177
|
-
[System.IO.File]::WriteAllText($emailJsonPath, $json, $utf8NoBom)
|
|
178
|
-
Write-Host ('Saved company email to: ' + $emailJsonPath) -ForegroundColor Green
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
Write-Host 'Skipped email prompt (-SkipEmail).' -ForegroundColor Yellow
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
# ---------- Install command ----------
|
|
187
|
-
if ($DryRun) {
|
|
188
|
-
Write-Host ('[DryRun] mkdir ' + $CommandsDir) -ForegroundColor Yellow
|
|
189
|
-
Write-Host ('[DryRun] copy ' + $CommandSrc + ' -> ' + $DestCommand)
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
New-Item -ItemType Directory -Force -Path $CommandsDir | Out-Null
|
|
193
|
-
Copy-Item -LiteralPath $CommandSrc -Destination $DestCommand -Force
|
|
194
|
-
Write-Host ('Installed command: ' + $DestCommand) -ForegroundColor Green
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
# ---------- Env ----------
|
|
198
|
-
if ($DryRun) {
|
|
199
|
-
if ($SkipEnv) {
|
|
200
|
-
Write-Host '[DryRun] skip env (-SkipEnv)' -ForegroundColor Yellow
|
|
201
|
-
}
|
|
202
|
-
elseif ($cliResolved) {
|
|
203
|
-
Write-Host ('[DryRun] set User env OHAI_REPORT_CLI=' + $cliResolved) -ForegroundColor Yellow
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
Write-Host '[DryRun] skip env (ohai_report.py missing)' -ForegroundColor Yellow
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
if (-not $SkipEnv -and $cliResolved) {
|
|
211
|
-
[Environment]::SetEnvironmentVariable('OHAI_REPORT_CLI', $cliResolved, 'User')
|
|
212
|
-
Write-Host ('Set user env OHAI_REPORT_CLI=' + $cliResolved) -ForegroundColor Green
|
|
213
|
-
}
|
|
214
|
-
elseif (-not $SkipEnv -and -not $cliResolved) {
|
|
215
|
-
Write-Host 'Skipped env: ohai_report.py not found under this repo.' -ForegroundColor Yellow
|
|
216
|
-
}
|
|
217
|
-
elseif ($SkipEnv) {
|
|
218
|
-
Write-Host 'Skipped env (-SkipEnv).' -ForegroundColor Yellow
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
# ---------- Hook ----------
|
|
223
|
-
if (-not $SkipHook) {
|
|
224
|
-
if ($DryRun) {
|
|
225
|
-
Write-Host ('[DryRun] mkdir ' + $HooksDir) -ForegroundColor Yellow
|
|
226
|
-
Write-Host ('[DryRun] copy ' + $HookSrc + ' -> ' + $DestHook)
|
|
227
|
-
Write-Host ('[DryRun] merge settings.json: ' + $SettingsPath) -ForegroundColor Yellow
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
New-Item -ItemType Directory -Force -Path $HooksDir | Out-Null
|
|
231
|
-
|
|
232
|
-
Copy-Item -LiteralPath $HookSrc -Destination $DestHook -Force
|
|
233
|
-
Write-Host ('Installed hook: ' + $DestHook) -ForegroundColor Green
|
|
234
|
-
|
|
235
|
-
# Merge settings.json with Python so formatting is stable and predictable.
|
|
236
|
-
$python = Resolve-OhaiPythonCommand
|
|
237
|
-
& $python $MergeSettingsPy --settings $SettingsPath --hook $DestHook --python-command $python
|
|
238
|
-
if ($LASTEXITCODE -ne 0) {
|
|
239
|
-
throw ('Failed to merge settings.json using ' + $MergeSettingsPy)
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
Write-Host 'Skipped hook installation (-SkipHook).' -ForegroundColor Yellow
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
# ---------- Summary ----------
|
|
248
|
-
Write-Host ""
|
|
249
|
-
Write-Host 'Next: fully quit and restart Claude Code so commands and hooks load.' -ForegroundColor Cyan
|
|
250
|
-
Write-Host ""
|
|
251
|
-
if ($cliResolved) {
|
|
252
|
-
Write-Host ('OHAI_REPORT_CLI (after restart): ' + $cliHint) -ForegroundColor Yellow
|
|
253
|
-
}
|
|
254
|
-
Write-Host ""
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
#Requires -Version 5.1
|
|
2
|
-
<#
|
|
3
|
-
.SYNOPSIS
|
|
4
|
-
Install oh-ai-report plugin and /report-ai-issue into OpenCode global config.
|
|
5
|
-
|
|
6
|
-
.DESCRIPTION
|
|
7
|
-
Target: %USERPROFILE%\.config\opencode\ (per OpenCode docs)
|
|
8
|
-
- plugins\oh-ai-report.ts
|
|
9
|
-
- commands\report-ai-issue.md (unless -PluginOnly)
|
|
10
|
-
- ohai-report\email.json (company email, unless -SkipEmail)
|
|
11
|
-
|
|
12
|
-
After install, fully restart OpenCode.
|
|
13
|
-
|
|
14
|
-
By default, sets user-level env OHAI_REPORT_CLI to this repo's ohai_report.py (Windows User
|
|
15
|
-
registry). Use -SkipEnv to leave env unchanged.
|
|
16
|
-
|
|
17
|
-
Company email: displays the current saved value on each run and asks whether
|
|
18
|
-
to update it; the default answer keeps the existing value. Non-interactive
|
|
19
|
-
installs only update when OHAI_INSTALL_USER_EMAIL is set to a valid email.
|
|
20
|
-
|
|
21
|
-
Email file: %USERPROFILE%\.config\opencode\ohai-report\email.json — edit this JSON to change
|
|
22
|
-
your company email. Per-repo override: <project>\.ohai-report\user_email.json (same shape).
|
|
23
|
-
|
|
24
|
-
.PARAMETER DryRun
|
|
25
|
-
Print actions only; do not copy files or change env.
|
|
26
|
-
|
|
27
|
-
.PARAMETER PluginOnly
|
|
28
|
-
Copy plugin only; skip commands.
|
|
29
|
-
|
|
30
|
-
.PARAMETER SkipEnv
|
|
31
|
-
Do not set OHAI_REPORT_CLI (default is to set it when ohai_report.py exists).
|
|
32
|
-
|
|
33
|
-
.PARAMETER SkipEmail
|
|
34
|
-
Do not prompt and do not write ohai-report/email.json.
|
|
35
|
-
#>
|
|
36
|
-
param(
|
|
37
|
-
[switch]$DryRun,
|
|
38
|
-
[switch]$PluginOnly,
|
|
39
|
-
[switch]$SkipEnv,
|
|
40
|
-
[switch]$SkipEmail
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
$ErrorActionPreference = "Stop"
|
|
44
|
-
|
|
45
|
-
function Test-OhaiCompanyEmail {
|
|
46
|
-
param([Parameter(Mandatory)][AllowEmptyString()][string]$Value)
|
|
47
|
-
$t = $Value.Trim()
|
|
48
|
-
if ($t.Length -lt 5) { return $false }
|
|
49
|
-
try {
|
|
50
|
-
$null = [mailaddress]$t
|
|
51
|
-
return ($t -eq ([mailaddress]$t).Address)
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return $false
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function Get-OhaiSavedEmail {
|
|
59
|
-
param([Parameter(Mandatory)][string[]]$Paths)
|
|
60
|
-
foreach ($path in $Paths) {
|
|
61
|
-
if (-not (Test-Path -LiteralPath $path)) {
|
|
62
|
-
continue
|
|
63
|
-
}
|
|
64
|
-
try {
|
|
65
|
-
$raw = Get-Content -LiteralPath $path -Raw
|
|
66
|
-
$j = $raw | ConvertFrom-Json -ErrorAction SilentlyContinue
|
|
67
|
-
$e = if ($j.user_email) { $j.user_email } elseif ($j.userEmail) { $j.userEmail } else { "" }
|
|
68
|
-
if (Test-OhaiCompanyEmail $e) {
|
|
69
|
-
return [pscustomobject]@{ Email = $e.Trim(); Path = $path }
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch { }
|
|
73
|
-
}
|
|
74
|
-
return $null
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function Read-OhaiEmailUpdate {
|
|
78
|
-
param(
|
|
79
|
-
[Parameter(Mandatory)][AllowEmptyString()][string]$CurrentEmail,
|
|
80
|
-
[Parameter(Mandatory)][string]$EmailPath
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
$display = if ($CurrentEmail) { $CurrentEmail } else { "(not set)" }
|
|
84
|
-
Write-Host ('Current company email: ' + $display) -ForegroundColor Cyan
|
|
85
|
-
|
|
86
|
-
if ([Console]::IsInputRedirected) {
|
|
87
|
-
$fromEnv = [Environment]::GetEnvironmentVariable('OHAI_INSTALL_USER_EMAIL', 'Process')
|
|
88
|
-
if (Test-OhaiCompanyEmail $fromEnv) {
|
|
89
|
-
Write-Host 'Non-interactive install: updating email from OHAI_INSTALL_USER_EMAIL.' -ForegroundColor Yellow
|
|
90
|
-
return $fromEnv.Trim()
|
|
91
|
-
}
|
|
92
|
-
Write-Host 'Non-interactive install: keeping current email; set OHAI_INSTALL_USER_EMAIL to update.' -ForegroundColor Yellow
|
|
93
|
-
return ""
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
$answer = (Read-Host 'Update company email? [y/N]').Trim().ToLowerInvariant()
|
|
97
|
-
if ($answer -ne 'y' -and $answer -ne 'yes') {
|
|
98
|
-
Write-Host 'Keeping current company email.' -ForegroundColor Yellow
|
|
99
|
-
return ""
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
while ($true) {
|
|
103
|
-
$line = Read-Host 'Company email'
|
|
104
|
-
if (Test-OhaiCompanyEmail $line) {
|
|
105
|
-
return $line.Trim()
|
|
106
|
-
}
|
|
107
|
-
Write-Host 'Invalid Company email. Examples: xxxxx@huawei.com or xxxxx@h-partners.com' -ForegroundColor Red
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
|
112
|
-
$PluginSrc = Join-Path $RepoRoot ".opencode\plugins\oh-ai-report.ts"
|
|
113
|
-
$CommandSrc = Join-Path $RepoRoot ".opencode\commands\report-ai-issue.md"
|
|
114
|
-
|
|
115
|
-
if (-not (Test-Path -LiteralPath $PluginSrc)) {
|
|
116
|
-
throw ('Plugin source not found: ' + $PluginSrc + ' (run from repo checkout)')
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
$OcRoot = Join-Path $env:USERPROFILE ".config\opencode"
|
|
120
|
-
$PluginsDir = Join-Path $OcRoot "plugins"
|
|
121
|
-
$CommandsDir = Join-Path $OcRoot "commands"
|
|
122
|
-
$DestPlugin = Join-Path $PluginsDir "oh-ai-report.ts"
|
|
123
|
-
$DestCommand = Join-Path $CommandsDir "report-ai-issue.md"
|
|
124
|
-
$emailDir = Join-Path $OcRoot "ohai-report"
|
|
125
|
-
$emailJsonPath = Join-Path $emailDir "email.json"
|
|
126
|
-
$legacyUserJsonPath = Join-Path $OcRoot "ohai-report-user.json"
|
|
127
|
-
$CliPy = Join-Path $RepoRoot "tools\ohai-report\ohai_report.py"
|
|
128
|
-
$cliResolved = if (Test-Path -LiteralPath $CliPy) { (Resolve-Path $CliPy).Path } else { "" }
|
|
129
|
-
$cliHint = if ($cliResolved) { $cliResolved } else { '(ohai_report.py not found in this repo)' }
|
|
130
|
-
|
|
131
|
-
Write-Host ""
|
|
132
|
-
Write-Host "=== OpenCode oh-ai-report install ===" -ForegroundColor Cyan
|
|
133
|
-
Write-Host ('Repo root: ' + $RepoRoot)
|
|
134
|
-
Write-Host ('OpenCode global config: ' + $OcRoot)
|
|
135
|
-
Write-Host ""
|
|
136
|
-
|
|
137
|
-
if ($DryRun) {
|
|
138
|
-
Write-Host ('[DryRun] mkdir ' + $PluginsDir) -ForegroundColor Yellow
|
|
139
|
-
Write-Host ('[DryRun] copy ' + $PluginSrc + ' -> ' + $DestPlugin)
|
|
140
|
-
if (-not $PluginOnly) {
|
|
141
|
-
Write-Host ('[DryRun] mkdir ' + $CommandsDir)
|
|
142
|
-
Write-Host ('[DryRun] copy ' + $CommandSrc + ' -> ' + $DestCommand)
|
|
143
|
-
}
|
|
144
|
-
if ($SkipEmail) {
|
|
145
|
-
Write-Host '[DryRun] skip user email file (-SkipEmail)' -ForegroundColor Yellow
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
Write-Host ('[DryRun] prompt company email + write ' + $emailJsonPath) -ForegroundColor Yellow
|
|
149
|
-
}
|
|
150
|
-
if ($SkipEnv) {
|
|
151
|
-
Write-Host '[DryRun] skip env (-SkipEnv)' -ForegroundColor Yellow
|
|
152
|
-
}
|
|
153
|
-
elseif ($cliResolved) {
|
|
154
|
-
Write-Host ('[DryRun] set User env OHAI_REPORT_CLI=' + $cliResolved) -ForegroundColor Yellow
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
Write-Host '[DryRun] skip env (ohai_report.py missing)' -ForegroundColor Yellow
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
$userEmailToSave = ""
|
|
162
|
-
if (-not $SkipEmail) {
|
|
163
|
-
$savedEmail = Get-OhaiSavedEmail -Paths @($emailJsonPath, $legacyUserJsonPath)
|
|
164
|
-
if ($savedEmail) {
|
|
165
|
-
Write-Host ('Email file: ' + $savedEmail.Path) -ForegroundColor Cyan
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
Write-Host ('Email file: ' + $emailJsonPath) -ForegroundColor Cyan
|
|
169
|
-
}
|
|
170
|
-
$currentEmail = if ($savedEmail) { $savedEmail.Email } else { "" }
|
|
171
|
-
$userEmailToSave = Read-OhaiEmailUpdate -CurrentEmail $currentEmail -EmailPath $emailJsonPath
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
New-Item -ItemType Directory -Force -Path $PluginsDir | Out-Null
|
|
175
|
-
Copy-Item -LiteralPath $PluginSrc -Destination $DestPlugin -Force
|
|
176
|
-
Write-Host ('Installed plugin: ' + $DestPlugin) -ForegroundColor Green
|
|
177
|
-
|
|
178
|
-
if (-not $PluginOnly) {
|
|
179
|
-
if (-not (Test-Path -LiteralPath $CommandSrc)) {
|
|
180
|
-
Write-Host ('Skipped command (missing source): ' + $CommandSrc) -ForegroundColor Yellow
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
New-Item -ItemType Directory -Force -Path $CommandsDir | Out-Null
|
|
184
|
-
Copy-Item -LiteralPath $CommandSrc -Destination $DestCommand -Force
|
|
185
|
-
Write-Host ('Installed command: ' + $DestCommand) -ForegroundColor Green
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (-not $SkipEmail -and $userEmailToSave) {
|
|
190
|
-
New-Item -ItemType Directory -Force -Path $emailDir | Out-Null
|
|
191
|
-
$obj = [ordered]@{ user_email = $userEmailToSave }
|
|
192
|
-
$json = ($obj | ConvertTo-Json -Compress)
|
|
193
|
-
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
|
|
194
|
-
[System.IO.File]::WriteAllText($emailJsonPath, $json, $utf8NoBom)
|
|
195
|
-
Write-Host ('Saved company email to: ' + $emailJsonPath) -ForegroundColor Green
|
|
196
|
-
Write-Host 'Per-repo override (optional): <your-repo>\.ohai-report\user_email.json with {"user_email":"..."}' -ForegroundColor Cyan
|
|
197
|
-
if (Test-Path -LiteralPath $legacyUserJsonPath) {
|
|
198
|
-
Write-Host ('Note: legacy file exists (still read by tools): ' + $legacyUserJsonPath) -ForegroundColor Yellow
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
elseif ($SkipEmail) {
|
|
202
|
-
Write-Host 'Skipped user email file (-SkipEmail).' -ForegroundColor Yellow
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (-not $SkipEnv -and $cliResolved) {
|
|
206
|
-
[Environment]::SetEnvironmentVariable('OHAI_REPORT_CLI', $cliResolved, 'User')
|
|
207
|
-
Write-Host ('Set user env OHAI_REPORT_CLI=' + $cliResolved) -ForegroundColor Green
|
|
208
|
-
}
|
|
209
|
-
elseif (-not $SkipEnv -and -not $cliResolved) {
|
|
210
|
-
Write-Host 'Skipped env: ohai_report.py not found under this repo.' -ForegroundColor Yellow
|
|
211
|
-
}
|
|
212
|
-
elseif ($SkipEnv) {
|
|
213
|
-
Write-Host 'Skipped env (-SkipEnv).' -ForegroundColor Yellow
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
Write-Host ""
|
|
218
|
-
function Add-OpenCodePluginConfig {
|
|
219
|
-
param(
|
|
220
|
-
[Parameter(Mandatory=$true)][string]$ConfigPath,
|
|
221
|
-
[Parameter(Mandatory=$true)][string]$PluginEntry
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
if (Test-Path -LiteralPath $ConfigPath) {
|
|
225
|
-
try {
|
|
226
|
-
$cfg = Get-Content -LiteralPath $ConfigPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
227
|
-
} catch {
|
|
228
|
-
Write-Warning ("Could not parse " + $ConfigPath + "; leaving it unchanged: " + $_.Exception.Message)
|
|
229
|
-
return
|
|
230
|
-
}
|
|
231
|
-
} else {
|
|
232
|
-
$cfg = [pscustomobject]@{
|
|
233
|
-
'$schema' = 'https://opencode.ai/config.json'
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (-not ($cfg.PSObject.Properties.Name -contains 'plugin')) {
|
|
238
|
-
Add-Member -InputObject $cfg -MemberType NoteProperty -Name plugin -Value @()
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
$existing = @($cfg.plugin | ForEach-Object { [string]$_ } | Where-Object { $_ })
|
|
242
|
-
if ($existing -notcontains $PluginEntry) {
|
|
243
|
-
$cfg.plugin = @($existing + $PluginEntry)
|
|
244
|
-
$cfg | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath $ConfigPath -Encoding UTF8
|
|
245
|
-
Write-Host ('Updated OpenCode config plugin list: ' + $ConfigPath) -ForegroundColor Green
|
|
246
|
-
} else {
|
|
247
|
-
Write-Host ('OpenCode config already includes plugin: ' + $PluginEntry) -ForegroundColor DarkGray
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
$PluginConfigEntry = './plugins/oh-ai-report.ts'
|
|
252
|
-
$OpenCodeConfigPath = Join-Path $OcRoot 'opencode.json'
|
|
253
|
-
if ($DryRun) {
|
|
254
|
-
Write-Host ('[DryRun] ensure opencode.json plugin includes ' + $PluginConfigEntry) -ForegroundColor Yellow
|
|
255
|
-
} else {
|
|
256
|
-
Add-OpenCodePluginConfig -ConfigPath $OpenCodeConfigPath -PluginEntry $PluginConfigEntry
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
Write-Host 'Next: fully quit and restart OpenCode so global plugins/commands load.' -ForegroundColor Cyan
|
|
260
|
-
Write-Host ""
|
|
261
|
-
if ($cliResolved) {
|
|
262
|
-
Write-Host ('OHAI_REPORT_CLI (after restart): ' + $cliHint) -ForegroundColor Yellow
|
|
263
|
-
}
|
|
264
|
-
Write-Host ""
|