coze_lab 0.1.24 → 0.1.25
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 +2 -0
- package/index.js +69 -6
- package/package.json +1 -1
- package/scripts/claude-code/cozeloop_hook.py +1 -1
- package/scripts/codex/cozeloop_hook.py +1 -1
package/README.md
CHANGED
|
@@ -74,6 +74,8 @@ In cloud mode, trace verification and hook uploads prefer
|
|
|
74
74
|
`COZELOOP_API_TOKEN` and fall back to `COZE_API_TOKEN`. The selfcheck result is
|
|
75
75
|
authoritative: if the token does not have trace ingest permission, onboard still
|
|
76
76
|
writes the hook configuration but reports `verify=fail` with `token_source`.
|
|
77
|
+
For Python SDK uploads, `OTEL_ENDPOINT` is not used as the SDK base URL; set
|
|
78
|
+
`COZELOOP_API_BASE_URL` only when the SDK ingest endpoint should be overridden.
|
|
77
79
|
|
|
78
80
|
**At hook execution time** (Claude Code / Codex), the Python hook script automatically:
|
|
79
81
|
1. Reads `~/.cozeloop/credentials.json`
|
package/index.js
CHANGED
|
@@ -4706,6 +4706,10 @@ function normalizeTraceAgentIds(ids) {
|
|
|
4706
4706
|
|
|
4707
4707
|
function getCloudCozeloopApiBaseUrl() {
|
|
4708
4708
|
const raw = process.env.COZELOOP_API_BASE_URL || process.env.OTEL_ENDPOINT || '';
|
|
4709
|
+
return normalizeCozeloopApiBaseUrl(raw);
|
|
4710
|
+
}
|
|
4711
|
+
|
|
4712
|
+
function normalizeCozeloopApiBaseUrl(raw) {
|
|
4709
4713
|
const base = raw.trim().replace(/\/+$/, '');
|
|
4710
4714
|
if (!base) return '';
|
|
4711
4715
|
if (base.endsWith('/v1/loop/opentelemetry/v1/traces')) {
|
|
@@ -4730,6 +4734,14 @@ function getCozeloopApiBaseUrl(cloud) {
|
|
|
4730
4734
|
return cloud ? (getCloudCozeloopApiBaseUrl() || COZE_API) : COZE_API;
|
|
4731
4735
|
}
|
|
4732
4736
|
|
|
4737
|
+
function getCloudCozeloopSdkApiBaseUrl() {
|
|
4738
|
+
return normalizeCozeloopApiBaseUrl(process.env.COZELOOP_API_BASE_URL || '');
|
|
4739
|
+
}
|
|
4740
|
+
|
|
4741
|
+
function getCozeloopSdkApiBaseUrl(cloud) {
|
|
4742
|
+
return cloud ? (getCloudCozeloopSdkApiBaseUrl() || COZE_API) : COZE_API;
|
|
4743
|
+
}
|
|
4744
|
+
|
|
4733
4745
|
function getOtelEndpointBase(cloud) {
|
|
4734
4746
|
return `${getCozeloopApiBaseUrl(cloud).replace(/\/+$/, '')}/v1/loop/opentelemetry`;
|
|
4735
4747
|
}
|
|
@@ -4935,11 +4947,13 @@ function runCommand(input) {
|
|
|
4935
4947
|
|
|
4936
4948
|
async function verifyTraceReportViaSdk(token, workspaceId, pairCode, pythonCmd, tokenSource) {
|
|
4937
4949
|
const pair = pairCode || crypto.randomBytes(6).toString('hex');
|
|
4938
|
-
const apiBase =
|
|
4950
|
+
const apiBase = getCozeloopSdkApiBaseUrl(true);
|
|
4939
4951
|
const script = `
|
|
4940
4952
|
import json
|
|
4941
4953
|
import os
|
|
4942
4954
|
import sys
|
|
4955
|
+
import urllib.error
|
|
4956
|
+
import urllib.request
|
|
4943
4957
|
|
|
4944
4958
|
events = []
|
|
4945
4959
|
|
|
@@ -4947,6 +4961,51 @@ def finish_event(info):
|
|
|
4947
4961
|
if getattr(info, "is_event_fail", False):
|
|
4948
4962
|
events.append(getattr(info, "detail_msg", "") or "trace export failed")
|
|
4949
4963
|
|
|
4964
|
+
def extract_logid(text):
|
|
4965
|
+
if not text:
|
|
4966
|
+
return ""
|
|
4967
|
+
marker = "logid="
|
|
4968
|
+
idx = text.find(marker)
|
|
4969
|
+
if idx >= 0:
|
|
4970
|
+
out = []
|
|
4971
|
+
for ch in text[idx + len(marker):]:
|
|
4972
|
+
if ch.isalnum():
|
|
4973
|
+
out.append(ch)
|
|
4974
|
+
else:
|
|
4975
|
+
break
|
|
4976
|
+
return "".join(out)
|
|
4977
|
+
for marker in ('"logid":"', '"log_id":"', '"Logid":"'):
|
|
4978
|
+
idx = text.find(marker)
|
|
4979
|
+
if idx >= 0:
|
|
4980
|
+
rest = text[idx + len(marker):]
|
|
4981
|
+
return rest.split('"', 1)[0]
|
|
4982
|
+
return ""
|
|
4983
|
+
|
|
4984
|
+
def http_diag():
|
|
4985
|
+
base = os.environ.get("COZELOOP_API_BASE_URL", "").strip().rstrip("/") or "https://api.coze.cn"
|
|
4986
|
+
url = base + "/v1/loop/traces/ingest"
|
|
4987
|
+
body = json.dumps({"spans": []}).encode()
|
|
4988
|
+
req = urllib.request.Request(
|
|
4989
|
+
url,
|
|
4990
|
+
data=body,
|
|
4991
|
+
headers={
|
|
4992
|
+
"Content-Type": "application/json",
|
|
4993
|
+
"Authorization": "Bearer " + os.environ.get("COZELOOP_API_TOKEN", ""),
|
|
4994
|
+
"x-tt-env": os.environ.get("x_tt_env", ""),
|
|
4995
|
+
"x-use-ppe": os.environ.get("x_use_ppe", ""),
|
|
4996
|
+
},
|
|
4997
|
+
method="POST",
|
|
4998
|
+
)
|
|
4999
|
+
try:
|
|
5000
|
+
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
5001
|
+
text = resp.read().decode("utf-8", "replace")
|
|
5002
|
+
return {"url": url, "status": resp.status, "logid": resp.headers.get("x-tt-logid", "") or extract_logid(text), "body": text[:300]}
|
|
5003
|
+
except urllib.error.HTTPError as e:
|
|
5004
|
+
text = e.read().decode("utf-8", "replace")
|
|
5005
|
+
return {"url": url, "status": e.code, "logid": e.headers.get("x-tt-logid", "") or extract_logid(text), "body": text[:300]}
|
|
5006
|
+
except Exception as e:
|
|
5007
|
+
return {"url": url, "status": 0, "logid": "", "body": type(e).__name__ + ": " + str(e)}
|
|
5008
|
+
|
|
4950
5009
|
try:
|
|
4951
5010
|
import cozeloop
|
|
4952
5011
|
kwargs = {
|
|
@@ -4966,11 +5025,15 @@ try:
|
|
|
4966
5025
|
client.flush()
|
|
4967
5026
|
client.close()
|
|
4968
5027
|
if events:
|
|
4969
|
-
|
|
5028
|
+
diag = http_diag()
|
|
5029
|
+
body = "\\n".join(events) + "\\nhttp_diag=" + json.dumps(diag, ensure_ascii=False)
|
|
5030
|
+
print(json.dumps({"success": False, "body": body, "logid": diag.get("logid", ""), "api_base_url": os.environ.get("COZELOOP_API_BASE_URL", ""), "token_source": os.environ.get("COZELOOP_TOKEN_SOURCE", "")}, ensure_ascii=False))
|
|
4970
5031
|
sys.exit(1)
|
|
4971
|
-
print(json.dumps({"success": True, "body": "", "api_base_url": os.environ.get("COZELOOP_API_BASE_URL", ""), "token_source": os.environ.get("COZELOOP_TOKEN_SOURCE", "")}, ensure_ascii=False))
|
|
5032
|
+
print(json.dumps({"success": True, "body": "", "logid": "", "api_base_url": os.environ.get("COZELOOP_API_BASE_URL", ""), "token_source": os.environ.get("COZELOOP_TOKEN_SOURCE", "")}, ensure_ascii=False))
|
|
4972
5033
|
except Exception as e:
|
|
4973
|
-
|
|
5034
|
+
diag = http_diag()
|
|
5035
|
+
body = str(e) + "\\nhttp_diag=" + json.dumps(diag, ensure_ascii=False)
|
|
5036
|
+
print(json.dumps({"success": False, "body": body, "logid": diag.get("logid", ""), "api_base_url": os.environ.get("COZELOOP_API_BASE_URL", ""), "token_source": os.environ.get("COZELOOP_TOKEN_SOURCE", "")}, ensure_ascii=False))
|
|
4974
5037
|
sys.exit(1)
|
|
4975
5038
|
`;
|
|
4976
5039
|
const env = {
|
|
@@ -5005,7 +5068,7 @@ except Exception as e:
|
|
|
5005
5068
|
const snippet = String(body || '').slice(0, 300);
|
|
5006
5069
|
if (snippet) console.log(snippet);
|
|
5007
5070
|
}
|
|
5008
|
-
return { success, status: result.code || 0, body, traceId: '', pairCode: pair, apiBaseUrl: apiBase, tokenSource };
|
|
5071
|
+
return { success, status: result.code || 0, body, traceId: '', pairCode: pair, apiBaseUrl: apiBase, tokenSource, logid: parsed?.logid || '' };
|
|
5009
5072
|
}
|
|
5010
5073
|
|
|
5011
5074
|
// 真实发一条最小 OTLP trace 到 CozeLoop,验证上报链路是否打通。
|
|
@@ -5538,7 +5601,7 @@ async function main() {
|
|
|
5538
5601
|
} else if (CLOUD_MODE) {
|
|
5539
5602
|
// 云端:注入已成功,验证失败不阻断(放行),记录结果供后台弹 warning。
|
|
5540
5603
|
cloudResult.verify = 'fail';
|
|
5541
|
-
cloudResult.logid = extractLogid(verifyResult.body) || cloudResult.logid;
|
|
5604
|
+
cloudResult.logid = verifyResult.logid || extractLogid(verifyResult.body) || cloudResult.logid;
|
|
5542
5605
|
cloudResult.message = `trace 上报自检失败 HTTP ${verifyResult.status}: ${(verifyResult.body || '').slice(0, 200)}`;
|
|
5543
5606
|
warn('trace 上报自检失败,但 hook 配置已写入(云端放行)。');
|
|
5544
5607
|
console.log('');
|
package/package.json
CHANGED
|
@@ -264,7 +264,7 @@ def _normalize_api_base_url(url: str) -> str:
|
|
|
264
264
|
|
|
265
265
|
def get_api_base_url() -> str:
|
|
266
266
|
return _normalize_api_base_url(
|
|
267
|
-
os.environ.get("COZELOOP_API_BASE_URL", "")
|
|
267
|
+
os.environ.get("COZELOOP_API_BASE_URL", "")
|
|
268
268
|
)
|
|
269
269
|
|
|
270
270
|
def get_fresh_token() -> Optional[str]:
|
|
@@ -225,7 +225,7 @@ def _normalize_api_base_url(url: str) -> str:
|
|
|
225
225
|
|
|
226
226
|
def get_api_base_url() -> str:
|
|
227
227
|
return _normalize_api_base_url(
|
|
228
|
-
os.environ.get("COZELOOP_API_BASE_URL", "")
|
|
228
|
+
os.environ.get("COZELOOP_API_BASE_URL", "")
|
|
229
229
|
)
|
|
230
230
|
|
|
231
231
|
|