oh-langfuse 0.1.79 → 0.1.80

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.
@@ -1,71 +1,71 @@
1
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
- import { listSystemCliCandidates } from "./cli-detection-utils.mjs";
6
-
7
- function isKnownBrokenWindowsOpencodeCandidate(candidate) {
8
- if (process.platform !== "win32") return false;
9
- const normalized = String(candidate || "").replace(/\//g, "\\").toLowerCase();
10
- return normalized.endsWith("\\node_modules\\opencode-ai\\bin\\opencode.exe");
11
- }
12
-
13
- function usableCandidate(candidate) {
14
- return candidate && !isKnownBrokenWindowsOpencodeCandidate(candidate) && fs.existsSync(candidate);
15
- }
16
-
17
- /**
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ import { spawnSync } from "node:child_process";
5
+ import { listSystemCliCandidates } from "./cli-detection-utils.mjs";
6
+
7
+ function isKnownBrokenWindowsOpencodeCandidate(candidate) {
8
+ if (process.platform !== "win32") return false;
9
+ const normalized = String(candidate || "").replace(/\//g, "\\").toLowerCase();
10
+ return normalized.endsWith("\\node_modules\\opencode-ai\\bin\\opencode.exe");
11
+ }
12
+
13
+ function usableCandidate(candidate) {
14
+ return candidate && !isKnownBrokenWindowsOpencodeCandidate(candidate) && fs.existsSync(candidate);
15
+ }
16
+
17
+ /**
18
18
  * OpenCode CLI 的官方安装脚本默认会把二进制放到 ~/.opencode/bin;
19
19
  * npm 全局安装则可能出现在 %AppData%\npm\opencode.cmd;PATH 也可能只认识 `opencode`。
20
20
  * @param {string|undefined} preferred --cmd=xxx 或可执行文件路径
21
21
  * @returns {string|null} 可执行的绝对路径,或仅在 PATH 中解析到则用 `opencode`
22
22
  */
23
23
  export function resolveOpencodeCli(preferred) {
24
- if (typeof preferred === "string" && preferred.trim()) {
25
- const p = preferred.trim();
26
- if (usableCandidate(p)) return path.resolve(p);
27
- }
24
+ if (typeof preferred === "string" && preferred.trim()) {
25
+ const p = preferred.trim();
26
+ if (usableCandidate(p)) return path.resolve(p);
27
+ }
28
28
 
29
29
  const home = os.homedir();
30
30
 
31
31
  /** @type {string[]} */
32
- const candidates = [];
33
- if (process.platform === "win32") {
34
- candidates.push(path.join(home, ".opencode", "bin", "opencode.exe"));
35
- if (process.env.APPDATA) {
36
- candidates.push(path.join(process.env.APPDATA, "npm", "node_modules", "opencode-ai", "node_modules", "opencode-windows-x64", "bin", "opencode.exe"));
37
- candidates.push(path.join(process.env.APPDATA, "npm", "node_modules", "opencode-ai", "node_modules", "opencode-windows-x64-baseline", "bin", "opencode.exe"));
38
- candidates.push(path.join(process.env.APPDATA, "npm", "node_modules", "opencode-windows-x64", "bin", "opencode.exe"));
39
- candidates.push(path.join(process.env.APPDATA, "npm", "node_modules", "opencode-windows-x64-baseline", "bin", "opencode.exe"));
40
- }
41
- if (process.env.LOCALAPPDATA) {
42
- candidates.push(path.join(process.env.LOCALAPPDATA, "Programs", "opencode", "opencode.exe"));
43
- }
44
- candidates.push(path.join(home, ".config", "opencode", "bin", "opencode.exe"));
45
- candidates.push(path.join(home, ".config", "opencode", "bin", "opencode.cmd"));
46
- candidates.push(path.join(home, ".opencode", "bin", "opencode.cmd"));
47
- candidates.push(path.join(home, "bin", "opencode.exe"));
48
- if (process.env.APPDATA) {
49
- candidates.push(path.join(process.env.APPDATA, "npm", "opencode.cmd"));
50
- candidates.push(path.join(process.env.APPDATA, "npm", "opencode"));
51
- }
52
- candidates.push(path.join(home, "scoop", "shims", "opencode.exe"));
53
- } else {
54
- candidates.push(path.join(home, ".opencode", "bin", "opencode"));
55
- candidates.push(path.join(home, ".local", "bin", "opencode"));
56
- candidates.push(...listSystemCliCandidates("opencode"));
57
- }
58
-
59
- for (const c of candidates) {
60
- if (usableCandidate(c)) return c;
61
- }
32
+ const candidates = [];
33
+ if (process.platform === "win32") {
34
+ candidates.push(path.join(home, ".opencode", "bin", "opencode.exe"));
35
+ if (process.env.APPDATA) {
36
+ candidates.push(path.join(process.env.APPDATA, "npm", "node_modules", "opencode-ai", "node_modules", "opencode-windows-x64", "bin", "opencode.exe"));
37
+ candidates.push(path.join(process.env.APPDATA, "npm", "node_modules", "opencode-ai", "node_modules", "opencode-windows-x64-baseline", "bin", "opencode.exe"));
38
+ candidates.push(path.join(process.env.APPDATA, "npm", "node_modules", "opencode-windows-x64", "bin", "opencode.exe"));
39
+ candidates.push(path.join(process.env.APPDATA, "npm", "node_modules", "opencode-windows-x64-baseline", "bin", "opencode.exe"));
40
+ }
41
+ if (process.env.LOCALAPPDATA) {
42
+ candidates.push(path.join(process.env.LOCALAPPDATA, "Programs", "opencode", "opencode.exe"));
43
+ }
44
+ candidates.push(path.join(home, ".config", "opencode", "bin", "opencode.exe"));
45
+ candidates.push(path.join(home, ".config", "opencode", "bin", "opencode.cmd"));
46
+ candidates.push(path.join(home, ".opencode", "bin", "opencode.cmd"));
47
+ candidates.push(path.join(home, "bin", "opencode.exe"));
48
+ if (process.env.APPDATA) {
49
+ candidates.push(path.join(process.env.APPDATA, "npm", "opencode.cmd"));
50
+ candidates.push(path.join(process.env.APPDATA, "npm", "opencode"));
51
+ }
52
+ candidates.push(path.join(home, "scoop", "shims", "opencode.exe"));
53
+ } else {
54
+ candidates.push(path.join(home, ".opencode", "bin", "opencode"));
55
+ candidates.push(path.join(home, ".local", "bin", "opencode"));
56
+ candidates.push(...listSystemCliCandidates("opencode"));
57
+ }
58
+
59
+ for (const c of candidates) {
60
+ if (usableCandidate(c)) return c;
61
+ }
62
62
 
63
63
  if (process.platform === "win32") {
64
64
  const r = spawnSync("where.exe", ["opencode"], { encoding: "utf8", windowsHide: true });
65
65
  if (r.status === 0 && r.stdout) {
66
- const line = r.stdout.trim().split(/\r?\n/)[0]?.trim();
67
- if (usableCandidate(line)) return line;
68
- }
66
+ const line = r.stdout.trim().split(/\r?\n/)[0]?.trim();
67
+ if (usableCandidate(line)) return line;
68
+ }
69
69
  } else {
70
70
  const r = spawnSync("which", ["opencode"], { encoding: "utf8" });
71
71
  if (r.status === 0 && r.stdout) {
@@ -1,20 +1,20 @@
1
1
  import fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
- import { spawnSync } from "node:child_process";
5
- import { fileURLToPath } from "node:url";
6
- import { hasSystemCli } from "./cli-detection-utils.mjs";
7
- import { buildUpdatePlan, extractVersionFromNpmMetadata } from "./update-utils.mjs";
8
- import { writeRuntimeInstallRecord } from "./runtime-state-utils.mjs";
4
+ import { spawnSync } from "node:child_process";
5
+ import { fileURLToPath } from "node:url";
6
+ import { hasSystemCli } from "./cli-detection-utils.mjs";
7
+ import { buildUpdatePlan, extractVersionFromNpmMetadata } from "./update-utils.mjs";
8
+ import { writeRuntimeInstallRecord } from "./runtime-state-utils.mjs";
9
9
 
10
10
  const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
11
11
  const packageJson = JSON.parse(fs.readFileSync(path.join(rootDir, "package.json"), "utf8"));
12
12
 
13
- const DEFAULT_LANGFUSE_BASE_URL = "https://metrics.openharmonyinsight.cn";
14
- const LEGACY_LANGFUSE_BASE_URLS = new Set([
15
- "http://120.46.221.227:3000",
16
- "https://120.46.221.227:3000",
17
- ]);
13
+ const DEFAULT_LANGFUSE_BASE_URL = "https://metrics.openharmonyinsight.cn";
14
+ const LEGACY_LANGFUSE_BASE_URLS = new Set([
15
+ "http://120.46.221.227:3000",
16
+ "https://120.46.221.227:3000",
17
+ ]);
18
18
  const DEFAULT_LANGFUSE_PUBLIC_KEY = "pk-lf-da0c90a7-6e93-4eb7-bb86-c1047c8d187d";
19
19
  const DEFAULT_LANGFUSE_SECRET_KEY = "sk-lf-0269b85d-bfdc-442c-bfa3-e737954e3315";
20
20
 
@@ -64,21 +64,21 @@ function readJsonIfExists(p) {
64
64
  }
65
65
  }
66
66
 
67
- function detectInstalledTargets(home = os.homedir()) {
68
- const codexHome = process.env.CODEX_HOME || path.join(home, ".codex");
69
- return {
70
- claude:
71
- fs.existsSync(path.join(home, ".claude", "hooks", "langfuse_hook.py")) ||
72
- hasSystemCli("claude"),
73
- opencode:
74
- fs.existsSync(path.join(home, ".config", "opencode", "opencode.json")) ||
75
- fs.existsSync(path.join(home, ".config", "opencode", "plugins", "opencode-plugin-langfuse")) ||
76
- hasSystemCli("opencode"),
77
- codex:
78
- fs.existsSync(path.join(codexHome, "hooks", "codex_langfuse_notify.py")) ||
79
- hasSystemCli("codex"),
80
- };
81
- }
67
+ function detectInstalledTargets(home = os.homedir()) {
68
+ const codexHome = process.env.CODEX_HOME || path.join(home, ".codex");
69
+ return {
70
+ claude:
71
+ fs.existsSync(path.join(home, ".claude", "hooks", "langfuse_hook.py")) ||
72
+ hasSystemCli("claude"),
73
+ opencode:
74
+ fs.existsSync(path.join(home, ".config", "opencode", "opencode.json")) ||
75
+ fs.existsSync(path.join(home, ".config", "opencode", "plugins", "opencode-plugin-langfuse")) ||
76
+ hasSystemCli("opencode"),
77
+ codex:
78
+ fs.existsSync(path.join(codexHome, "hooks", "codex_langfuse_notify.py")) ||
79
+ hasSystemCli("codex"),
80
+ };
81
+ }
82
82
 
83
83
  function claudeConfig(home) {
84
84
  const settings = readJsonIfExists(path.join(home, ".claude", "settings.json")) || {};
@@ -102,7 +102,7 @@ function codexConfig(home) {
102
102
  };
103
103
  }
104
104
 
105
- function opencodeConfig(home) {
105
+ function opencodeConfig(home) {
106
106
  const config = readJsonIfExists(path.join(home, ".config", "opencode-plugin-langfuse", "config.json")) || {};
107
107
  return {
108
108
  baseUrl: process.env.LANGFUSE_BASEURL || process.env.LANGFUSE_HOST,
@@ -110,29 +110,29 @@ function opencodeConfig(home) {
110
110
  secretKey: process.env.LANGFUSE_SECRET_KEY,
111
111
  userId: config.userId || config.usrid || process.env.LANGFUSE_USER_ID,
112
112
  };
113
- }
114
-
115
- function normalizeLegacyBaseUrl(baseUrl) {
116
- const value = String(baseUrl || "").trim().replace(/\/+$/, "");
117
- return LEGACY_LANGFUSE_BASE_URLS.has(value) ? DEFAULT_LANGFUSE_BASE_URL : baseUrl;
118
- }
119
-
120
- function mergedConfig(target, args) {
121
- const home = os.homedir();
122
- const existing = target === "claude" ? claudeConfig(home) : target === "codex" ? codexConfig(home) : opencodeConfig(home);
123
- const baseUrl = normalizeLegacyBaseUrl(
124
- args.langfuseBaseUrl ||
125
- args.langfuseHost ||
126
- args.host ||
127
- existing.baseUrl ||
128
- process.env.LANGFUSE_BASEURL ||
129
- DEFAULT_LANGFUSE_BASE_URL
130
- );
131
- const config = {
132
- baseUrl,
133
- publicKey: args.publicKey || existing.publicKey || process.env.LANGFUSE_PUBLIC_KEY || DEFAULT_LANGFUSE_PUBLIC_KEY,
134
- secretKey: args.secretKey || existing.secretKey || process.env.LANGFUSE_SECRET_KEY || DEFAULT_LANGFUSE_SECRET_KEY,
135
- userId: args.userId || args.userid || existing.userId || process.env.LANGFUSE_USER_ID || process.env.CC_USER_ID || "",
113
+ }
114
+
115
+ function normalizeLegacyBaseUrl(baseUrl) {
116
+ const value = String(baseUrl || "").trim().replace(/\/+$/, "");
117
+ return LEGACY_LANGFUSE_BASE_URLS.has(value) ? DEFAULT_LANGFUSE_BASE_URL : baseUrl;
118
+ }
119
+
120
+ function mergedConfig(target, args) {
121
+ const home = os.homedir();
122
+ const existing = target === "claude" ? claudeConfig(home) : target === "codex" ? codexConfig(home) : opencodeConfig(home);
123
+ const baseUrl = normalizeLegacyBaseUrl(
124
+ args.langfuseBaseUrl ||
125
+ args.langfuseHost ||
126
+ args.host ||
127
+ existing.baseUrl ||
128
+ process.env.LANGFUSE_BASEURL ||
129
+ DEFAULT_LANGFUSE_BASE_URL
130
+ );
131
+ const config = {
132
+ baseUrl,
133
+ publicKey: args.publicKey || existing.publicKey || process.env.LANGFUSE_PUBLIC_KEY || DEFAULT_LANGFUSE_PUBLIC_KEY,
134
+ secretKey: args.secretKey || existing.secretKey || process.env.LANGFUSE_SECRET_KEY || DEFAULT_LANGFUSE_SECRET_KEY,
135
+ userId: args.userId || args.userid || existing.userId || process.env.LANGFUSE_USER_ID || process.env.CC_USER_ID || "",
136
136
  };
137
137
  if (!config.userId) throw new Error(`Missing user id for ${target}; provide --userId=<employee-id> or run setup first.`);
138
138
  return config;
@@ -57,9 +57,9 @@ echo.
57
57
  call npm run claude:setup -- --userId=%USER_ID% --pyPath=%PY_PATH%
58
58
  if errorlevel 1 exit /b 1
59
59
 
60
- echo.
61
- echo Check:
62
- call npx oh-langfuse@latest check claude
60
+ echo.
61
+ echo Check:
62
+ call npx oh-langfuse@latest check claude
63
63
  exit /b %errorlevel%
64
64
 
65
65
  :OPENCODE
@@ -72,11 +72,11 @@ echo - NO auto-launch: open opencode in a NEW terminal afterwards
72
72
  echo.
73
73
 
74
74
  set "OC_USER_ID="
75
- set /p OC_USER_ID=Enter userId (required) ^>
76
- if "%OC_USER_ID%"=="" (
77
- echo [ERROR] userId is required.
78
- exit /b 1
79
- )
75
+ set /p OC_USER_ID=Enter userId (required) ^>
76
+ if "%OC_USER_ID%"=="" (
77
+ echo [ERROR] userId is required.
78
+ exit /b 1
79
+ )
80
80
 
81
81
  echo.
82
82
  echo Write LANGFUSE_* to Windows user env vars (HKCU)?
@@ -98,7 +98,7 @@ set "OC_CMD="
98
98
  set /p OC_CMD=OpenCode CLI path (optional; press Enter to auto-detect) ^>
99
99
 
100
100
  set "SETUP_ARGS="
101
- set "SETUP_ARGS=%SETUP_ARGS% --userId=%OC_USER_ID%"
101
+ set "SETUP_ARGS=%SETUP_ARGS% --userId=%OC_USER_ID%"
102
102
  if /i "%OC_SET_ENV%"=="n" set "SETUP_ARGS=%SETUP_ARGS% --no-set-env"
103
103
  if /i "%OC_SET_ENV%"=="no" set "SETUP_ARGS=%SETUP_ARGS% --no-set-env"
104
104
  if /i "%OC_SKIP_INSTALL%"=="y" set "SETUP_ARGS=%SETUP_ARGS% --skip-plugin-install"
@@ -120,13 +120,13 @@ if errorlevel 1 goto :OPENCODE_FAIL
120
120
  echo.
121
121
  echo ============================================
122
122
  echo OpenCode setup finished.
123
- echo Next:
124
- echo 1) Open a NEW terminal (HKCU env vars take effect).
125
- echo 2) Run: opencode
126
- echo Optional launcher:
127
- echo %USERPROFILE%\.config\opencode\launch-opencode-langfuse.cmd
128
- echo 3) Check: npx oh-langfuse@latest check opencode
129
- echo ============================================
123
+ echo Next:
124
+ echo 1) Open a NEW terminal (HKCU env vars take effect).
125
+ echo 2) Run: opencode
126
+ echo Optional launcher:
127
+ echo %USERPROFILE%\.config\opencode\launch-opencode-langfuse.cmd
128
+ echo 3) Check: npx oh-langfuse@latest check opencode
129
+ echo ============================================
130
130
  exit /b 0
