oh-aicoding-tool 0.1.0

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 (55) hide show
  1. package/CODEX_LANGFUSE_PLAN.md +62 -0
  2. package/README.md +114 -0
  3. package/bin/cli.js +166 -0
  4. package/bin/langfuse-cli.js +718 -0
  5. package/codex_langfuse_notify.py +591 -0
  6. package/langfuse_hook.py +603 -0
  7. package/opencode-ohai-report/.claude/commands/report-ai-issue.md +60 -0
  8. package/opencode-ohai-report/.opencode/commands/report-ai-issue.md +30 -0
  9. package/opencode-ohai-report/.opencode/plugins/oh-ai-report.ts +569 -0
  10. package/opencode-ohai-report/README.md +45 -0
  11. package/opencode-ohai-report/bin/cli.js +421 -0
  12. package/opencode-ohai-report/docs/opencode-ai-issue-collection-architecture.md +313 -0
  13. package/opencode-ohai-report/docs/opencode-ai-issue-collection-best-practices.md +476 -0
  14. package/opencode-ohai-report/docs/opencode-ai-issue-collection-phase1-summary.md +405 -0
  15. package/opencode-ohai-report/examples/issue_output.json +4 -0
  16. package/opencode-ohai-report/package.json +40 -0
  17. package/opencode-ohai-report/scripts/claude_report_hook.py +257 -0
  18. package/opencode-ohai-report/scripts/create_issue.py +34 -0
  19. package/opencode-ohai-report/scripts/install-claude-plugin.ps1 +254 -0
  20. package/opencode-ohai-report/scripts/install-opencode-plugin.ps1 +264 -0
  21. package/opencode-ohai-report/scripts/install-opencode-plugin.sh +218 -0
  22. package/opencode-ohai-report/scripts/merge-claude-settings.py +99 -0
  23. package/opencode-ohai-report/tools/ohai-report/README.md +151 -0
  24. package/opencode-ohai-report/tools/ohai-report/examples/issue-input.json +26 -0
  25. package/opencode-ohai-report/tools/ohai-report/ohai_report/__init__.py +5 -0
  26. package/opencode-ohai-report/tools/ohai-report/ohai_report/__main__.py +9 -0
  27. package/opencode-ohai-report/tools/ohai-report/ohai_report/cli.py +319 -0
  28. package/opencode-ohai-report/tools/ohai-report/ohai_report/git_context.py +32 -0
  29. package/opencode-ohai-report/tools/ohai-report/ohai_report/gitcode_defaults.py +14 -0
  30. package/opencode-ohai-report/tools/ohai-report/ohai_report/issue_markdown.py +313 -0
  31. package/opencode-ohai-report/tools/ohai-report/ohai_report/metadata.py +360 -0
  32. package/opencode-ohai-report/tools/ohai-report/ohai_report/observability/__init__.py +1 -0
  33. package/opencode-ohai-report/tools/ohai-report/ohai_report/observability/langfuse.py +38 -0
  34. package/opencode-ohai-report/tools/ohai-report/ohai_report/payload.py +64 -0
  35. package/opencode-ohai-report/tools/ohai-report/ohai_report/schema.py +80 -0
  36. package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/__init__.py +1 -0
  37. package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/base.py +15 -0
  38. package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/gitcode.py +405 -0
  39. package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/local.py +21 -0
  40. package/opencode-ohai-report/tools/ohai-report/ohai_report/sinks/webhook.py +354 -0
  41. package/opencode-ohai-report/tools/ohai-report/ohai_report/webhook_defaults.py +9 -0
  42. package/opencode-ohai-report/tools/ohai-report/ohai_report/workspace.py +61 -0
  43. package/opencode-ohai-report/tools/ohai-report/ohai_report.py +10 -0
  44. package/opencode-ohai-report/tools/ohai-report/schemas/report_issue.schema.json +166 -0
  45. package/package.json +59 -0
  46. package/scripts/codex-langfuse-check.mjs +101 -0
  47. package/scripts/codex-langfuse-setup.mjs +181 -0
  48. package/scripts/langfuse-check.mjs +90 -0
  49. package/scripts/langfuse-setup.mjs +278 -0
  50. package/scripts/opencode-langfuse-check.mjs +94 -0
  51. package/scripts/opencode-langfuse-run.mjs +96 -0
  52. package/scripts/opencode-langfuse-setup.mjs +478 -0
  53. package/scripts/resolve-opencode-cli.mjs +58 -0
  54. package/setup-langfuse.bat +163 -0
  55. package/setup-langfuse.sh +130 -0
