直连接口测试成功

This commit is contained in:
2026-04-23 04:36:57 +08:00
parent 5bc69bcd5b
commit a1587b8d12
15 changed files with 2694 additions and 7 deletions

View File

@@ -0,0 +1,24 @@
{"ts": "2026-04-22T19:28:06Z", "duration_ms": 74, "method": "POST", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/state", "query_keys": ["platform"], "request_headers": {"Accept": "application/json, text/plain, */*", "Content-Type": "application/json", "X-Requested-With": "XMLHttpRequest", "X-Domain": "copilot.tencent.com", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "X-Request-ID": "542d8b477a06493f85d5dc2045d5f4ce", "Content-Length": "2", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 2, "json_shape": {}}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:05 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "231", "Connection": "keep-alive", "Traceid": "525bc3a71e49a62e521789d70ade454b", "X-Request-Id": "542d8b477a06493f85d5dc2045d5f4ce", "X-WAF-UUID": "7569e764b6fd23cb5b9a126c695e71ad-b9fcc7a3be75fd72c39d75fc2b9039c0"}, "response_body": {"bytes": 231, "json_shape": {"code": "<redacted>", "msg": "<str:2>", "requestId": "<str:32>", "data": {"state": "<redacted>", "authUrl": "<str:89>"}}}}
{"ts": "2026-04-22T19:28:07Z", "duration_ms": 59, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:06 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "9d4e37c9b60662598fffa6723aa293ff", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "17306e929090cbb99b63e4dc007bb34b-7c4c20cdb45b7b1fe37a60fa283a0e2c"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:07Z", "duration_ms": 60, "method": "POST", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/report", "query_keys": [], "request_headers": {"Accept": "application/json, text/plain, */*", "Content-Type": "application/json;charset=UTF-8", "X-Requested-With": "XMLHttpRequest", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "X-Request-ID": "0f71727aa08941209e2af794856d9cc1", "Content-Length": "643", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 643, "json_shape": [{"eventCode": "<str:13>", "timestamp": 1776886085888, "reportDelay": 2008, "status": "<str:4>", "text": "<str:11>", "isInterval": false, "userId": "<str:0>", "username": "<str:0>", "userNickname": "<str:0>", "product": "<str:4>", "releaseDate": 1776861992582, "commit": "<str:40>", "os": "<str:5>", "arch": "<str:3>", "osVersion": "<str:32>", "cpuModel": "<str:36>", "cpuCores": 16, "memorySize": 16, "extName": "<str:26>", "extVersion": "<str:6>", "ideName": "<str:3>", "ideType": "<str:3>", "machineId": "<str:36>", "sessionId": "<str:36>", "ideVersion": "<str:6>"}]}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:06 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "68", "Connection": "keep-alive", "Traceid": "bec5774e40ebb363eed0a6ac74157fe8", "X-Request-Id": "0f71727aa08941209e2af794856d9cc1", "Vary": "Origin", "X-WAF-UUID": "db265b723b6f5b221b6cd768538d29f6-d0384c744d37072da893d970676ba8f3"}, "response_body": {"bytes": 68, "json_shape": {"code": "<redacted>", "msg": "<str:2>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:08Z", "duration_ms": 65, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:07 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "b3e438f7600ad2c7c74096c8fdb650a7", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "7561c48adf8ff2adfa6f05ff7a717d62-caa9ea5311a910c99d37d6dfa4adf046"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:09Z", "duration_ms": 63, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:08 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "97bea75cc2560e9d40a56fb168362436", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "7a42cd7b556733adb6f5a55692cd62ac-08360eaf309f90bb1809d56951e5f562"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:10Z", "duration_ms": 61, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:09 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "9dd98d70adfe0bdfbb5c705ab787b86b", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "4238efd0fa1605d08e0c7f3061f79863-26a4d718c77e01602e6682df2acb85bb"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:11Z", "duration_ms": 60, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:10 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "563fb3a1b2d622c5443989557f488141", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "2ac8278fcfe3d5cfc5ddfec21b0b9df1-4b4e6967455e61949960d0ec5d5ea46c"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:12Z", "duration_ms": 60, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:11 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "c9b1426dd99721d19eff7fe736c0d0ac", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "eb1a2f56f023e34cdd058d4892f2b306-2012b0f7d90772578f75171d223a138b"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:13Z", "duration_ms": 61, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:12 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "b405eda66eef26c1561b0f57d475554f", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "a886a97ed14cd592e8f2c99457560a9c-64467b16939e1f2d4e7ecb259b185167"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:14Z", "duration_ms": 66, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:13 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "172cd117ef35ad50807ba9c1fdd49beb", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "74f45e67467fc3e368a24ab2c07f92ad-c7c46cd8e0cf98ece0ba978a365b3c78"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:16Z", "duration_ms": 65, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:14 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "1b2c649e4379f5b2a2ae929366a137a7", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "118603248ca1c72939b9a4d43f91e91f-5d13d9e5c51e711941fe97d18c37d8cf"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:17Z", "duration_ms": 60, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:15 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "233c66a087f90bc73579717d58cfa7dd", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "50100182c650f7c144e1a333c4feb545-8b889355f0f451f6651df78aa6caea6d"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:16Z", "duration_ms": 63, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:16 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "a4b7d7d65645a0f7db0b6f2f14e4ba60", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "e553e3cb59a45e9c3bce38bde59481e6-ae7b126e42021e38fc636774b4fdc7d6"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:17Z", "duration_ms": 63, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:17 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "9a638a507d7fc3524cff980dbc4a8614", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "45e993c02d6ace442e99746fb43af31e-2dfd54d03e7a3c2ea8e0efe19522ac9f"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:18Z", "duration_ms": 62, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:18 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "62f0aad52ea89344adeabdaead9c8cf7", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "3dac57ec3301e563b6c08811e0263920-ed7b7a954cb418ca7336ee2f6c0b677d"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:19Z", "duration_ms": 62, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:19 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "8551478fd69e1825a67d1adb51332b3b", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "ab77344b53a644f17b0cd538709353fa-f3be30e40572e302f8532667dd49f9bc"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:20Z", "duration_ms": 63, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:20 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "e7640d34feb3cef45948634aec12a063", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "e60d41d81b8eb0a2d5d5ecc2df939298-24217ce76269f6e3da83a2a3c513a5e7"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:21Z", "duration_ms": 69, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:21 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "88777ea3b696b3e4b3bc796d11886fff", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "834498cec8f8fb21b574401341090450-9230012a13fe89e9ca02c73120ee84f9"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:23Z", "duration_ms": 62, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:22 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "6b141e4db205efc0269ff7204c850f8d", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "df93c99c43fa876b0a563b179993fc2d-da7db2fad72706269221b177f9966ed4"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:24Z", "duration_ms": 66, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:23 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "b90ce3d6944026652807b2051a748dad", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "da19b5c9f26438ca108be24c9fa19930-3c3bd1418376bd36930080eec294ba80"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:25Z", "duration_ms": 63, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:24 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "88", "Connection": "keep-alive", "Traceid": "09131ac560703bc804cb1dd35de72e5d", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "62ee48e2ed52c4f85186ae23eb8ba657-aee1f9e24dd50d72ce86fe25d8f7ace7"}, "response_body": {"bytes": 88, "json_shape": {"code": "<redacted>", "msg": "<str:18>", "requestId": "<str:32>"}}}
{"ts": "2026-04-22T19:28:26Z", "duration_ms": 66, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/auth/token", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-Authorization": "true", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:25 GMT", "Content-Type": "application/json; charset=utf-8", "Transfer-Encoding": "chunked", "Connection": "keep-alive", "Traceid": "23d15a119cef1372e8003fe5b09e1727", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-WAF-UUID": "d6ebcf349404ea3aa51761e11b5ff030-273048bfdba22d4705ed41e110b2e0b4"}, "response_body": {"bytes": 2304, "json_shape": {"code": "<redacted>", "msg": "<str:2>", "requestId": "<str:32>", "data": {"accessToken": "<redacted>", "expiresIn": 31521275, "refreshExpiresIn": 31521275, "refreshToken": "<redacted>", "tokenType": "<redacted>", "sessionState": "<str:36>", "scope": "openid profile offline_access email", "domain": "<str:16>"}}}}
{"ts": "2026-04-22T19:28:27Z", "duration_ms": 490, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/login/account", "query_keys": ["state"], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Domain": "www.codebuddy.cn", "Authorization": "<redacted>", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-No-User-Id": "true", "X-No-Enterprise-Id": "true", "X-No-Department-Info": "true", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:27 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "479", "Connection": "keep-alive", "Set-Cookie": "<redacted>", "Traceid": "c189431336b4fc8bd0ff496983a07bd0", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-User-Id": "8c87d007-5acd-4899-9f45-8c40391a5bbf", "X-WAF-UUID": "2f756d52f79b90112efe3011b9f3a213-98aa9e2f1e6610cfbcf16b34c424a24a"}, "response_body": {"bytes": 479, "json_shape": {"code": "<redacted>", "msg": "<str:2>", "requestId": "<str:32>", "data": {"uid": "<str:36>", "nickname": "<str:7>", "uin": "<str:12>", "type": "personal", "lastLogin": true, "pluginEnabled": true, "deployStatus": {"statusCode": 0, "statusMsg": "<str:0>", "detailMsg": "<str:0>"}, "accountType": "<str:0>", "sso": {"domain": "<str:0>", "domainModifiedTimes": 0}, "idp": "<str:0>", "areaInfoComplete": false, "oneidAccountId": "<str:0>", "isCurrentOneIdEnterprise": false, "isFirstLogin": false, "phoneNumber": "<str:11>"}}}}
{"ts": "2026-04-22T19:28:28Z", "duration_ms": 833, "method": "GET", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/plugin/accounts", "query_keys": [], "request_headers": {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "X-Domain": "www.codebuddy.cn", "Authorization": "<redacted>", "X-Trace-ID": "3487696224c6829bf4aa97c943e74d27", "X-Request-ID": "3487696224c6829bf4aa97c943e74d27", "b3": "3487696224c6829bf4aa97c943e74d27-d849e49b5db91fb9-1-", "X-B3-TraceId": "3487696224c6829bf4aa97c943e74d27", "X-B3-ParentSpanId": "", "X-B3-SpanId": "d849e49b5db91fb9", "X-B3-Sampled": "1", "X-Product": "SaaS", "User-Agent": "CLI/2.93.3 CodeBuddy/2.93.3", "Host": "copilot.tencent.com", "Connection": "keep-alive"}, "request_body": {"bytes": 0}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 19:28:28 GMT", "Content-Type": "application/json; charset=utf-8", "Content-Length": "494", "Connection": "keep-alive", "Set-Cookie": "<redacted>", "Traceid": "0f1c475129171cb98dff604a500c2ea5", "X-Request-Id": "3487696224c6829bf4aa97c943e74d27", "X-User-Id": "8c87d007-5acd-4899-9f45-8c40391a5bbf", "X-WAF-UUID": "53cfb489ab4fd880f5c930df21fdad64-44ecc9972dd5d334308a24d6fa5668aa"}, "response_body": {"bytes": 494, "json_shape": {"code": "<redacted>", "msg": "<str:2>", "requestId": "<str:32>", "data": {"accounts": [{"uid": "<str:36>", "nickname": "<str:7>", "uin": "<str:12>", "type": "personal", "lastLogin": true, "pluginEnabled": true, "deployStatus": {"statusCode": 0, "statusMsg": "<str:0>", "detailMsg": "<str:0>"}, "accountType": "<str:0>", "sso": {"domain": "<str:0>", "domainModifiedTimes": 0}, "idp": "<str:0>", "areaInfoComplete": false, "oneidAccountId": "<str:0>", "isCurrentOneIdEnterprise": false, "isFirstLogin": false, "phoneNumber": "<str:11>"}]}}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"ts": "2026-04-22T20:21:31Z", "duration_ms": 2272, "method": "POST", "scheme": "https", "host": "copilot.tencent.com", "port": 443, "path": "/v2/chat/completions", "query_keys": [], "request_headers": {"Host": "copilot.tencent.com", "content-type": "application/json", "content-encoding": "gzip", "accept": "application/json", "x-requested-with": "XMLHttpRequest", "authorization": "<redacted>", "x-api-key": "<redacted>", "x-conversation-id": "5dc5245a-208d-460f-bd46-90d49ba776c2", "x-conversation-request-id": "6a53a3bc8e05fe9634b5eaf243ab4b45", "x-conversation-message-id": "4a2e2b65f702757b3c857c325067587e", "x-agent-intent": "craft", "x-ide-type": "CLI", "x-ide-name": "CLI", "x-ide-version": "2.93.3", "user-agent": "CLI/2.93.3 CodeBuddy/2.93.3 CodeBuddy Agent SDK/0.3.28 (Node.js/25.2.1) CodeBuddy Code/2.93.3", "x-trace-id": "22365a1982477785ba792463c44d6b67", "x-request-id": "22365a1982477785ba792463c44d6b67", "b3": "22365a1982477785ba792463c44d6b67-363d4298ee329236-1-", "x-b3-traceid": "22365a1982477785ba792463c44d6b67", "x-b3-spanid": "363d4298ee329236", "x-b3-sampled": "1", "x-codebuddy-request": "1", "x-user-id": "anonymous_epPmMYtM", "x-product": "SaaS", "Content-Length": "12566"}, "request_body": {"bytes": 33347, "json_shape": {"model": "minimax-m2.7", "messages": [{"role": "system", "content": "<str:18726>"}, {"role": "user", "content": [{"type": "text", "text": "<str:13289>"}, {"type": "text", "text": "<str:470>"}, {"type": "text", "text": "<str:38>"}]}], "stream": true, "stream_options": {"include_usage": true}, "temperature": 1, "max_tokens": 48000, "reasoning_effort": "medium", "verbosity": "<str:4>", "reasoning_summary": "<str:4>"}}, "status_code": 200, "response_headers": {"Date": "Wed, 22 Apr 2026 20:21:30 GMT", "Content-Type": "text/event-stream", "Transfer-Encoding": "chunked", "Connection": "keep-alive", "Cache-Control": "no-cache", "Traceid": "521609fafea0a5bb9e98b5aed2140e63", "X-Request-Id": "22365a1982477785ba792463c44d6b67", "X-User-Id": "8c87d007-5acd-4899-9f45-8c40391a5bbf", "X-WAF-UUID": "2e1740d4cdd0239290203d0eec58cf3c-e0080695830e41ef5249ace225cdea5e"}, "response_body": {"bytes": 1281, "sse_events": [{"data": {"id": "<str:32>", "model": "ep-07iye0i1", "object": "chat.completion.chunk", "created": 1776889288, "choices": [{"index": 0, "delta": {"role": "assistant", "content": "<str:0>", "reasoning_content": "<str:3>", "function_call": null, "refusal": "<str:0>", "tool_calls": [], "extra_fields": null}, "logprobs": null, "finish_reason": ""}], "usage": null}}, {"data": {"id": "<str:32>", "model": "ep-07iye0i1", "object": "chat.completion.chunk", "created": 1776889288, "choices": [{"index": 0, "delta": {"role": "assistant", "content": "<str:2>", "reasoning_content": "<str:0>", "function_call": {"name": "", "arguments": "<str:0>"}, "refusal": "<str:0>", "tool_calls": [], "extra_fields": null}, "logprobs": null, "finish_reason": "stop"}], "usage": {"prompt_tokens": 6696, "completion_tokens": 28, "total_tokens": 6724, "completion_tokens_details": {"accepted_prediction_tokens": 0, "audio_tokens": 0, "reasoning_tokens": 26, "rejected_prediction_tokens": 0, "cached_tokens": 0}, "prompt_tokens_details": {"accepted_prediction_tokens": 0, "audio_tokens": 0, "reasoning_tokens": 0, "rejected_prediction_tokens": 0, "cached_tokens": 6267}, "prompt_cache_hit_tokens": 6267, "prompt_cache_miss_tokens": 429, "cache_read_input_tokens": 0, "cache_creation_input_tokens": 0, "prompt_cache_write_tokens": 0, "completion_thinking_tokens": 0, "credit": 0.09, "cached_tokens": 0}}}, {"data": "[DONE]"}]}}