131
131
 
132
132
  :CODEX
@@ -150,9 +150,9 @@ echo.
150
150
  call npm run codex:setup -- --userId=%CODEX_USER_ID% --pyPath=%CODEX_PY_PATH%
151
151
  if errorlevel 1 exit /b 1
152
152
 
153
- echo.
154
- echo Check:
155
- call npx oh-langfuse@latest check codex
153
+ echo.
154
+ echo Check:
155
+ call npx oh-langfuse@latest check codex
156
156
  exit /b %errorlevel%
157
157
 
158
158
  :NO_NPM
package/setup-langfuse.sh CHANGED
@@ -44,8 +44,8 @@ case "$choice" in
44
44
  echo "Running: npm run claude:setup -- --userId=${user_id} --pyPath=${py_path}"
45
45
  npm run claude:setup -- --userId="${user_id}" --pyPath="${py_path}"
46
46
  echo
47
- echo "Check: npx oh-langfuse@latest check claude"
48
- npx oh-langfuse@latest check claude
47
+ echo "Check: npx oh-langfuse@latest check claude"
48
+ npx oh-langfuse@latest check claude
49
49
  ;;
50
50
 
51
51
  2)
@@ -56,12 +56,12 @@ case "$choice" in
56
56
  echo " - NO auto-launch: you will open opencode in a NEW terminal afterwards"