@@ -0,0 +1,58 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ import { spawnSync } from "node:child_process";
5
+
6
+ /**
7
+ * OpenCode CLI 的官方安装脚本默认会把二进制放到 ~/.opencode/bin;
8
+ * npm 全局安装则可能出现在 %AppData%\npm\opencode.cmd;PATH 也可能只认识 `opencode`。
9
+ * @param {string|undefined} preferred --cmd=xxx 或可执行文件路径
10
+ * @returns {string|null} 可执行的绝对路径,或仅在 PATH 中解析到则用 `opencode`
11
+ */
12
+ export function resolveOpencodeCli(preferred) {
13
+ if (typeof preferred === "string" && preferred.trim()) {
14
+ const p = preferred.trim();
15
+ if (fs.existsSync(p)) return path.resolve(p);
16
+ }
17
+
18
+ const home = os.homedir();
19
+
20
+ /** @type {string[]} */
21
+ const candidates = [];
22
+ if (process.platform === "win32") {
23
+ candidates.push(path.join(home, ".opencode", "bin", "opencode.exe"));
24
+ candidates.push(path.join(home, ".opencode", "bin", "opencode.cmd"));
25
+ candidates.push(path.join(home, "bin", "opencode.exe"));
26
+ if (process.env.LOCALAPPDATA) {
27
+ candidates.push(path.join(process.env.LOCALAPPDATA, "Programs", "opencode", "opencode.exe"));
28
+ }
29
+ if (process.env.APPDATA) {
30
+ candidates.push(path.join(process.env.APPDATA, "npm", "opencode.cmd"));
31
+ candidates.push(path.join(process.env.APPDATA, "npm", "opencode"));
32
+ }
33
+ candidates.push(path.join(home, "scoop", "shims", "opencode.exe"));
34
+ } else {
35
+ candidates.push(path.join(home, ".opencode", "bin", "opencode"));
36
+ candidates.push(path.join(home, ".local", "bin", "opencode"));
37
+ }
38
+
39
+ for (const c of candidates) {
40
+ if (c && fs.existsSync(c)) return c;
41
+ }
42
+
43
+ if (process.platform === "win32") {
44
+ const r = spawnSync("where.exe", ["opencode"], { encoding: "utf8", windowsHide: true });
45
+ if (r.status === 0 && r.stdout) {
46
+ const line = r.stdout.trim().split(/\r?\n/)[0]?.trim();
47
+ if (line && fs.existsSync(line)) return line;
48
+ }
49
+ } else {
50
+ const r = spawnSync("which", ["opencode"], { encoding: "utf8" });
51
+ if (r.status === 0 && r.stdout) {
52
+ const line = r.stdout.trim().split(/\r?\n/)[0]?.trim();
53
+ return line || null;
54
+ }
55
+ }
56
+
57
+ return null;
58
+ }
@@ -0,0 +1,163 @@
1
+ @echo off
2
+ setlocal EnableExtensions DisableDelayedExpansion
3
+
4
+ REM ASCII-only file to avoid mojibake in cmd.exe.
5
+ REM Labels must be ":LABEL" (do not use "::LABEL").
6
+
7
+ cd /d "%~dp0" >nul 2>&1
8
+
9
+ echo.
10
+ echo ============================================
11
+ echo Langfuse Setup (Claude Code / OpenCode / Codex)
12
+ echo CWD: %CD%
13
+ echo ============================================
14
+ echo.
15
+
16
+ where npm >nul 2>&1
17
+ if errorlevel 1 goto :NO_NPM
18
+
19
+ set "ARG_TARGET=%~1"
20
+ if /i "%ARG_TARGET%"=="claude" goto :CLAUDE
21
+ if /i "%ARG_TARGET%"=="opencode" goto :OPENCODE
22
+ if /i "%ARG_TARGET%"=="codex" goto :CODEX
23
+
24
+ echo Select target:
25
+ echo [1] Claude Code (requires userId + langfuse_hook.py)
26
+ echo [2] OpenCode (configure plugin only; open opencode in a NEW terminal)
27
+ echo [3] Codex (configure notify hook; restart Codex afterwards)
28
+ echo.
29
+ set "CHOICE="
30
+ set /p CHOICE=Enter 1, 2, or 3 ^>
31
+
32
+ if "%CHOICE%"=="1" goto :CLAUDE
33
+ if "%CHOICE%"=="2" goto :OPENCODE
34
+ if "%CHOICE%"=="3" goto :CODEX
35
+
36
+ echo [ERROR] Invalid input: %CHOICE%
37
+ exit /b 1
38
+
39
+ :CLAUDE
40
+ echo.
41
+ set "USER_ID="
42
+ set /p USER_ID=Enter userId (required) ^>
43
+ if "%USER_ID%"=="" (
44
+ echo [ERROR] userId is required.
45
+ exit /b 1
46
+ )
47
+
48
+ echo.
49
+ set "PY_PATH=.\langfuse_hook.py"
50
+ set /p PY_PATH=Path to langfuse_hook.py (default .\langfuse_hook.py) ^>
51
+ if "%PY_PATH%"=="" set "PY_PATH=.\langfuse_hook.py"
52
+
53
+ echo.
54
+ echo Running:
55
+ echo npm run claude:setup -- --userId=%USER_ID% --pyPath=%PY_PATH%
56
+ echo.
57
+ call npm run claude:setup -- --userId=%USER_ID% --pyPath=%PY_PATH%
58
+ if errorlevel 1 exit /b 1
59
+
60
+ echo.
61
+ echo Check:
62
+ call npm run claude:check
63
+ exit /b %errorlevel%
64
+
65
+ :OPENCODE
66
+ echo.
67
+ echo OpenCode setup will:
68
+ echo - install/update Langfuse OTEL plugin under ~/.config/opencode
69
+ echo - update ~/.config/opencode/opencode.json (enable OpenTelemetry + plugin)
70
+ echo - optionally write LANGFUSE_* to Windows user env vars (HKCU)
71
+ echo - NO auto-launch: open opencode in a NEW terminal afterwards
72
+ echo.
73
+
74
+ set "OC_USER_ID="
75
+ set /p OC_USER_ID=Enter userId (optional; press Enter to skip) ^>
76
+
77
+ echo.
78
+ echo Write LANGFUSE_* to Windows user env vars (HKCU)?
79
+ echo - Recommended if you start OpenCode from Desktop/Start Menu.
80
+ echo - Default: Yes (press Enter). Type n to disable.
81
+ set "OC_SET_ENV="
82
+ set /p OC_SET_ENV=Write user env vars? (Enter=Yes, n=No) ^>
83
+
84
+ echo.
85
+ echo Skip plugin install (npm install opencode-plugin-langfuse)?
86
+ echo - Only choose Yes if already installed at:
87
+ echo %USERPROFILE%\.config\opencode\node_modules\opencode-plugin-langfuse
88
+ echo - Default: No (press Enter). Type y to skip install.
89
+ set "OC_SKIP_INSTALL="
90
+ set /p OC_SKIP_INSTALL=Skip plugin install? (Enter=No, y=Yes) ^>
91
+
92
+ echo.
93
+ set "OC_CMD="
94
+ set /p OC_CMD=OpenCode CLI path (optional; press Enter to auto-detect) ^>
95
+
96
+ set "SETUP_ARGS="
97
+ if not "%OC_USER_ID%"=="" set "SETUP_ARGS=%SETUP_ARGS% --userId=%OC_USER_ID%"
98
+ if /i "%OC_SET_ENV%"=="n" set "SETUP_ARGS=%SETUP_ARGS% --no-set-env"
99
+ if /i "%OC_SET_ENV%"=="no" set "SETUP_ARGS=%SETUP_ARGS% --no-set-env"
100
+ if /i "%OC_SKIP_INSTALL%"=="y" set "SETUP_ARGS=%SETUP_ARGS% --skip-plugin-install"
101
+ if /i "%OC_SKIP_INSTALL%"=="yes" set "SETUP_ARGS=%SETUP_ARGS% --skip-plugin-install"
102
+ if not "%OC_CMD%"=="" set "SETUP_ARGS=%SETUP_ARGS% --cmd=%OC_CMD%"
103
+
104
+ echo.
105
+ echo Running:
106
+ echo npm run opencode:setup -- %SETUP_ARGS%
107
+ echo.
108
+
109
+ if "%SETUP_ARGS%"=="" (
110
+ call npm run opencode:setup
111
+ ) else (
112
+ call npm run opencode:setup -- %SETUP_ARGS%
113
+ )
114
+ if errorlevel 1 goto :OPENCODE_FAIL
115
+
116
+ echo.
117
+ echo ============================================
118
+ echo OpenCode setup finished.
119
+ echo Next:
120
+ echo 1) Open a NEW terminal (HKCU env vars take effect).
121
+ echo 2) Run: opencode
122
+ echo Optional launcher:
123
+ echo %USERPROFILE%\.config\opencode\launch-opencode-langfuse.cmd
124
+ echo ============================================
125
+ exit /b 0
126
+
127
+ :CODEX
128
+ echo.
129
+ set "CODEX_USER_ID="
130
+ set /p CODEX_USER_ID=Enter userId (required) ^>
131
+ if "%CODEX_USER_ID%"=="" (
132
+ echo [ERROR] userId is required.
133
+ exit /b 1
134
+ )
135
+
136
+ echo.
137
+ set "CODEX_PY_PATH=.\codex_langfuse_notify.py"
138
+ set /p CODEX_PY_PATH=Path to codex_langfuse_notify.py (default .\codex_langfuse_notify.py) ^>
139
+ if "%CODEX_PY_PATH%"=="" set "CODEX_PY_PATH=.\codex_langfuse_notify.py"
140
+
141
+ echo.
142
+ echo Running:
143
+ echo npm run codex:setup -- --userId=%CODEX_USER_ID% --pyPath=%CODEX_PY_PATH%
144
+ echo.
145
+ call npm run codex:setup -- --userId=%CODEX_USER_ID% --pyPath=%CODEX_PY_PATH%
146
+ if errorlevel 1 exit /b 1
147
+
148
+ echo.
149
+ echo Check:
150
+ call npm run codex:check
151
+ exit /b %errorlevel%
152
+
153
+ :NO_NPM
154
+ echo [ERROR] npm not found. Install Node.js (includes npm) and reopen your terminal.
155
+ exit /b 1
156
+
157
+ :OPENCODE_FAIL
158
+ echo.
159
+ echo [ERROR] OpenCode setup failed. Please read the error above.
160
+ echo [HINT] If you see JSON parse errors, check encoding of:
161
+ echo %USERPROFILE%\.config\opencode\opencode.json
162
+ echo [HINT] If npm install failed, check npm registry / network / proxy.
163
+ exit /b 1
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env sh
2
+ set -eu
3
+
4
+ # NOTE: Keep this file LF (not CRLF).
5
+
6
+ cd "$(dirname "$0")"
7
+
8
+ echo
9
+ echo "============================================"
10
+ echo " Langfuse Setup (Claude Code / OpenCode / Codex)"
11
+ echo " CWD: $(pwd)"
12
+ echo "============================================"
13
+ echo
14
+
15
+ if ! command -v npm >/dev/null 2>&1; then
16
+ echo "[ERROR] npm not found. Please install Node.js (includes npm)."
17
+ exit 1
18
+ fi
19
+
20
+ echo "Select target:"
21
+ echo " [1] Claude Code (requires userId + langfuse_hook.py)"
22
+ echo " [2] OpenCode (configure plugin only; open opencode in a NEW terminal)"
23
+ echo " [3] Codex (configure notify hook; restart Codex afterwards)"
24
+ echo
25
+ printf "Enter 1, 2, or 3 > "
26
+ IFS= read -r choice || true
27
+
28
+ case "$choice" in
29
+ 1)
30
+ printf "Enter userId (required) > "
31
+ IFS= read -r user_id || true
32
+ if [ -z "${user_id}" ]; then
33
+ echo "[ERROR] userId is required."
34
+ exit 1
35
+ fi
36
+
37
+ printf "Path to langfuse_hook.py (default ./langfuse_hook.py) > "
38
+ IFS= read -r py_path || true
39
+ if [ -z "${py_path:-}" ]; then
40
+ py_path="./langfuse_hook.py"
41
+ fi
42
+
43
+ echo
44
+ echo "Running: npm run claude:setup -- --userId=${user_id} --pyPath=${py_path}"
45
+ npm run claude:setup -- --userId="${user_id}" --pyPath="${py_path}"
46
+ echo
47
+ echo "Check: npm run claude:check"
48
+ npm run claude:check
49
+ ;;
50
+
51
+ 2)
52
+ echo
53
+ echo "OpenCode setup will:"
54
+ echo " - install/update the Langfuse OTEL plugin under ~/.config/opencode"
55
+ echo " - update ~/.config/opencode/opencode.json (enable OpenTelemetry + plugin)"
56
+ echo " - NO auto-launch: you will open opencode in a NEW terminal afterwards"
57
+ echo
58
+
59
+ printf "Enter userId (optional; press Enter to skip) > "
60
+ IFS= read -r user_id || true
61
+
62
+ echo
63
+ echo "Skip plugin install (npm install opencode-plugin-langfuse)?"
64
+ echo " - Only choose Yes if you already have it installed and working at:"
65
+ echo " ~/.config/opencode/node_modules/opencode-plugin-langfuse"
66
+ echo " - Default: No (press Enter). Type y to skip install."
67
+ printf "Skip plugin install? (Enter=No, y=Yes) > "
68
+ IFS= read -r skip_install || true
69
+
70
+ printf "OpenCode CLI path (optional; press Enter to auto-detect) > "
71
+ IFS= read -r oc_cmd || true
72
+
73
+ run_args=""
74
+ if [ -n "${user_id:-}" ]; then
75
+ run_args="${run_args} --userId=${user_id}"
76
+ fi
77
+ case "${skip_install:-}" in
78
+ y|Y|yes|YES|Yes)
79
+ run_args="${run_args} --skip-plugin-install"
80
+ ;;
81
+ esac
82
+ if [ -n "${oc_cmd:-}" ]; then
83
+ run_args="${run_args} --cmd=${oc_cmd}"
84
+ fi
85
+
86
+ echo
87
+ if [ -n "${run_args# }" ]; then
88
+ echo "Running: npm run opencode:setup --${run_args}"
89
+ npm run opencode:setup -- ${run_args# }
90
+ else
91
+ echo "Running: npm run opencode:setup"
92
+ npm run opencode:setup
93
+ fi
94
+
95
+ echo
96
+ echo "============================================"
97
+ echo "OpenCode setup finished."
98
+ echo "Next:"
99
+ echo " 1) Open a NEW terminal."
100
+ echo " 2) Run: opencode"
101
+ echo "============================================"
102
+ ;;
103
+
104
+ 3)
105
+ printf "Enter userId (required) > "
106
+ IFS= read -r user_id || true
107
+ if [ -z "${user_id}" ]; then
108
+ echo "[ERROR] userId is required."
109
+ exit 1
110
+ fi
111
+
112
+ printf "Path to codex_langfuse_notify.py (default ./codex_langfuse_notify.py) > "
113
+ IFS= read -r py_path || true
114
+ if [ -z "${py_path:-}" ]; then
115
+ py_path="./codex_langfuse_notify.py"
116
+ fi
117
+
118
+ echo
119
+ echo "Running: npm run codex:setup -- --userId=${user_id} --pyPath=${py_path}"
120
+ npm run codex:setup -- --userId="${user_id}" --pyPath="${py_path}"
121
+ echo
122
+ echo "Check: npm run codex:check"
123
+ npm run codex:check
124
+ ;;
125
+
126
+ *)
127
+ echo "[ERROR] Invalid input: ${choice}"
128
+ exit 1
129
+ ;;
130
+ esac