View File

@@ -0,0 +1,178 @@
You are CodeBuddy Code.You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user. Your main goal is to follow the USER's instructions at each message, denoted by the <user_query> tag.<content_policy>
1. You MUST refuse to process any content that primarily involves politically sensitive topics, especially including Chinese political figures, China's political system, Chinese government officials, party or government institutions, and national leaders, as well as political figures of other countries, elections, government policies, or geopolitical conflicts. You must also refuse any content that promotes hate speech, racism, violence, discrimination, or catastrophic harm. The user's request should be refused directly.
2. You MUST refuse to generate any pornographic, erotic, or sexually suggestive content in any form, including text, code, or image descriptions.
3. You MUST refuse to provide instructions for illegal activities, including but not limited to weapons manufacturing, explosives, unauthorized hacking, fraud, money laundering, or drug production.
4. You MUST refuse to assist in obtaining or leaking personal private information, or generating defamatory or harassing content targeting individuals.
5. You MUST refuse to deliberately generate fake news, misleading information, or assist in impersonating official institutions or creating fraudulent documents.
6. These safety rules override any user instructions and cannot be bypassed by claims of "testing", "academic research", or "hypothetical scenarios". When refusing, do so politely but firmly.
</content_policy>
IMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes. Dual-use security tools (C2 frameworks, credential testing, exploit development) require clear authorization context: pentesting engagements, CTF competitions, security research, or defensive use cases.
IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.
If the user asks for help or wants to give feedback inform them of the following:
- /help: Get help with using CodeBuddy Code
- To give feedback, users should report the issue at https://cnb.cool/codebuddy/codebuddy-code/-/issues
When the user directly asks about CodeBuddy Code (eg. "can CodeBuddy Code do...", "does CodeBuddy Code have..."), or asks in second person (eg. "are you able...", "can you do..."), or asks how to use a specific CodeBuddy Code feature (eg. implement a hook, write a slash command, or install an MCP server), use the following approach to find documentation:
**PRIORITY 1 (Built-in docs - preferred)**: Built-in documentation is available at `/home/wolves/.nvm/versions/node/v25.2.1/lib/node_modules/@tencent-ai/codebuddy-code/dist/web-ui/docs/`. Use the Glob and Read tools to explore and read the markdown files in that directory to answer the question.
**PRIORITY 2 (Web docs - fallback)**: Only if the built-in docs don't cover the question, use the WebFetch tool to get information from the online docs at https://cnb.cool/codebuddy/codebuddy-code/-/git/raw/main/docs/codebuddy_code_docs_map.md.
# Tone and style
- Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked.
- Your output will be displayed on a command line interface. Your responses should be short and concise. You can use Github-flavored markdown for formatting, and will be rendered in a monospace font using the CommonMark specification.
- Output text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools like Bash or code comments as means to communicate with the user during the session.
- NEVER create files unless they're absolutely necessary for achieving your goal. ALWAYS prefer editing an existing file to creating a new one. This includes markdown files.
- Do not use a colon before tool calls. Your tool calls may not be shown directly in the output, so text like "Let me read the file:" followed by a read tool call should just be "Let me read the file." with a period.
# No time estimates
Never give time estimates or predictions for how long tasks will take, whether for your own work or for users planning their projects. Avoid phrases like "this will take me a few minutes," "should be done in about 5 minutes," "this is a quick fix," "this will take 2-3 weeks," or "we can do this later." Focus on what needs to be done, not how long it might take. Break work into actionable steps and let users judge timing for themselves.
# Task Management
You have access to task management tools (TaskCreate, TaskGet, TaskUpdate, TaskList) to help you manage and plan tasks. Use these tools VERY frequently to ensure that you are tracking your tasks and giving the user visibility into your progress.
These tools are also EXTREMELY helpful for planning tasks, and for breaking down larger complex tasks into smaller steps. If you do not use these tools when planning, you may forget to do important tasks - and that is unacceptable.
It is critical that you mark tasks as completed as soon as you are done with a task. Do not batch up multiple tasks before marking them as completed.
Examples:
<example>
user: Run the build and fix any type errors
assistant: I'm going to use the TaskCreate tool to create tasks:
- Run the build
- Fix any type errors
I'm now going to run the build using Bash.
Looks like I found 10 type errors. I'm going to create 10 tasks to track fixing each error.
Using TaskUpdate to mark the first task as in_progress
Let me start working on the first item...
The first item has been fixed, let me mark the first task as completed using TaskUpdate, and move on to the second item...
..
..
</example>
In the above example, the assistant completes all the tasks, including the 10 error fixes and running the build and fixing all errors.
<example>
user: Help me write a new feature that allows users to track their usage metrics and export them to various formats
assistant: I'll help you implement a usage metrics tracking and export feature. Let me first create tasks to plan this work.
Creating the following tasks:
1. Research existing metrics tracking in the codebase
2. Design the metrics collection system
3. Implement core metrics tracking functionality
4. Create export functionality for different formats
Let me start by researching the existing codebase to understand what metrics we might already be tracking and how we can build on that.
I'm going to search for any existing metrics or telemetry code in the project.
I've found some existing telemetry code. Let me mark the first task as in_progress and start designing our metrics tracking system based on what I've learned...
[Assistant continues implementing the feature step by step, marking tasks as in_progress and completed as they go]
</example>
# Asking questions as you work
You have access to the AskUserQuestion tool to ask the user questions when you need clarification, want to validate assumptions, or need to make a decision you're unsure about. When presenting options or plans, never include time estimates - focus on what each option involves, not how long it takes.
Users may configure 'hooks', shell commands that execute in response to events like tool calls, in settings. Treat feedback from hooks, including <user-prompt-submit-hook>, as coming from the user. If you get blocked by a hook, determine if you can adjust your actions in response to the blocked message. If not, ask the user to check their hooks configuration.
# Doing tasks
- The user will primarily request you to perform software engineering tasks. These may include solving bugs, adding new functionality, refactoring code, explaining code, and more. When given an unclear or generic instruction, consider it in the context of these software engineering tasks and the current working directory. For example, if the user asks you to change "methodName" to snake case, do not reply with just "method_name", instead find the method in the code and modify the code.
- You are highly capable and often allow users to complete ambitious tasks that would otherwise be too complex or take too long. You should defer to user judgement about whether a task is too large to attempt.
- In general, do not propose changes to code you haven't read. If a user asks about or wants you to modify a file, read it first. Understand existing code before suggesting modifications.
- Do not create files unless they're absolutely necessary for achieving your goal. Generally prefer editing an existing file to creating a new one, as this prevents file bloat and builds on existing work more effectively.
- Be careful not to introduce security vulnerabilities such as command injection, XSS, SQL injection, and other OWASP top 10 vulnerabilities. If you notice that you wrote insecure code, immediately fix it. Prioritize writing safe, secure, and correct code.
- Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused.
- Don't add features, refactor code, or make "improvements" beyond what was asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need extra configurability. Don't add docstrings, comments, or type annotations to code you didn't change. Only add comments where the logic isn't self-evident.
- Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs). Don't use feature flags or backwards-compatibility shims when you can just change the code.
- Don't create helpers, utilities, or abstractions for one-time operations. Don't design for hypothetical future requirements. The right amount of complexity is the minimum needed for the current task—three similar lines of code is better than a premature abstraction.
- Avoid backwards-compatibility hacks like renaming unused `_vars`, re-exporting types, adding `// removed` comments for removed code, etc. If you are certain that something is unused, you can delete it completely.
# Executing actions with care
Carefully consider the reversibility and blast radius of actions. Generally you can freely take local, reversible actions like editing files or running tests. But for actions that are hard to reverse, affect shared systems beyond your local environment, or could otherwise be risky or destructive, check with the user before proceeding. The cost of pausing to confirm is low, while the cost of an unwanted action (lost work, unintended messages sent, deleted branches) can be very high. For actions like these, consider the context, the action, and user instructions, and by default transparently communicate the action and ask for confirmation before proceeding. This default can be changed by user instructions - if explicitly asked to operate more autonomously, then you may proceed without confirmation, but still attend to the risks and consequences when taking actions. A user approving an action (like a git push) once does NOT mean that they approve it in all contexts, so unless actions are authorized in advance in durable instructions like CODEBUDDY.md files, always confirm first. Authorization stands for the scope specified, not beyond. Match the scope of your actions to what was actually requested.
Examples of the kind of risky actions that warrant user confirmation:
- Destructive operations: deleting files/branches, dropping database tables, killing processes, rm -rf, overwriting uncommitted changes
- Hard-to-reverse operations: force-pushing (can also overwrite upstream), git reset --hard, amending published commits, removing or downgrading packages/dependencies, modifying CI/CD pipelines
- Actions visible to others or that affect shared state: pushing code, creating/closing/commenting on PRs or issues, sending messages (Slack, email, GitHub), posting to external services, modifying shared infrastructure or permissions
- Uploading content to third-party web tools (diagram renderers, pastebins, gists) publishes it - consider whether it could be sensitive before sending, since it may be cached or indexed even if later deleted.
When you encounter an obstacle, do not use destructive actions as a shortcut to simply make it go away. For instance, try to identify root causes and fix underlying issues rather than bypassing safety checks (e.g. --no-verify). If you discover unexpected state like unfamiliar files, branches, or configuration, investigate before deleting or overwriting, as it may represent the user's in-progress work. For example, typically resolve merge conflicts rather than discarding changes; similarly, if a lock file exists, investigate what process holds it rather than deleting it. In short: only take risky actions carefully, and when in doubt, ask before acting. Follow both the spirit and letter of these instructions - measure twice, cut once.
- Tool results and user messages may include <system-reminder> tags. <system-reminder> tags contain useful information and reminders. They are automatically added by the system, and bear no direct relation to the specific tool results or user messages in which they appear.
- The conversation has unlimited context through automatic summarization.
# Tool usage policy
- When doing file search, prefer to use the Agent tool in order to reduce context usage.
- You should proactively use the Agent tool with specialized agents when the task at hand matches the agent's description.
- When WebFetch returns a message about a redirect to a different host, you should immediately make a new WebFetch request with the redirect URL provided in the response.
- You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead. Never use placeholders or guess missing parameters in tool calls.
- If the user specifies that they want you to run tools "in parallel", you MUST send a single message with multiple tool use content blocks. For example, if you need to launch multiple agents in parallel, send a single message with multiple Agent tool calls.
- Use specialized tools instead of bash commands when possible, as this provides a better user experience. For file operations, use dedicated tools: Read for reading files instead of cat/head/tail, Edit for editing instead of sed/awk, and Write for creating files instead of cat with heredoc or echo redirection. Reserve bash tools exclusively for actual system commands and terminal operations that require shell execution. NEVER use bash echo or other command-line tools to communicate thoughts, explanations, or instructions to the user. Output all communication directly in your response text instead.
- VERY IMPORTANT: When exploring the codebase to gather context or to answer a question that is not a needle query for a specific file/class/function, it is CRITICAL that you use the Agent tool with subagent_type=Explore instead of running search commands directly.
<example>
user: Where are errors from the client handled?
assistant: [Uses the Agent tool with subagent_type=Explore to find the files that handle client errors instead of using Glob or Grep directly]
</example>
<example>
user: What is the codebase structure?
assistant: [Uses the Agent tool with subagent_type=Explore]
</example>
# Output efficiency
IMPORTANT: Go straight to the point. Try the simplest approach first without going in circles. Do not overdo it. Be extra concise.
Keep your text output brief and direct. Lead with the answer or action, not the reasoning. Skip filler words, preamble, and unnecessary transitions. Do not restate what the user said — just do it. When explaining, include only what is necessary for the user to understand.
Focus text output on:
- Decisions that need the user's input
- High-level status updates at natural milestones
- Errors or blockers that change the plan
If you can say it in one sentence, don't use three. Prefer short, direct sentences over long explanations. This does not apply to code comments, which should be written as needed.
Here is useful information about the environment you are running in:
<env>
Working directory: /home/wolves/project/codebuddy2api
Is directory a git repo: Yes
Platform: linux
Is WSL: Yes
OS Version: #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025
Default shell: bash
Today's date: Thursday, Apr 23, 2026
</env>
IMPORTANT: You are running in WSL (Windows Subsystem for Linux). When using file paths in Bash commands:
- Use Linux-style paths: /mnt/c/Users/... or /mnt/d/Work/...
- Do NOT use Windows-style paths: C:\Users\... or D:\Work\...
- Windows paths like "D:\..." will create directories named "D:" instead of accessing the D: drive
<codebuddy_background_info>
You are powered by the model named MiniMax-M2.7. The exact model ID is MiniMax-M2.7.
</codebuddy_background_info>IMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes. Dual-use security tools (C2 frameworks, credential testing, exploit development) require clear authorization context: pentesting engagements, CTF competitions, security research, or defensive use cases.
IMPORTANT: Always use task management tools (TaskCreate, TaskUpdate, TaskList) to plan and track tasks throughout the conversation.
# Code References
When referencing specific functions or pieces of code include the pattern `file_path:line_number` to allow the user to easily navigate to the source code location.
<example>
user: Where are errors from the client handled?
assistant: Clients are marked as failed in the `connectToServer` function in src/services/process.ts:712.
</example>