57
57
  echo
58
58
 
59
- printf "Enter userId (required) > "
60
- IFS= read -r user_id || true
61
- if [ -z "${user_id:-}" ]; then
62
- echo "[ERROR] userId is required."
63
- exit 1
64
- fi
59
+ printf "Enter userId (required) > "
60
+ IFS= read -r user_id || true
61
+ if [ -z "${user_id:-}" ]; then
62
+ echo "[ERROR] userId is required."
63
+ exit 1
64
+ fi
65
65
 
66
66
  echo
67
67
  echo "Skip plugin install (npm install opencode-plugin-langfuse)?"
@@ -75,7 +75,7 @@ case "$choice" in
75
75
  IFS= read -r oc_cmd || true
76
76
 
77
77
  run_args=""
78
- run_args="${run_args} --userId=${user_id}"
78
+ run_args="${run_args} --userId=${user_id}"
79
79
  case "${skip_install:-}" in
80
80
  y|Y|yes|YES|Yes)
81
81
  run_args="${run_args} --skip-plugin-install"
@@ -96,14 +96,14 @@ case "$choice" in
96
96
 
97
97
  echo
98
98
  echo "============================================"
99
- echo "OpenCode setup finished."
100
- echo "Next:"
101
- echo " 1) Open a NEW terminal."
102
- echo " 2) Run: opencode"
103
- echo " 3) Check: npx oh-langfuse@latest check opencode"
104
- echo " If LANGFUSE_* is not visible in the new terminal, run:"
105
- echo " ~/.config/opencode/launch-opencode-langfuse.sh"
106
- echo "============================================"
99
+ echo "OpenCode setup finished."
100
+ echo "Next:"
101
+ echo " 1) Open a NEW terminal."
102
+ echo " 2) Run: opencode"
103
+ echo " 3) Check: npx oh-langfuse@latest check opencode"
104
+ echo " If LANGFUSE_* is not visible in the new terminal, run:"
105
+ echo " ~/.config/opencode/launch-opencode-langfuse.sh"
106
+ echo "============================================"
107
107
  ;;
108
108
 
109
109
  3)
@@ -124,8 +124,8 @@ case "$choice" in
124
124
  echo "Running: npm run codex:setup -- --userId=${user_id} --pyPath=${py_path}"
125
125
  npm run codex:setup -- --userId="${user_id}" --pyPath="${py_path}"
126
126
  echo
127
- echo "Check: npx oh-langfuse@latest check codex"
128
- npx oh-langfuse@latest check codex
127
+ echo "Check: npx oh-langfuse@latest check codex"
128
+ npx oh-langfuse@latest check codex
129
129
  ;;
130
130
 
131
131
  *)