oh-langfuse 0.1.77 → 0.1.79
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/bin/cli.js +30 -21
- package/codex_langfuse_notify.py +19 -6
- package/langfuse_hook.py +19 -6
- package/package.json +1 -1
- package/scripts/codex-langfuse-setup.mjs +25 -14
- package/scripts/langfuse-setup.mjs +27 -16
- package/scripts/opencode-langfuse-run.mjs +21 -10
- package/scripts/opencode-langfuse-setup.mjs +1674 -1581
- package/scripts/real-self-verify.mjs +21 -9
- package/scripts/update-langfuse-runtime.mjs +29 -12
package/bin/cli.js
CHANGED
|
@@ -9,8 +9,12 @@ import { resolveOpencodeCli } from "../scripts/resolve-opencode-cli.mjs";
|
|
|
9
9
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
10
|
const scriptsDir = path.join(rootDir, "scripts");
|
|
11
11
|
|
|
12
|
-
const DEFAULT_LANGFUSE_BASE_URL = "
|
|
13
|
-
const
|
|
12
|
+
const DEFAULT_LANGFUSE_BASE_URL = "https://metrics.openharmonyinsight.cn";
|
|
13
|
+
const LEGACY_LANGFUSE_BASE_URLS = new Set([
|
|
14
|
+
"http://120.46.221.227:3000",
|
|
15
|
+
"https://120.46.221.227:3000",
|
|
16
|
+
]);
|
|
17
|
+
const DEFAULT_LANGFUSE_PUBLIC_KEY = "pk-lf-da0c90a7-6e93-4eb7-bb86-c1047c8d187d";
|
|
14
18
|
const DEFAULT_LANGFUSE_SECRET_KEY = "sk-lf-0269b85d-bfdc-442c-bfa3-e737954e3315";
|
|
15
19
|
const USER_ID_PATTERN = /^[a-z](?:\d{8}|wx\d{7})$/;
|
|
16
20
|
const USER_ID_PATTERN_TEXT = "^[a-z](?:\\d{8}|wx\\d{7})$";
|
|
@@ -115,13 +119,18 @@ function mask(v) {
|
|
|
115
119
|
return `${v.slice(0, 4)}...${v.slice(-4)}`;
|
|
116
120
|
}
|
|
117
121
|
|
|
118
|
-
function hasValue(v) {
|
|
119
|
-
return typeof v === "string" && v.trim().length > 0;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
function hasValue(v) {
|
|
123
|
+
return typeof v === "string" && v.trim().length > 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function normalizeLegacyBaseUrl(baseUrl) {
|
|
127
|
+
const value = String(baseUrl || "").trim().replace(/\/+$/, "");
|
|
128
|
+
return LEGACY_LANGFUSE_BASE_URLS.has(value) ? DEFAULT_LANGFUSE_BASE_URL : baseUrl;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function normalizeUserId(v) {
|
|
132
|
+
return String(v || "").trim();
|
|
133
|
+
}
|
|
125
134
|
|
|
126
135
|
function isValidUserId(v) {
|
|
127
136
|
return USER_ID_PATTERN.test(normalizeUserId(v));
|
|
@@ -506,18 +515,18 @@ async function askMultiChoice(rl, label, choices, options = {}) {
|
|
|
506
515
|
.map((idx) => choices[idx].value);
|
|
507
516
|
}
|
|
508
517
|
|
|
509
|
-
function langfuseConfig(overrides = {}) {
|
|
510
|
-
const config = {
|
|
511
|
-
baseUrl: envDefault("LANGFUSE_BASEURL", envDefault("LANGFUSE_HOST", DEFAULT_LANGFUSE_BASE_URL)),
|
|
512
|
-
publicKey: envDefault("LANGFUSE_PUBLIC_KEY", DEFAULT_LANGFUSE_PUBLIC_KEY),
|
|
513
|
-
secretKey: envDefault("LANGFUSE_SECRET_KEY", DEFAULT_LANGFUSE_SECRET_KEY),
|
|
514
|
-
userId: ""
|
|
515
|
-
};
|
|
516
|
-
for (const [key, value] of Object.entries(overrides)) {
|
|
517
|
-
if (hasValue(value)) config[key] = value;
|
|
518
|
-
}
|
|
519
|
-
return config;
|
|
520
|
-
}
|
|
518
|
+
function langfuseConfig(overrides = {}) {
|
|
519
|
+
const config = {
|
|
520
|
+
baseUrl: normalizeLegacyBaseUrl(envDefault("LANGFUSE_BASEURL", envDefault("LANGFUSE_HOST", DEFAULT_LANGFUSE_BASE_URL))),
|
|
521
|
+
publicKey: envDefault("LANGFUSE_PUBLIC_KEY", DEFAULT_LANGFUSE_PUBLIC_KEY),
|
|
522
|
+
secretKey: envDefault("LANGFUSE_SECRET_KEY", DEFAULT_LANGFUSE_SECRET_KEY),
|
|
523
|
+
userId: ""
|
|
524
|
+
};
|
|
525
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
526
|
+
if (hasValue(value)) config[key] = key === "baseUrl" ? normalizeLegacyBaseUrl(value) : value;
|
|
527
|
+
}
|
|
528
|
+
return config;
|
|
529
|
+
}
|
|
521
530
|
|
|
522
531
|
async function collectLangfuseConfig(rl, { requireUserId = false, overrides = {} } = {}) {
|
|
523
532
|
const config = langfuseConfig(overrides);
|
package/codex_langfuse_notify.py
CHANGED
|
@@ -238,12 +238,25 @@ def collect_repo_context(cwd: Optional[str], cwd_source: str = "unavailable") ->
|
|
|
238
238
|
return context
|
|
239
239
|
context["git_root"] = root
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
241
|
+
remote_context: Dict[str, str] = {}
|
|
242
|
+
remote_error = ""
|
|
243
|
+
for remote_name in ("origin", "gitcode", "upstream"):
|
|
244
|
+
ok_remote, remote, remote_error = run_git_command(cwd_text, ["config", "--get", f"remote.{remote_name}.url"])
|
|
245
|
+
if ok_remote and remote:
|
|
246
|
+
remote_context = sanitize_git_remote(remote)
|
|
247
|
+
if remote_context.get("git_remote"):
|
|
248
|
+
break
|
|
249
|
+
remote_context = {}
|
|
250
|
+
if not remote_context.get("git_remote"):
|
|
251
|
+
ok_list, remotes_raw, list_error = run_git_command(cwd_text, ["remote"])
|
|
252
|
+
if ok_list and remotes_raw:
|
|
253
|
+
first_remote = remotes_raw.splitlines()[0].strip() if remotes_raw.strip() else ""
|
|
254
|
+
if first_remote:
|
|
255
|
+
ok_remote, remote, remote_error = run_git_command(cwd_text, ["config", "--get", f"remote.{first_remote}.url"])
|
|
256
|
+
if ok_remote and remote:
|
|
257
|
+
remote_context = sanitize_git_remote(remote)
|
|
258
|
+
if remote_context.get("git_remote"):
|
|
244
259
|
context.update(remote_context)
|
|
245
|
-
if not remote_context["git_remote"]:
|
|
246
|
-
context["git_context_error"] = "remote_parse_failed"
|
|
247
260
|
elif remote_error in ("timeout", "git_unavailable"):
|
|
248
261
|
context["git_context_available"] = False
|
|
249
262
|
context["git_context_error"] = remote_error
|
|
@@ -1503,7 +1516,7 @@ def main() -> int:
|
|
|
1503
1516
|
or os.environ.get("LANGFUSE_BASEURL")
|
|
1504
1517
|
or os.environ.get("LANGFUSE_HOST")
|
|
1505
1518
|
or config.get("baseUrl")
|
|
1506
|
-
or "https://
|
|
1519
|
+
or "https://metrics.openharmonyinsight.cn"
|
|
1507
1520
|
)
|
|
1508
1521
|
user_id = (
|
|
1509
1522
|
find_value(payload, ("user_id", "userId", "username", "userName"))
|
package/langfuse_hook.py
CHANGED
|
@@ -228,12 +228,25 @@ def collect_repo_context(cwd: Optional[str], cwd_source: str = "unavailable") ->
|
|
|
228
228
|
return context
|
|
229
229
|
context["git_root"] = root
|
|
230
230
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
remote_context: Dict[str, str] = {}
|
|
232
|
+
remote_error = ""
|
|
233
|
+
for remote_name in ("origin", "gitcode", "upstream"):
|
|
234
|
+
ok_remote, remote, remote_error = run_git_command(cwd_text, ["config", "--get", f"remote.{remote_name}.url"])
|
|
235
|
+
if ok_remote and remote:
|
|
236
|
+
remote_context = sanitize_git_remote(remote)
|
|
237
|
+
if remote_context.get("git_remote"):
|
|
238
|
+
break
|
|
239
|
+
remote_context = {}
|
|
240
|
+
if not remote_context.get("git_remote"):
|
|
241
|
+
ok_list, remotes_raw, list_error = run_git_command(cwd_text, ["remote"])
|
|
242
|
+
if ok_list and remotes_raw:
|
|
243
|
+
first_remote = remotes_raw.splitlines()[0].strip() if remotes_raw.strip() else ""
|
|
244
|
+
if first_remote:
|
|
245
|
+
ok_remote, remote, remote_error = run_git_command(cwd_text, ["config", "--get", f"remote.{first_remote}.url"])
|
|
246
|
+
if ok_remote and remote:
|
|
247
|
+
remote_context = sanitize_git_remote(remote)
|
|
248
|
+
if remote_context.get("git_remote"):
|
|
234
249
|
context.update(remote_context)
|
|
235
|
-
if not remote_context["git_remote"]:
|
|
236
|
-
context["git_context_error"] = "remote_parse_failed"
|
|
237
250
|
elif remote_error in ("timeout", "git_unavailable"):
|
|
238
251
|
context["git_context_available"] = False
|
|
239
252
|
context["git_context_error"] = remote_error
|
|
@@ -1170,7 +1183,7 @@ def main() -> int:
|
|
|
1170
1183
|
|
|
1171
1184
|
public_key = os.environ.get("CC_LANGFUSE_PUBLIC_KEY") or os.environ.get("LANGFUSE_PUBLIC_KEY")
|
|
1172
1185
|
secret_key = os.environ.get("CC_LANGFUSE_SECRET_KEY") or os.environ.get("LANGFUSE_SECRET_KEY")
|
|
1173
|
-
host = os.environ.get("CC_LANGFUSE_BASE_URL") or os.environ.get("LANGFUSE_BASEURL") or "https://
|
|
1186
|
+
host = os.environ.get("CC_LANGFUSE_BASE_URL") or os.environ.get("LANGFUSE_BASEURL") or "https://metrics.openharmonyinsight.cn"
|
|
1174
1187
|
|
|
1175
1188
|
if not public_key or not secret_key:
|
|
1176
1189
|
warn("Missing Langfuse public/secret key in hook environment; exiting.")
|
package/package.json
CHANGED
|
@@ -7,13 +7,23 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { defaultWindowsNpmCliCandidates, listSystemCliCandidates } from "./cli-detection-utils.mjs";
|
|
8
8
|
import { writeRuntimeInstallRecord } from "./runtime-state-utils.mjs";
|
|
9
9
|
|
|
10
|
-
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
10
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
+
const DEFAULT_LANGFUSE_BASE_URL = "https://metrics.openharmonyinsight.cn";
|
|
12
|
+
const LEGACY_LANGFUSE_BASE_URLS = new Set([
|
|
13
|
+
"http://120.46.221.227:3000",
|
|
14
|
+
"https://120.46.221.227:3000",
|
|
15
|
+
]);
|
|
16
|
+
const USER_ID_PATTERN = /^[a-z](?:\d{8}|wx\d{7})$/;
|
|
17
|
+
const USER_ID_PATTERN_TEXT = "^[a-z](?:\\d{8}|wx\\d{7})$";
|
|
18
|
+
|
|
19
|
+
function normalizeLegacyBaseUrl(baseUrl) {
|
|
20
|
+
const value = String(baseUrl || "").trim().replace(/\/+$/, "");
|
|
21
|
+
return LEGACY_LANGFUSE_BASE_URLS.has(value) ? DEFAULT_LANGFUSE_BASE_URL : baseUrl;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function normalizeUserId(v) {
|
|
25
|
+
return String(v || "").trim();
|
|
26
|
+
}
|
|
17
27
|
|
|
18
28
|
function assertValidUserId(userId) {
|
|
19
29
|
if (!USER_ID_PATTERN.test(normalizeUserId(userId))) {
|
|
@@ -463,13 +473,14 @@ async function main() {
|
|
|
463
473
|
args.publicKey || process.env.LANGFUSE_PUBLIC_KEY || "pk-lf-da0c90a7-6e93-4eb7-bb86-c1047c8d187d";
|
|
464
474
|
const secretKey =
|
|
465
475
|
args.secretKey || process.env.LANGFUSE_SECRET_KEY || "sk-lf-0269b85d-bfdc-442c-bfa3-e737954e3315";
|
|
466
|
-
const baseUrl =
|
|
467
|
-
args.langfuseBaseUrl ||
|
|
468
|
-
args.langfuseHost ||
|
|
469
|
-
args.host ||
|
|
470
|
-
process.env.LANGFUSE_BASEURL ||
|
|
471
|
-
process.env.LANGFUSE_HOST ||
|
|
472
|
-
|
|
476
|
+
const baseUrl = normalizeLegacyBaseUrl(
|
|
477
|
+
args.langfuseBaseUrl ||
|
|
478
|
+
args.langfuseHost ||
|
|
479
|
+
args.host ||
|
|
480
|
+
process.env.LANGFUSE_BASEURL ||
|
|
481
|
+
process.env.LANGFUSE_HOST ||
|
|
482
|
+
DEFAULT_LANGFUSE_BASE_URL
|
|
483
|
+
);
|
|
473
484
|
const userId = normalizeUserId(args.userId || args.userid || "");
|
|
474
485
|
if (!userId || typeof userId !== "string") {
|
|
475
486
|
throw new Error("缺少参数:--userId=你的工号");
|
|
@@ -7,15 +7,25 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { defaultWindowsNpmCliCandidates, listSystemCliCandidates } from "./cli-detection-utils.mjs";
|
|
8
8
|
import { writeRuntimeInstallRecord } from "./runtime-state-utils.mjs";
|
|
9
9
|
|
|
10
|
-
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
-
const packageJson = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
10
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
|
|
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
|
+
]);
|
|
18
|
+
const USER_ID_PATTERN = /^[a-z](?:\d{8}|wx\d{7})$/;
|
|
19
|
+
const USER_ID_PATTERN_TEXT = "^[a-z](?:\\d{8}|wx\\d{7})$";
|
|
20
|
+
|
|
21
|
+
function normalizeLegacyBaseUrl(baseUrl) {
|
|
22
|
+
const value = String(baseUrl || "").trim().replace(/\/+$/, "");
|
|
23
|
+
return LEGACY_LANGFUSE_BASE_URLS.has(value) ? DEFAULT_LANGFUSE_BASE_URL : baseUrl;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function normalizeUserId(v) {
|
|
27
|
+
return String(v || "").trim();
|
|
28
|
+
}
|
|
19
29
|
|
|
20
30
|
function assertValidUserId(userId) {
|
|
21
31
|
if (!USER_ID_PATTERN.test(normalizeUserId(userId))) {
|
|
@@ -473,13 +483,14 @@ async function main() {
|
|
|
473
483
|
}
|
|
474
484
|
assertValidUserId(userId);
|
|
475
485
|
|
|
476
|
-
const langfuseHost =
|
|
477
|
-
args.langfuseBaseUrl ||
|
|
478
|
-
args.langfuseHost ||
|
|
479
|
-
args.host ||
|
|
480
|
-
process.env.LANGFUSE_BASEURL ||
|
|
481
|
-
process.env.LANGFUSE_HOST ||
|
|
482
|
-
|
|
486
|
+
const langfuseHost = normalizeLegacyBaseUrl(
|
|
487
|
+
args.langfuseBaseUrl ||
|
|
488
|
+
args.langfuseHost ||
|
|
489
|
+
args.host ||
|
|
490
|
+
process.env.LANGFUSE_BASEURL ||
|
|
491
|
+
process.env.LANGFUSE_HOST ||
|
|
492
|
+
DEFAULT_LANGFUSE_BASE_URL
|
|
493
|
+
);
|
|
483
494
|
|
|
484
495
|
const publicKey =
|
|
485
496
|
args.publicKey || process.env.LANGFUSE_PUBLIC_KEY || "pk-lf-da0c90a7-6e93-4eb7-bb86-c1047c8d187d";
|
|
@@ -3,12 +3,22 @@ import { fileURLToPath } from "node:url";
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { resolveOpencodeCli } from "./resolve-opencode-cli.mjs";
|
|
5
5
|
|
|
6
|
-
const USER_ID_PATTERN = /^[a-z](?:\d{8}|wx\d{7})$/;
|
|
7
|
-
const USER_ID_PATTERN_TEXT = "^[a-z](?:\\d{8}|wx\\d{7})$";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
const USER_ID_PATTERN = /^[a-z](?:\d{8}|wx\d{7})$/;
|
|
7
|
+
const USER_ID_PATTERN_TEXT = "^[a-z](?:\\d{8}|wx\\d{7})$";
|
|
8
|
+
const DEFAULT_LANGFUSE_BASE_URL = "https://metrics.openharmonyinsight.cn";
|
|
9
|
+
const LEGACY_LANGFUSE_BASE_URLS = new Set([
|
|
10
|
+
"http://120.46.221.227:3000",
|
|
11
|
+
"https://120.46.221.227:3000",
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
function normalizeLegacyBaseUrl(baseUrl) {
|
|
15
|
+
const value = String(baseUrl || "").trim().replace(/\/+$/, "");
|
|
16
|
+
return LEGACY_LANGFUSE_BASE_URLS.has(value) ? DEFAULT_LANGFUSE_BASE_URL : baseUrl;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function normalizeUserId(v) {
|
|
20
|
+
return String(v || "").trim();
|
|
21
|
+
}
|
|
12
22
|
|
|
13
23
|
function assertValidUserId(userId) {
|
|
14
24
|
if (!USER_ID_PATTERN.test(normalizeUserId(userId))) {
|
|
@@ -42,7 +52,7 @@ function main() {
|
|
|
42
52
|
args.publicKey || process.env.LANGFUSE_PUBLIC_KEY || "pk-lf-da0c90a7-6e93-4eb7-bb86-c1047c8d187d";
|
|
43
53
|
const secretKey =
|
|
44
54
|
args.secretKey || process.env.LANGFUSE_SECRET_KEY || "sk-lf-0269b85d-bfdc-442c-bfa3-e737954e3315";
|
|
45
|
-
const baseUrl = args.langfuseBaseUrl || process.env.LANGFUSE_BASEURL ||
|
|
55
|
+
const baseUrl = normalizeLegacyBaseUrl(args.langfuseBaseUrl || process.env.LANGFUSE_BASEURL || DEFAULT_LANGFUSE_BASE_URL);
|
|
46
56
|
const userId = normalizeUserId(args.userId || args.userid || "");
|
|
47
57
|
if (!userId) {
|
|
48
58
|
throw new Error("Missing userId. Run with --userId=your-id.");
|
|
@@ -54,9 +64,10 @@ function main() {
|
|
|
54
64
|
const setupPath = path.join(scriptsDir, "opencode-langfuse-setup.mjs");
|
|
55
65
|
const setupExtra = [];
|
|
56
66
|
if (args["no-set-env"]) setupExtra.push("--no-set-env");
|
|
57
|
-
if (args["skip-plugin-install"]) setupExtra.push("--skip-plugin-install");
|
|
58
|
-
if (userId) setupExtra.push(`--userId=${userId}`);
|
|
59
|
-
|
|
67
|
+
if (args["skip-plugin-install"]) setupExtra.push("--skip-plugin-install");
|
|
68
|
+
if (userId) setupExtra.push(`--userId=${userId}`);
|
|
69
|
+
setupExtra.push(`--langfuseBaseUrl=${baseUrl}`);
|
|
70
|
+
runNodeScript(setupPath, setupExtra);
|
|
60
71
|
|
|
61
72
|
// 2) 直接带环境变量启动 opencode(本进程内有效)
|
|
62
73
|
const cmdArg = args.cmd || "opencode";
|