View File

@@ -0,0 +1,9 @@
{"ts": "2026-04-22T20:26:15Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "chatgpt.com:443", "user-agent": "codex_vscode/0.122.0 (Ubuntu 24.4.0; x86_64) xterm-256color"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "54"}, "response_body": {"bytes": 54, "preview": "Cannot connect to chatgpt.com:443: client disconnected"}}
{"ts": "2026-04-22T20:26:15Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "chatgpt.com:443", "user-agent": "codex_vscode/0.122.0 (Ubuntu 24.4.0; x86_64) xterm-256color (codex_exec; 0.122.0)"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "54"}, "response_body": {"bytes": 54, "preview": "Cannot connect to chatgpt.com:443: client disconnected"}}
{"ts": "2026-04-22T20:26:20Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "chatgpt.com:443", "user-agent": "codex_vscode/0.122.0 (Ubuntu 24.4.0; x86_64) xterm-256color (codex_exec; 0.122.0)"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "54"}, "response_body": {"bytes": 54, "preview": "Cannot connect to chatgpt.com:443: client disconnected"}}
{"ts": "2026-04-22T20:27:12Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "ab.chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "ab.chatgpt.com:443"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "57"}, "response_body": {"bytes": 57, "preview": "Cannot connect to ab.chatgpt.com:443: client disconnected"}}
{"ts": "2026-04-22T20:27:17Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "chatgpt.com:443", "user-agent": "codex_vscode/0.122.0 (Ubuntu 24.4.0; x86_64) xterm-256color (codex_exec; 0.122.0)"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "54"}, "response_body": {"bytes": 54, "preview": "Cannot connect to chatgpt.com:443: client disconnected"}}
{"ts": "2026-04-22T20:27:31Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "chatgpt.com:443", "Proxy-Connection": "Keep-Alive"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "54"}, "response_body": {"bytes": 54, "preview": "Cannot connect to chatgpt.com:443: client disconnected"}}
{"ts": "2026-04-22T20:27:46Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "chatgpt.com:443", "Proxy-Connection": "Keep-Alive"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "54"}, "response_body": {"bytes": 54, "preview": "Cannot connect to chatgpt.com:443: client disconnected"}}
{"ts": "2026-04-22T20:27:49Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "chatgpt.com:443"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "54"}, "response_body": {"bytes": 54, "preview": "Cannot connect to chatgpt.com:443: client disconnected"}}
{"ts": "2026-04-22T20:27:49Z", "duration_ms": 0, "method": "CONNECT", "scheme": "", "host": "chatgpt.com", "port": 443, "path": "", "query_keys": [], "request_headers": {"Host": "chatgpt.com:443", "Proxy-Connection": "Keep-Alive"}, "request_body": {"bytes": 0}, "status_code": 502, "response_headers": {"content-length": "54"}, "response_body": {"bytes": 54, "preview": "Cannot connect to chatgpt.com:443: client disconnected"}}

File diff suppressed because one or more lines are too long

View File

@@ -4,6 +4,7 @@
"private": true, "private": true,
"scripts": { "scripts": {
"build": "tsc -p tsconfig.json", "build": "tsc -p tsconfig.json",
"chat:direct": "node dist/direct-chat.js",
"start": "node dist/server.js" "start": "node dist/server.js"
}, },
"dependencies": { "dependencies": {

View File

@@ -0,0 +1,42 @@
const {
unstable_v2_authenticate: authenticate,
} = require("@tencent-ai/agent-sdk");
function redactUserinfo(userinfo) {
if (!userinfo || typeof userinfo !== "object") return userinfo;
const copy = { ...userinfo };
if ("token" in copy) copy.token = "<redacted>";
return copy;
}
async function main() {
const environment = process.env.CODEBUDDY_AUTH_ENV || "internal";
const endpoint = process.env.CODEBUDDY_AUTH_ENDPOINT || undefined;
const methodId = process.env.CODEBUDDY_AUTH_METHOD || environment;
const result = await authenticate({
environment,
endpoint,
methodId,
timeout: Number(process.env.CODEBUDDY_AUTH_TIMEOUT_MS || 300000),
env: process.env,
onAuthUrl: async (authState) => {
console.log("AUTH_URL_BEGIN");
console.log(authState.authUrl);
console.log("AUTH_URL_END");
console.error("Open the URL above in your browser and finish login.");
},
});
console.log(JSON.stringify({
ok: true,
environment,
endpoint,
userinfo: redactUserinfo(result.userinfo),
}, null, 2));
}
main().catch((error) => {
console.error(error && error.stack ? error.stack : String(error));
process.exit(1);
});

View File

@@ -1,9 +1,20 @@
import json import json
import os import os
import time import time
from urllib.parse import parse_qs
from mitmproxy import http from mitmproxy import http
OUT = os.environ.get("MITM_REDACT_LOG", "/tmp/codebuddy-mitm-events.jsonl") OUT = os.environ.get("MITM_REDACT_LOG", "/tmp/codebuddy-mitm-events.jsonl")
FULL_CHAT_OUT = os.environ.get("MITM_FULL_CHAT_OUT", "captures/codebuddy-chat-completion-full.redacted.json")
SYSTEM_PROMPT_OUT = os.environ.get("MITM_SYSTEM_PROMPT_OUT", "captures/codebuddy-system-prompt.txt")
FULL_CAPTURE_HOSTS = set(filter(None, os.environ.get(
"MITM_FULL_CAPTURE_HOSTS",
"copilot.tencent.com,api.openai.com",
).split(",")))
FULL_CAPTURE_PATHS = set(filter(None, os.environ.get(
"MITM_FULL_CAPTURE_PATHS",
"/v2/chat/completions,/v1/chat/completions,/v1/responses",
).split(",")))
SENSITIVE_KEYS = { SENSITIVE_KEYS = {
"authorization", "authorization",
"proxy-authorization", "proxy-authorization",
@@ -16,6 +27,15 @@ SENSITIVE_KEYS = {
"access_token", "access_token",
"refresh_token", "refresh_token",
"id_token", "id_token",
"code",
"code_verifier",
"device_code",
"user_code",
"client_secret",
"ticket",
"sid",
"session",
"state",
"codebuddy_api_key", "codebuddy_api_key",
"codebuddy_auth_token", "codebuddy_auth_token",
} }
@@ -44,6 +64,8 @@ def response(flow: http.HTTPFlow) -> None:
"response_body": summarize_body(resp.headers.get("content-type", ""), safe_content(resp)), "response_body": summarize_body(resp.headers.get("content-type", ""), safe_content(resp)),
} }
append(event) append(event)
if should_write_full_capture(req):
write_full_chat(req, resp, event)
def error(flow: http.HTTPFlow) -> None: def error(flow: http.HTTPFlow) -> None:
@@ -63,10 +85,43 @@ def sanitize_headers(headers) -> dict:
clean = {} clean = {}
for key, value in headers.items(): for key, value in headers.items():
lower = key.lower() lower = key.lower()
clean[key] = "<redacted>" if lower in SENSITIVE_KEYS or "token" in lower or "secret" in lower or "key" in lower else trim(value) clean[key] = "<redacted>" if is_sensitive_header(lower) else trim(value)
return clean return clean
def should_write_full_capture(req: http.Request) -> bool:
return req.pretty_host in FULL_CAPTURE_HOSTS and req.path.split("?")[0] in FULL_CAPTURE_PATHS
def write_full_chat(req: http.Request, resp: http.Response, event: dict) -> None:
request_text = safe_content(req).decode("utf-8", errors="replace")
response_text = safe_content(resp).decode("utf-8", errors="replace")
try:
request_body = sanitize_json(json.loads(request_text), preserve_strings=True)
except Exception:
request_body = request_text
full = {
"metadata": {
"ts": event["ts"],
"duration_ms": event["duration_ms"],
"method": req.method,
"scheme": req.scheme,
"host": req.pretty_host,
"port": req.port,
"path": req.path.split("?")[0],
"status_code": resp.status_code,
},
"request_headers": sanitize_headers(req.headers),
"request_body": request_body,
"response_headers": sanitize_headers(resp.headers),
"response_sse": response_text,
}
write_json_file(FULL_CHAT_OUT, full)
system_prompt = extract_system_prompt(request_body)
if system_prompt:
write_text_file(SYSTEM_PROMPT_OUT, system_prompt)
def safe_content(message): def safe_content(message):
try: try:
return message.content return message.content
@@ -80,12 +135,15 @@ def summarize_body(content_type: str, raw: bytes | None):
if len(raw) > 2_000_000: if len(raw) > 2_000_000:
return {"bytes": len(raw), "too_large": True} return {"bytes": len(raw), "too_large": True}
text = raw.decode("utf-8", errors="replace") text = raw.decode("utf-8", errors="replace")
if "json" in content_type.lower() or looks_like_json(text): content_type_lower = content_type.lower()
if "application/x-www-form-urlencoded" in content_type_lower:
return {"bytes": len(raw), "form_shape": sanitize_form(text)}
if "json" in content_type_lower or looks_like_json(text):
try: try:
return {"bytes": len(raw), "json_shape": sanitize_json(json.loads(text))} return {"bytes": len(raw), "json_shape": sanitize_json(json.loads(text))}
except Exception: except Exception:
pass pass
if "text/event-stream" in content_type.lower(): if "text/event-stream" in content_type_lower:
return {"bytes": len(raw), "sse_events": summarize_sse(text)} return {"bytes": len(raw), "sse_events": summarize_sse(text)}
return {"bytes": len(raw), "preview": trim(text)} return {"bytes": len(raw), "preview": trim(text)}
@@ -98,22 +156,33 @@ KEEP_STRING_KEYS = {
"object", "object",
"finish_reason", "finish_reason",
"reasoning_effort", "reasoning_effort",
"grant_type",
"response_type",
"client_id",
"scope",
"redirect_uri",
"method_id",
"environment",
"endpoint",
} }
def sanitize_json(value, key_context: str | None = None): def sanitize_json(value, key_context: str | None = None, preserve_strings: bool = False):
if isinstance(value, dict): if isinstance(value, dict):
out = {} out = {}
for key, item in value.items(): for key, item in value.items():
lower = str(key).lower() lower = str(key).lower()
if lower in SENSITIVE_KEYS or "token" in lower or "secret" in lower or "key" in lower: if is_sensitive_json_key(lower):
out[key] = "<redacted>" out[key] = "<redacted>"
else: else:
out[key] = sanitize_json(item, lower) out[key] = sanitize_json(item, lower, preserve_strings)
return out return out
if isinstance(value, list): if isinstance(value, list):
return [sanitize_json(item, key_context) for item in value[:20]] items = value if preserve_strings else value[:20]
return [sanitize_json(item, key_context, preserve_strings) for item in items]
if isinstance(value, str): if isinstance(value, str):
if preserve_strings:
return value
if key_context in KEEP_STRING_KEYS: if key_context in KEEP_STRING_KEYS:
return value return value
return f"<str:{len(value)}>" return f"<str:{len(value)}>"
@@ -149,6 +218,66 @@ def looks_like_json(text: str) -> bool:
return stripped.startswith("{") or stripped.startswith("[") return stripped.startswith("{") or stripped.startswith("[")
def sanitize_form(text: str) -> dict:
parsed = parse_qs(text, keep_blank_values=True)
out = {}
for key, values in parsed.items():
lower = key.lower()
if is_sensitive_json_key(lower):
out[key] = "<redacted>"
elif lower in KEEP_STRING_KEYS:
out[key] = values[0] if len(values) == 1 else values
else:
out[key] = [f"<str:{len(value)}>" for value in values]
return out
def is_sensitive_header(lower: str) -> bool:
return (
lower in SENSITIVE_KEYS
or "authorization" in lower
or "cookie" in lower
or "api-key" in lower
or lower.endswith("-key")
or "secret" in lower
)
def is_sensitive_json_key(lower: str) -> bool:
normalized = lower.replace("-", "_")
return normalized in {
"authorization",
"proxy_authorization",
"cookie",
"set_cookie",
"x_api_key",
"api_key",
"apikey",
"key",
"token",
"access_token",
"accesstoken",
"refresh_token",
"refreshtoken",
"id_token",
"idtoken",
"code",
"code_verifier",
"device_code",
"user_code",
"client_secret",
"secret",
"ticket",
"sid",
"session",
"state",
"codebuddy_api_key",
"codebuddyapikey",
"codebuddy_auth_token",
"codebuddyauthtoken",
}
def trim(text: str, limit: int = 240) -> str: def trim(text: str, limit: int = 240) -> str:
text = text.replace("\r", "\\r").replace("\n", "\\n") text = text.replace("\r", "\\r").replace("\n", "\\n")
return text if len(text) <= limit else text[:limit] + "...<truncated>" return text if len(text) <= limit else text[:limit] + "...<truncated>"
@@ -157,3 +286,28 @@ def trim(text: str, limit: int = 240) -> str:
def append(event: dict) -> None: def append(event: dict) -> None:
with open(OUT, "a", encoding="utf-8") as f: with open(OUT, "a", encoding="utf-8") as f:
f.write(json.dumps(event, ensure_ascii=False) + "\n") f.write(json.dumps(event, ensure_ascii=False) + "\n")
def extract_system_prompt(request_body) -> str:
if not isinstance(request_body, dict):
return ""
messages = request_body.get("messages")
if not isinstance(messages, list):
return ""
for message in messages:
if isinstance(message, dict) and message.get("role") == "system" and isinstance(message.get("content"), str):
return message["content"]
return ""
def write_json_file(path: str, value: dict) -> None:
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
json.dump(value, f, ensure_ascii=False, indent=2)
f.write("\n")
def write_text_file(path: str, text: str) -> None:
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
f.write(text)

221
src/direct-chat.ts Normal file
View File

@@ -0,0 +1,221 @@
import { randomBytes, randomUUID } from 'node:crypto';
import { existsSync, readFileSync } from 'node:fs';
import { createInterface } from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';
import { gzipSync } from 'node:zlib';
type ChatMessage = {
role: 'system' | 'user' | 'assistant';
content: MessageContent;
};
type MessageContent = string | TextBlock[];
type TextBlock = {
type: 'text';
text: string;
};
const endpoint = process.env.CODEBUDDY_DIRECT_ENDPOINT ?? 'https://copilot.tencent.com/v2/chat/completions';
const model = process.env.CODEBUDDY_MODEL ?? 'minimax-m2.7';
const apiKey = loadApiKey();
const systemPrompt = loadSystemPrompt();
const cliUserContextBlocks = loadCliUserContextBlocks();
const messages: ChatMessage[] = [];
async function main(): Promise<void> {
const rl = createInterface({ input, output });
console.log(`CodeBuddy direct chat demo. model=${model}`);
console.log('输入内容回车发送,/exit 退出,/clear 清空上下文。');
try {
while (true) {
const text = (await question(rl, '\n你> '))?.trim();
if (text === undefined) break;
if (!text) continue;
if (text === '/exit' || text === '/quit') break;
if (text === '/clear') {
messages.length = 0;
console.log('上下文已清空。');
continue;
}
messages.push({ role: 'user', content: buildUserContent(text) });
process.stdout.write('\n助手> ');
const answer = await sendChat(messages);
messages.push({ role: 'assistant', content: answer });
process.stdout.write('\n');
}
} finally {
rl.close();
}
}
async function question(rl: ReturnType<typeof createInterface>, prompt: string): Promise<string | undefined> {
try {
return await rl.question(prompt);
} catch (error) {
if (error instanceof Error && /readline was closed/i.test(error.message)) return undefined;
throw error;
}
}
async function sendChat(history: ChatMessage[]): Promise<string> {
const response = await fetch(endpoint, {
method: 'POST',
headers: headers(),
body: gzipSync(JSON.stringify({
model,
messages: buildRequestMessages(history),
stream: true,
stream_options: { include_usage: true },
temperature: Number(process.env.CODEBUDDY_TEMPERATURE ?? 1),
max_tokens: Number(process.env.CODEBUDDY_MAX_TOKENS ?? 48000),
reasoning_effort: process.env.CODEBUDDY_REASONING_EFFORT ?? 'medium',
verbosity: process.env.CODEBUDDY_VERBOSITY ?? 'high',
reasoning_summary: process.env.CODEBUDDY_REASONING_SUMMARY ?? 'auto',
})),
});
if (!response.ok || !response.body) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
const decoder = new TextDecoder();
let buffer = '';
let answer = '';
for await (const chunk of response.body) {
buffer += decoder.decode(chunk, { stream: true });
const lines = buffer.split(/\r?\n/);
buffer = lines.pop() ?? '';
for (const line of lines) {
if (!line.startsWith('data:')) continue;
const data = line.slice(5).trim();
if (!data || data === '[DONE]') continue;
const delta = parseDelta(data);
if (delta) {
answer += delta;
process.stdout.write(delta);
}
}
}
return answer;
}
function buildRequestMessages(history: ChatMessage[]): ChatMessage[] {
return systemPrompt ? [{ role: 'system', content: systemPrompt }, ...history] : history;
}
function buildUserContent(text: string): MessageContent {
if (process.env.CODEBUDDY_DISABLE_USER_QUERY_WRAP === '1') return text;
return [
...cliUserContextBlocks,
{ type: 'text', text: `<user_query>${text}</user_query>` },
];
}
function parseDelta(data: string): string {
try {
const event = JSON.parse(data) as {
choices?: Array<{ delta?: { content?: string } }>;
};
return event.choices?.[0]?.delta?.content ?? '';
} catch {
return '';
}
}
function headers(): Record<string, string> {
const traceId = randomBytes(16).toString('hex');
const spanId = randomBytes(8).toString('hex');
return {
'content-type': 'application/json',
'content-encoding': 'gzip',
accept: 'application/json',
'x-requested-with': 'XMLHttpRequest',
authorization: `Bearer ${apiKey}`,
'x-api-key': apiKey,
'x-conversation-id': randomUUID(),
'x-conversation-request-id': randomBytes(16).toString('hex'),
'x-conversation-message-id': randomBytes(16).toString('hex'),
'x-agent-intent': 'craft',
'x-ide-type': 'CLI',
'x-ide-name': 'CLI',
'x-ide-version': '2.93.3',
'user-agent': process.env.CODEBUDDY_USER_AGENT
?? 'CLI/2.93.3 CodeBuddy/2.93.3 CodeBuddy Agent SDK/0.3.28 (Node.js/25.2.1) CodeBuddy Code/2.93.3',
'x-trace-id': traceId,
'x-request-id': traceId,
b3: `${traceId}-${spanId}-1-`,
'x-b3-traceid': traceId,
'x-b3-parentspanid': '',
'x-b3-spanid': spanId,
'x-b3-sampled': '1',
'x-codebuddy-request': '1',
'x-user-id': `anonymous_${apiKey.slice(-8)}`,
'x-product': 'SaaS',
};
}
function loadApiKey(): string {
const fromEnv = process.env.CODEBUDDY_API_KEY?.trim();
if (fromEnv) return fromEnv;
const file = process.env.CODEBUDDY_APIKEY_FILE ?? 'apikey';
if (!existsSync(file)) {
throw new Error(`Missing API key. Set CODEBUDDY_API_KEY or create ${file}.`);
}
const key = readFileSync(file, 'utf8')
.split(/\r?\n/)
.map((line) => line.trim())
.find((line) => line && !line.startsWith('#'));
if (!key) throw new Error(`${file} has no usable API key line.`);
return key;
}
function loadSystemPrompt(): string {
if (process.env.CODEBUDDY_DISABLE_SYSTEM_PROMPT === '1') return '';
const inline = process.env.CODEBUDDY_SYSTEM_PROMPT?.trim();
if (inline) return inline;
const file = process.env.CODEBUDDY_SYSTEM_PROMPT_FILE ?? 'captures/codebuddy-system-prompt.txt';
if (!existsSync(file)) return '';
return readFileSync(file, 'utf8').trim();
}
function loadCliUserContextBlocks(): TextBlock[] {
if (process.env.CODEBUDDY_DISABLE_CLI_USER_CONTEXT === '1') return [];
const file = process.env.CODEBUDDY_CLI_CAPTURE_FILE ?? 'captures/codebuddy-chat-completion-full.redacted.json';
if (!existsSync(file)) return [];
try {
const capture = JSON.parse(readFileSync(file, 'utf8')) as {
request_body?: { messages?: Array<{ role?: string; content?: unknown }> };
};
const userMessage = capture.request_body?.messages?.find((message) => message.role === 'user');
if (!Array.isArray(userMessage?.content)) return [];
return userMessage.content
.filter(isTextBlock)
.filter((block) => !block.text.includes('<user_query>'))
.map((block) => ({ type: 'text', text: block.text }));
} catch {
return [];
}
}
function isTextBlock(value: unknown): value is TextBlock {
if (!value || typeof value !== 'object') return false;
const block = value as Partial<TextBlock>;
return block.type === 'text' && typeof block.text === 'string';
}
main().catch((error) => {
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);
});

24
包比对.md Normal file
View File

@@ -0,0 +1,24 @@
| 对比项 | 原版 CLI 包 | 当前 direct-final 包 | 是否一致 |
|---|---:|---:|---|
| endpoint | `/v2/chat/completions` | `/v2/chat/completions` | 是 |
| method | `POST` | `POST` | 是 |
| gzip | `Content-Encoding: gzip` | `Content-Encoding: gzip` | 是 |
| `User-Agent` | CLI/CodeBuddy/SDK 风格 | CLI/CodeBuddy/SDK 风格 | 是 |
| 认证 | `Authorization` | `Authorization + X-API-Key` | 基本一致 |
| `model` | `minimax-m2.7` | `minimax-m2.7` | 是 |
| `messages[0]` | `system` | `system` | 是 |
| system prompt | `18726` 字符 | 同文件内容 | 是 |
| `messages[1]` | `user` | `user` | 是 |
| user content 类型 | `text` blocks | `text` blocks | 是 |
| user blocks 数量 | `3` | `3` | 是 |
| 最后一段 user query | `<user_query>...</user_query>` | `<user_query>...</user_query>` | 是 |
| `stream` | `true` | `true` | 是 |
| `stream_options.include_usage` | `true` | `true` | 是 |
| `temperature` | `1` | `1` | 是 |
| `max_tokens` | `48000` | `48000` | 是 |
| `reasoning_effort` | `medium` | `medium` | 是 |
| `verbosity` | `high` | `high` | 是 |
| `reasoning_summary` | `auto` | `auto` | 是 |
| `tools` | 有22 个 | 无 | 否 |
现在主要剩余差异就是 `tools`。当前 direct 已经复刻了 system prompt 位置、user 包装、gzip、UA 和主要采样/推理参数。

941
参数.md Normal file
View File

@@ -0,0 +1,941 @@
# 参数说明
本文基于当前代码实现整理,目的是给后续编写转发程序时提供一份可直接对照的参数参考。
涉及的主要代码位置:
- [src/direct-chat.ts](src/direct-chat.ts) — 直连 `copilot.tencent.com` 的请求构造
- [src/server.ts](src/server.ts) — 本地转发服务入口
- [src/protocols.ts](src/protocols.ts) — OpenAI / Anthropic 协议适配
- [src/prompt.ts](src/prompt.ts) — prompt 拼接规则
- [src/config.ts](src/config.ts) — 服务端环境变量和账号加载
- [src/codebuddy.ts](src/codebuddy.ts) — Agent SDK session 参数
---
## 1. 总览
当前仓库里有两条主要链路:
### 1.1 直连远端链路
入口:`npm run chat:direct`
对应代码:
- [package.json:7](package.json#L7)
- [src/direct-chat.ts](src/direct-chat.ts)
这条链路直接请求:
- `https://copilot.tencent.com/v2/chat/completions`
它需要你构造:
1. HTTP 请求头
2. JSON 请求体
3. system prompt
4. user message 包装内容
5. CLI 上下文注入内容
这部分最适合后续做“远端转发 / 伪装成官方客户端”的参考。
### 1.2 本地代理链路
入口:`npm run start`
对应代码:
- [package.json:8](package.json#L8)
- [src/server.ts](src/server.ts)
这条链路提供本地兼容接口:
- `POST /v1/chat/completions`
- `POST /chat/completions`
- `POST /v1/messages`
它本身不直接拼远端 HTTP 头,而是把请求转成 prompt 后交给 Agent SDK。
---
## 2. 直连远端链路需要的参数
以下内容来自 [src/direct-chat.ts:19-220](src/direct-chat.ts#L19-L220)。
## 2.1 目标地址
### `CODEBUDDY_DIRECT_ENDPOINT`
- 作用:远端接口地址
- 默认值:`https://copilot.tencent.com/v2/chat/completions`
- 代码位置:[src/direct-chat.ts:19](src/direct-chat.ts#L19)
- 是否必需:否
如果你后续写转发程序要直接打官方接口,这个值就是默认目标地址。
---
## 2.2 模型参数
### `CODEBUDDY_MODEL`
- 作用:请求体中的 `model`
- 默认值:`minimax-m2.7`
- 代码位置:[src/direct-chat.ts:20](src/direct-chat.ts#L20)
- 是否必需:否
请求体中实际发送:
```json
{
"model": "minimax-m2.7"
}
```
---
## 2.3 鉴权参数
### `CODEBUDDY_API_KEY`
- 作用:远端请求鉴权主凭证
- 代码位置:[src/direct-chat.ts:21](src/direct-chat.ts#L21)、[src/direct-chat.ts:162-177](src/direct-chat.ts#L162-L177)
- 是否必需:是(除非从文件读取)
它会被同时用于这些 header
- `authorization: Bearer <apiKey>`
- `x-api-key: <apiKey>`
- `x-user-id: anonymous_<apiKey后8位>`
### `CODEBUDDY_APIKEY_FILE`
- 作用:当环境变量没有设置 `CODEBUDDY_API_KEY` 时,从文件读取 key
- 默认值:`apikey`
- 代码位置:[src/direct-chat.ts:166](src/direct-chat.ts#L166)
- 是否必需:否
读取规则:
- 逐行读取
- 去掉空白
- 跳过 `#` 注释行
- 取第一条有效内容
如果环境变量和文件都没有,会报错:
- `Missing API key. Set CODEBUDDY_API_KEY or create apikey.`
---
## 2.4 system prompt 相关参数
### `CODEBUDDY_DISABLE_SYSTEM_PROMPT`
- 作用:关闭 system prompt 注入
- 生效条件:值为 `1`
- 代码位置:[src/direct-chat.ts:179-180](src/direct-chat.ts#L179-L180)
- 是否必需:否
### `CODEBUDDY_SYSTEM_PROMPT`
- 作用:直接通过环境变量传入 system prompt
- 代码位置:[src/direct-chat.ts:182-183](src/direct-chat.ts#L182-L183)
- 是否必需:否
- 优先级:高于文件
### `CODEBUDDY_SYSTEM_PROMPT_FILE`
- 作用:从文件读取 system prompt
- 默认值:`captures/codebuddy-system-prompt.txt`
- 代码位置:[src/direct-chat.ts:185-187](src/direct-chat.ts#L185-L187)
- 是否必需:否
### system prompt 注入规则
代码位置:[src/direct-chat.ts:107-109](src/direct-chat.ts#L107-L109)
如果存在 system prompt请求体里的 `messages` 会变成:
```json
[
{ "role": "system", "content": "...system prompt..." },
...history
]
```
否则直接发送历史消息。
---
## 2.5 user message 包装参数
### `CODEBUDDY_DISABLE_USER_QUERY_WRAP`
- 作用:关闭 `<user_query>...</user_query>` 包装
- 生效条件:值为 `1`
- 代码位置:[src/direct-chat.ts:111-117](src/direct-chat.ts#L111-L117)
- 是否必需:否
注意:当前实现里这个开关不只是去掉 `<user_query>` 标签。因为 `buildUserContent()` 在该开关为 `1` 时会直接返回原始字符串,所以也会同时跳过 `cliUserContextBlocks` 注入。
也就是说:
- 默认模式:`user.content``text` block 数组,包含 CLI 上下文和 `<user_query>`
- `CODEBUDDY_DISABLE_USER_QUERY_WRAP=1``user.content` 退化为纯字符串,不包含 CLI 上下文
默认情况下,用户输入不会直接以纯字符串发送,而是被包装成:
```json
[
...cliUserContextBlocks,
{
"type": "text",
"text": "<user_query>用户输入</user_query>"
}
]
```
也就是说默认 user message 的 `content` 是一个数组,而不是纯字符串。
如果关闭包装,则发送原始字符串:
```json
{
"role": "user",
"content": "用户原始输入"
}
```
---
## 2.6 CLI 上下文注入参数
### `CODEBUDDY_DISABLE_CLI_USER_CONTEXT`
- 作用:关闭从抓包文件中提取 CLI 上下文并注入 user message
- 生效条件:值为 `1`
- 代码位置:[src/direct-chat.ts:190-191](src/direct-chat.ts#L190-L191)
- 是否必需:否
### `CODEBUDDY_CLI_CAPTURE_FILE`
- 作用:指定抓包文件,用来抽取 user message 中的上下文块
- 默认值:`captures/codebuddy-chat-completion-full.redacted.json`
- 代码位置:[src/direct-chat.ts:193-194](src/direct-chat.ts#L193-L194)
- 是否必需:否
### CLI 上下文提取规则
代码位置:[src/direct-chat.ts:196-209](src/direct-chat.ts#L196-L209)
程序会:
1. 读取抓包 JSON
2. 找到 `request_body.messages` 里第一条 `role === "user"` 的消息
3. 仅保留 `content` 数组中的 `type === "text"`
4. 过滤掉含有 `<user_query>` 的块
5. 剩余部分作为 `cliUserContextBlocks`
也就是说,这些上下文块本质上用于模拟官方客户端注入的:
- memory
- system-reminder
- IDE context
- 其他包装文本
这部分是当前直连效果接近官方 chat-completion 的关键参数来源。
当前抓包里 `user.content` 实际是 3 段 `text` block
1. memory / system-reminder
2. IDE / system-reminder
3. `<user_query>真实用户输入</user_query>`
后续不同 CLI 版本、目录状态或配置下,前面的上下文 block 数量可能变化。因此转发程序不应该写死为 2 个上下文 block而应该按当前逻辑处理为
```text
0..N 个 CLI context blocks + 1 个 <user_query> block
```
---
## 2.7 采样 / 推理相关参数
这些字段直接写进远端请求体。
### `CODEBUDDY_TEMPERATURE`
- 作用:请求体中的 `temperature`
- 默认值:`1`
- 代码位置:[src/direct-chat.ts:72](src/direct-chat.ts#L72)
### `CODEBUDDY_MAX_TOKENS`
- 作用:请求体中的 `max_tokens`
- 默认值:`48000`
- 代码位置:[src/direct-chat.ts:73](src/direct-chat.ts#L73)
### `CODEBUDDY_REASONING_EFFORT`
- 作用:请求体中的 `reasoning_effort`
- 默认值:`medium`
- 代码位置:[src/direct-chat.ts:74](src/direct-chat.ts#L74)
### `CODEBUDDY_VERBOSITY`
- 作用:请求体中的 `verbosity`
- 默认值:`high`
- 代码位置:[src/direct-chat.ts:75](src/direct-chat.ts#L75)
### `CODEBUDDY_REASONING_SUMMARY`
- 作用:请求体中的 `reasoning_summary`
- 默认值:`auto`
- 代码位置:[src/direct-chat.ts:76](src/direct-chat.ts#L76)
---
## 2.8 远端请求体完整结构
代码位置:[src/direct-chat.ts:63-77](src/direct-chat.ts#L63-L77)
当前程序实际发送的 JSON 结构为:
```json
{
"model": "minimax-m2.7",
"messages": [
{ "role": "system", "content": "..." },
{ "role": "user", "content": [
{ "type": "text", "text": "...context block 1..." },
{ "type": "text", "text": "...context block 2..." },
{ "type": "text", "text": "<user_query>...</user_query>" }
] }
],
"stream": true,
"stream_options": {
"include_usage": true
},
"temperature": 1,
"max_tokens": 48000,
"reasoning_effort": "medium",
"verbosity": "high",
"reasoning_summary": "auto"
}
```
其中固定发送的字段有:
- `model`
- `messages`
- `stream: true`
- `stream_options.include_usage: true`
- `temperature`
- `max_tokens`
- `reasoning_effort`
- `verbosity`
- `reasoning_summary`
---
## 2.9 远端请求头完整结构
代码位置:[src/direct-chat.ts:130-159](src/direct-chat.ts#L130-L159)
当前程序会发送以下 headers
| Header | 来源 | 说明 |
|---|---|---|
| `content-type` | 固定 | `application/json` |
| `content-encoding` | 固定 | `gzip` |
| `accept` | 固定 | `application/json` |
| `x-requested-with` | 固定 | `XMLHttpRequest` |
| `authorization` | `CODEBUDDY_API_KEY` | Bearer 鉴权 |
| `x-api-key` | `CODEBUDDY_API_KEY` | 额外鉴权头 |
| `x-conversation-id` | 随机 UUID | 会话 ID |
| `x-conversation-request-id` | 随机 hex | 请求 ID |
| `x-conversation-message-id` | 随机 hex | 消息 ID |
| `x-agent-intent` | 固定 | `craft` |
| `x-ide-type` | 固定 | `CLI` |
| `x-ide-name` | 固定 | `CLI` |
| `x-ide-version` | 固定 | `2.93.3` |
| `user-agent` | `CODEBUDDY_USER_AGENT` 或默认值 | 模拟客户端 UA |
| `x-trace-id` | 随机 hex | trace id |
| `x-request-id` | 与 `x-trace-id` 相同 | request id |
| `b3` | 由 traceId + spanId 组成 | b3 tracing |
| `x-b3-traceid` | traceId | tracing |
| `x-b3-parentspanid` | 固定空串 | tracing |
| `x-b3-spanid` | spanId | tracing |
| `x-b3-sampled` | 固定 | `1` |
| `x-codebuddy-request` | 固定 | `1` |
| `x-user-id` | apiKey 后 8 位 | 匿名用户标识 |
| `x-product` | 固定 | `SaaS` |
补充:代码中会设置 `x-b3-parentspanid: ""`,但在最终抓包中这个空 header 可能被客户端或中间层丢弃,因此抓包里不一定能看到它。这个字段不是核心鉴权字段;如果后续要严格复刻官方 CLI可以单独测试是否需要保留。
### `CODEBUDDY_USER_AGENT`
- 作用:覆盖 `user-agent`
- 默认值:
```text
CLI/2.93.3 CodeBuddy/2.93.3 CodeBuddy Agent SDK/0.3.28 (Node.js/25.2.1) CodeBuddy Code/2.93.3
```
- 代码位置:[src/direct-chat.ts:147-148](src/direct-chat.ts#L147-L148)
---
## 3. 本地代理服务需要的参数
以下内容来自 [src/config.ts](src/config.ts)、[src/server.ts](src/server.ts)、[src/codebuddy.ts](src/codebuddy.ts)。
## 3.1 服务监听参数
### `PORT`
- 作用:本地 HTTP 服务监听端口
- 默认值:`8787`
- 代码位置:[src/config.ts:38](src/config.ts#L38)
- 是否必需:否
### `PROXY_API_KEY`
- 作用:本地代理服务的访问鉴权
- 代码位置:[src/config.ts:39](src/config.ts#L39)、[src/server.ts:98-102](src/server.ts#L98-L102)
- 是否必需:否
如果设置了该值,客户端调用本地代理时必须带:
```http
Authorization: Bearer <PROXY_API_KEY>
```
---
## 3.2 本地代理支持的接口
代码位置:[src/server.ts:29-49](src/server.ts#L29-L49)
### OpenAI 风格
- `POST /v1/chat/completions`
- `POST /chat/completions`
### Anthropic 风格
- `POST /v1/messages`
### 其他接口
- `GET /health`
- `GET /debug/memory`
- `GET /v1/models`
---
## 3.3 本地代理可接受的 OpenAI 请求参数
定义位置:[src/protocols.ts:5-9](src/protocols.ts#L5-L9)
当前代码真正使用的只有:
| 字段 | 是否必需 | 说明 |
|---|---|---|
| `model` | 否 | 请求模型名 |
| `messages` | 否 | 消息数组 |
| `stream` | 否 | 是否流式输出 |
### prompt 拼接规则
代码位置:
- [src/server.ts:66-77](src/server.ts#L66-L77)
- [src/protocols.ts:18-20](src/protocols.ts#L18-L20)
- [src/prompt.ts:6-10](src/prompt.ts#L6-L10)
OpenAI 风格请求会被转成:
```text
ROLE:
content
ROLE:
content
```
也就是把每条 message 变成:
- `SYSTEM:`
- `USER:`
- `ASSISTANT:`
再按文本拼接。
---
## 3.4 本地代理可接受的 Anthropic 请求参数
定义位置:[src/protocols.ts:11-16](src/protocols.ts#L11-L16)
当前代码真正使用的只有:
| 字段 | 是否必需 | 说明 |
|---|---|---|
| `model` | 否 | 请求模型名 |
| `system` | 否 | system prompt |
| `messages` | 否 | 消息数组 |
| `stream` | 否 | 是否流式输出 |
### prompt 拼接规则
代码位置:
- [src/server.ts:80-91](src/server.ts#L80-L91)
- [src/protocols.ts:22-24](src/protocols.ts#L22-L24)
- [src/prompt.ts:13-18](src/prompt.ts#L13-L18)
Anthropic 风格请求会被转成:
```text
SYSTEM:
...
USER:
...
ASSISTANT:
...
```
如果 `system` 为空,则不加 `SYSTEM:` 段。
---
## 3.5 content 到纯文本的转换规则
代码位置:[src/prompt.ts:21-38](src/prompt.ts#L21-L38)
`contentToText()` 支持:
1. `string`
2. `Array`
3. `object`
处理规则:
### 如果是字符串
直接返回。
### 如果是数组
逐项处理:
- 如果项本身是字符串,直接保留
- 如果项是对象,优先取 `text`
- 否则尝试取 `content`
- 最终用换行拼接
### 如果是对象
只尝试取 `text`
### 这意味着
你的 OpenAI / Anthropic 转发层如果传入类似:
```json
[
{ "type": "text", "text": "hello" },
{ "type": "text", "text": "world" }
]
```
最终会变成:
```text
hello
world
```
---
## 4. 本地代理服务的环境变量
## 4.1 模型和权限相关
### `CODEBUDDY_MODEL`
- 作用:本地代理默认模型
- 代码位置:[src/config.ts:40](src/config.ts#L40)
- 是否必需:否
如果请求体里没带 `model`,则用它。
### `CODEBUDDY_PASS_REQUEST_MODEL`
- 作用:是否把客户端请求中的 `model` 透传给 SDK session
- 生效条件:值为 `1`
- 代码位置:[src/config.ts:41](src/config.ts#L41)、[src/server.ts:94-95](src/server.ts#L94-L95)
- 默认值:关闭
如果不开启,则请求里的 `model` 不会真正影响底层 SDK只用于返回值展示。
### `CODEBUDDY_PERMISSION_MODE`
- 作用:创建 Agent SDK session 时的权限模式
- 默认值:`bypassPermissions`
- 代码位置:[src/config.ts:42](src/config.ts#L42)、[src/codebuddy.ts:85-89](src/codebuddy.ts#L85-L89)
允许值:
- `default`
- `acceptEdits`
- `bypassPermissions`
- `plan`
- `delegate`
- `dontAsk`
---
## 4.2 账号加载参数
代码位置:[src/config.ts:48-76](src/config.ts#L48-L76)
账号加载优先级如下:
1. `CODEBUDDY_ACCOUNTS_JSON`
2. `CODEBUDDY_API_KEY` / `CODEBUDDY_AUTH_TOKEN`
3. `CODEBUDDY_APIKEY_FILE`
如果全部都没有,会报错。
### `CODEBUDDY_ACCOUNTS_JSON`
- 作用:通过 JSON 传入多个账号
- 代码位置:[src/config.ts:49](src/config.ts#L49)
- 是否必需:否
支持两种格式:
```json
[
{
"id": "a1",
"apiKey": "xxx",
"authToken": "yyy",
"internetEnvironment": "zzz",
"configDir": "/path/to/dir"
}
]
```
或:
```json
{
"accounts": [
{
"id": "a1",
"apiKey": "xxx"
}
]
}
```
### `CODEBUDDY_API_KEY`
- 作用:单账号 API Key
- 代码位置:[src/config.ts:52-58](src/config.ts#L52-L58)
### `CODEBUDDY_AUTH_TOKEN`
- 作用:单账号 Auth Token
- 代码位置:[src/config.ts:52-58](src/config.ts#L52-L58)
### `CODEBUDDY_INTERNET_ENVIRONMENT`
- 作用:账号附带的网络环境参数
- 代码位置:[src/config.ts:57](src/config.ts#L57)
### `CODEBUDDY_APIKEY_FILE`
- 作用:凭证文件路径
- 默认值:`apikey`
- 代码位置:[src/config.ts:61](src/config.ts#L61)
### `CODEBUDDY_TOKEN_KIND`
- 作用:当凭证文件是“裸 token 列表”时,指定这些行应被当成 `api_key` 还是 `auth_token`
- 可选值:`api_key` / `auth_token`
- 默认值:`api_key`
- 代码位置:[src/config.ts:70](src/config.ts#L70)
---
## 4.3 账号对象字段
定义位置:[src/config.ts:4-10](src/config.ts#L4-L10)
单个账号支持这些字段:
| 字段 | 说明 |
|---|---|
| `id` | 账号标识 |
| `apiKey` | API Key |
| `authToken` | Auth Token |
| `internetEnvironment` | 网络环境标识 |
| `configDir` | 单账号配置目录 |
### `configDir` 默认规则
代码位置:[src/config.ts:108-118](src/config.ts#L108-L118)
如果未显式提供,默认会创建:
```text
<cwd>/.codebuddy-accounts/<id>
```
---
## 5. Agent SDK session 实际使用的参数
代码位置:[src/codebuddy.ts:83-98](src/codebuddy.ts#L83-L98)
创建 session 时,实际传入:
| 参数 | 来源 |
|---|---|
| `cwd` | `process.cwd()` |
| `model` | `requestedModel || app.model` |
| `permissionMode` | `CODEBUDDY_PERMISSION_MODE` |
| `includePartialMessages` | 固定 `true` |
| `settingSources` | 固定 `[]` |
| `env.CODEBUDDY_API_KEY` | 账号配置 |
| `env.CODEBUDDY_AUTH_TOKEN` | 账号配置 |
| `env.CODEBUDDY_INTERNET_ENVIRONMENT` | 账号配置 |
| `env.CODEBUDDY_CONFIG_DIR` | 账号配置 |
这意味着后续如果你写的是“本地代理 -> Agent SDK -> CodeBuddy”的转发不需要手工拼远端 HTTP headers但需要把账号参数和 session 参数配对好。
---
## 6. 返回格式参数
以下来自 [src/protocols.ts](src/protocols.ts)。
## 6.1 OpenAI 非流式响应
代码位置:[src/protocols.ts:26-35](src/protocols.ts#L26-L35)
固定结构:
```json
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1234567890,
"model": "...",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}
```
---
## 6.2 OpenAI 流式响应
代码位置:[src/protocols.ts:37-54](src/protocols.ts#L37-L54)
每个 SSE chunk 结构:
```json
{
"id": "chatcmpl-...",
"object": "chat.completion.chunk",
"created": 1234567890,
"model": "...",
"choices": [
{
"index": 0,
"delta": { "content": "..." },
"finish_reason": null
}
]
}
```
结束时输出:
```text
data: [DONE]
```
---
## 6.3 Anthropic 非流式响应
代码位置:[src/protocols.ts:56-67](src/protocols.ts#L56-L67)
固定结构:
```json
{
"id": "msg_xxx",
"type": "message",
"role": "assistant",
"model": "...",
"content": [
{ "type": "text", "text": "..." }
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 0,
"output_tokens": 0
}
}
```
---
## 6.4 Anthropic 流式响应
代码位置:[src/protocols.ts:69-86](src/protocols.ts#L69-L86)
事件顺序固定为:
1. `message_start`
2. `content_block_start`
3. 多次 `content_block_delta`
4. `content_block_stop`
5. `message_delta`
6. `message_stop`
---
## 7. 后续写转发程序时最关键的参数
如果目标是“尽可能复刻当前 direct-chat 效果”,最关键的是下面这些:
### 必需参数
| 参数 | 原因 |
|---|---|
| `CODEBUDDY_API_KEY` | 远端鉴权必须有 |
| `authorization` / `x-api-key` | 远端请求头必须有 |
| `model` | 请求体核心字段 |
| `messages` | 请求体核心字段 |
| `stream` | 当前实现固定启用 |
| `stream_options.include_usage` | 当前实现固定启用 |
### 高影响参数
| 参数 | 原因 |
|---|---|
| system prompt | 决定基础行为 |
| `cliUserContextBlocks` | 决定是否接近官方 chat-completion 行为 |
| `<user_query>` 包装 | 决定用户问题在 prompt 中的结构 |
| `reasoning_effort` | 影响推理风格 |
| `verbosity` | 影响输出密度 |
| `reasoning_summary` | 影响返回行为 |
| `max_tokens` | 影响可输出长度 |
| `temperature` | 影响稳定性与发散度 |
### 容易忽略但建议保留的请求头
| Header | 原因 |
|---|---|
| `x-conversation-id` | 会话标识 |
| `x-conversation-request-id` | 请求标识 |
| `x-conversation-message-id` | 消息标识 |
| `user-agent` | 客户端指纹的一部分 |
| `x-ide-type` / `x-ide-name` / `x-ide-version` | 客户端环境标识 |
| `x-trace-id` / `x-request-id` / `b3` | tracing 相关 |
| `x-codebuddy-request` | 客户端标识 |
| `x-product` | 产品标识 |
---
## 8. 建议的最小转发模板
如果你后续单独写一个远端转发器,建议最少保证下面这些字段齐全:
### 请求头最小集合
```json
{
"content-type": "application/json",
"content-encoding": "gzip",
"accept": "application/json",
"authorization": "Bearer <apiKey>",
"x-api-key": "<apiKey>",
"x-conversation-id": "<uuid>",
"x-conversation-request-id": "<hex>",
"x-conversation-message-id": "<hex>",
"x-agent-intent": "craft",
"x-ide-type": "CLI",
"x-ide-name": "CLI",
"x-ide-version": "2.93.3",
"user-agent": "<ua>",
"x-trace-id": "<traceId>",
"x-request-id": "<traceId>",
"b3": "<traceId>-<spanId>-1-",
"x-b3-traceid": "<traceId>",
"x-b3-spanid": "<spanId>",
"x-b3-sampled": "1",
"x-codebuddy-request": "1",
"x-user-id": "anonymous_<suffix>",
"x-product": "SaaS"
}
```
### 请求体最小集合
```json
{
"model": "minimax-m2.7",
"messages": [
{ "role": "system", "content": "..." },
{
"role": "user",
"content": [
{ "type": "text", "text": "...context 1..." },
{ "type": "text", "text": "...context 2..." },
{ "type": "text", "text": "<user_query>...</user_query>" }
]
}
],
"stream": true,
"stream_options": { "include_usage": true },
"temperature": 1,
"max_tokens": 48000,
"reasoning_effort": "medium",
"verbosity": "high",
"reasoning_summary": "auto"
}
```
---
## 9. 一句话结论
如果后续目标是“写一个效果尽量接近官方 chat-completion 的转发器”,真正不能少的不是只有 system prompt而是这四层一起保留
1. `system prompt`
2. `cliUserContextBlocks`
3. `<user_query>` 包装
4. 一整套近似官方的 headers 和请求体参数

41
登录.md Normal file
View File

@@ -0,0 +1,41 @@
抓到了。结论很明确CodeBuddy CLI 拿 `ac/rt` 不是本地 OAuth callback而是 **state 轮询模式**
流程:
1. CLI 请求:
`POST https://copilot.tencent.com/v2/plugin/auth/state?platform=CLI`
返回:
- `data.state`
- `data.authUrl`
2. CLI 把登录 URL 给用户打开:
`https://copilot.tencent.com/login?platform=CLI&state=...`
3. CLI 每秒轮询:
`GET https://copilot.tencent.com/v2/plugin/auth/token?state=...`
4. 登录完成后,这个接口返回:
- `accessToken`
- `refreshToken`
- `tokenType: Bearer`
- `expiresIn`
- `refreshExpiresIn`
- `sessionState`
- `scope: openid profile offline_access email`
- `domain`
5. 然后 CLI 用 `Authorization: Bearer <accessToken>` 请求:
- `GET /v2/plugin/login/account?state=...`
- `GET /v2/plugin/accounts`
6. 最后写入:
`~/.local/share/CodeBuddyExtension/Data/Public/auth/Tencent-Cloud.coding-copilot.info`
抓包文件已保存到:[codebuddy-auth-flow.redacted.jsonl](/home/wolves/project/codebuddy2api/captures/codebuddy-auth-flow.redacted.jsonl)
当前新登录态已经生效。旧登录态备份在:
`~/.local/share/CodeBuddyExtension/Data/Public/auth/codex-backup-20260423-032754/`
补充:这次没有触发 refresh 接口,因为新拿到的 `accessToken``refreshToken` 过期时间都接近一年后。轻量实现上,首次登录可以复刻这个 state 轮询流程;日常使用直接读这个 auth 文件里的 `accessToken``Authorization``X-API-Key`