Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
92fb4f9b
Unverified
提交
92fb4f9b
authored
5月 16, 2025
作者:
Will Chen
提交者:
GitHub
5月 16, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
useful utility for debugging raw LLM response (#181)
Co-authored-by:
graphite-app[bot]
<
96075541+graphite-app[bot]@users.noreply.github.com
>
上级
9a288fd8
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
107 行增加
和
0 行删除
+107
-0
debug_fetch.ts
src/ipc/utils/debug_fetch.ts
+107
-0
没有找到文件。
src/ipc/utils/debug_fetch.ts
0 → 100644
浏览文件 @
92fb4f9b
import
log
from
"electron-log"
;
const
logger
=
log
.
scope
(
"debug-fetch"
);
interface
DebugFetchOptions
extends
RequestInit
{
debugTag
?:
string
;
logResponse
?:
boolean
;
logStream
?:
boolean
;
includeUsageInStream
?:
boolean
;
}
/**
* A debug-friendly fetch wrapper that logs requests and responses
* Particularly useful for debugging SSE streams
*/
export
async
function
debugFetch
(
url
:
RequestInfo
|
URL
,
options
:
DebugFetchOptions
=
{},
):
Promise
<
Response
>
{
const
{
debugTag
=
"fetch"
,
logResponse
=
true
,
logStream
=
true
,
...
fetchOptions
}
=
options
;
// Log the request
logger
.
info
(
`[
${
debugTag
}
] Request:`
,
{
url
,
method
:
fetchOptions
.
method
||
"GET"
,
headers
:
fetchOptions
.
headers
,
});
if
(
fetchOptions
.
body
&&
options
.
includeUsageInStream
)
{
fetchOptions
.
body
=
JSON
.
stringify
({
...
JSON
.
parse
(
fetchOptions
.
body
as
string
),
stream_options
:
{
include_usage
:
true
},
});
}
const
response
=
await
fetch
(
url
,
fetchOptions
);
// Log the initial response
logger
.
info
(
`[
${
debugTag
}
] Response:`
,
{
status
:
response
.
status
,
statusText
:
response
.
statusText
,
headers
:
Object
.
fromEntries
(
response
.
headers
.
entries
()),
});
// If it's not a stream or we don't want to log it, return as is
if
(
!
logResponse
||
!
response
.
body
)
{
return
response
;
}
// Clone the response so we can read it multiple times
const
clonedResponse
=
response
.
clone
();
// If it's a stream and we want to log it
if
(
logStream
&&
isEventStream
(
response
))
{
// Create a new ReadableStream that will log chunks as they come in
const
loggedBody
=
new
ReadableStream
({
async
start
(
controller
)
{
const
reader
=
clonedResponse
.
body
!
.
getReader
();
const
decoder
=
new
TextDecoder
();
try
{
while
(
true
)
{
const
{
done
,
value
}
=
await
reader
.
read
();
if
(
done
)
break
;
const
chunk
=
decoder
.
decode
(
value
,
{
stream
:
true
});
logger
.
info
(
`[
${
debugTag
}
] Stream chunk:`
,
chunk
);
controller
.
enqueue
(
value
);
}
controller
.
close
();
}
catch
(
error
)
{
logger
.
error
(
`[
${
debugTag
}
] Stream error:`
,
error
);
controller
.
error
(
error
);
}
},
});
// Return a new response with our logged body
return
new
Response
(
loggedBody
,
{
headers
:
response
.
headers
,
status
:
response
.
status
,
statusText
:
response
.
statusText
,
});
}
// For non-stream responses, log the body if requested
if
(
logResponse
)
{
try
{
const
bodyText
=
await
clonedResponse
.
text
();
logger
.
info
(
`[
${
debugTag
}
] Response body:`
,
bodyText
);
}
catch
(
error
)
{
logger
.
error
(
`[
${
debugTag
}
] Error reading response body:`
,
error
);
}
}
return
response
;
}
function
isEventStream
(
response
:
Response
):
boolean
{
const
contentType
=
response
.
headers
.
get
(
"content-type"
);
return
contentType
?.
includes
(
"text/event-stream"
)
||
false
;
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论