Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
46cb7ca5
Unverified
提交
46cb7ca5
authored
5月 02, 2025
作者:
Will Chen
提交者:
GitHub
5月 02, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
redo reverts code (when possible) (#75)
上级
5fc49231
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
49 行增加
和
2 行删除
+49
-2
ChatInput.tsx
src/components/chat/ChatInput.tsx
+4
-0
MessagesList.tsx
src/components/chat/MessagesList.tsx
+43
-2
app_handlers.ts
src/ipc/handlers/app_handlers.ts
+1
-0
ipc_types.ts
src/ipc/ipc_types.ts
+1
-0
没有找到文件。
src/components/chat/ChatInput.tsx
浏览文件 @
46cb7ca5
...
@@ -53,6 +53,7 @@ import {
...
@@ -53,6 +53,7 @@ import {
TooltipTrigger
,
TooltipTrigger
,
}
from
"../ui/tooltip"
;
}
from
"../ui/tooltip"
;
import
{
useNavigate
}
from
"@tanstack/react-router"
;
import
{
useNavigate
}
from
"@tanstack/react-router"
;
import
{
useVersions
}
from
"@/hooks/useVersions"
;
const
showTokenBarAtom
=
atom
(
false
);
const
showTokenBarAtom
=
atom
(
false
);
...
@@ -61,6 +62,8 @@ export function ChatInput({ chatId }: { chatId?: number }) {
...
@@ -61,6 +62,8 @@ export function ChatInput({ chatId }: { chatId?: number }) {
const
[
inputValue
,
setInputValue
]
=
useAtom
(
chatInputValueAtom
);
const
[
inputValue
,
setInputValue
]
=
useAtom
(
chatInputValueAtom
);
const
textareaRef
=
useRef
<
HTMLTextAreaElement
>
(
null
);
const
textareaRef
=
useRef
<
HTMLTextAreaElement
>
(
null
);
const
{
settings
,
updateSettings
,
isAnyProviderSetup
}
=
useSettings
();
const
{
settings
,
updateSettings
,
isAnyProviderSetup
}
=
useSettings
();
const
appId
=
useAtomValue
(
selectedAppIdAtom
);
const
{
refreshVersions
}
=
useVersions
(
appId
);
const
{
streamMessage
,
isStreaming
,
setIsStreaming
,
error
,
setError
}
=
const
{
streamMessage
,
isStreaming
,
setIsStreaming
,
error
,
setError
}
=
useStreamChat
();
useStreamChat
();
const
[
showError
,
setShowError
]
=
useState
(
true
);
const
[
showError
,
setShowError
]
=
useState
(
true
);
...
@@ -162,6 +165,7 @@ export function ChatInput({ chatId }: { chatId?: number }) {
...
@@ -162,6 +165,7 @@ export function ChatInput({ chatId }: { chatId?: number }) {
}
finally
{
}
finally
{
setIsApproving
(
false
);
setIsApproving
(
false
);
setIsPreviewOpen
(
true
);
setIsPreviewOpen
(
true
);
refreshVersions
();
// Keep same as handleReject
// Keep same as handleReject
refreshProposal
();
refreshProposal
();
...
...
src/components/chat/MessagesList.tsx
浏览文件 @
46cb7ca5
...
@@ -9,6 +9,9 @@ import { selectedChatIdAtom } from "@/atoms/chatAtoms";
...
@@ -9,6 +9,9 @@ import { selectedChatIdAtom } from "@/atoms/chatAtoms";
import
{
useAtom
,
useAtomValue
}
from
"jotai"
;
import
{
useAtom
,
useAtomValue
}
from
"jotai"
;
import
{
RefreshCw
}
from
"lucide-react"
;
import
{
RefreshCw
}
from
"lucide-react"
;
import
{
Button
}
from
"@/components/ui/button"
;
import
{
Button
}
from
"@/components/ui/button"
;
import
{
useVersions
}
from
"@/hooks/useVersions"
;
import
{
selectedAppIdAtom
}
from
"@/atoms/appAtoms"
;
import
{
showError
}
from
"@/lib/toast"
;
interface
MessagesListProps
{
interface
MessagesListProps
{
messages
:
Message
[];
messages
:
Message
[];
...
@@ -17,6 +20,8 @@ interface MessagesListProps {
...
@@ -17,6 +20,8 @@ interface MessagesListProps {
export
const
MessagesList
=
forwardRef
<
HTMLDivElement
,
MessagesListProps
>
(
export
const
MessagesList
=
forwardRef
<
HTMLDivElement
,
MessagesListProps
>
(
function
MessagesList
({
messages
,
messagesEndRef
},
ref
)
{
function
MessagesList
({
messages
,
messagesEndRef
},
ref
)
{
const
appId
=
useAtomValue
(
selectedAppIdAtom
);
const
{
versions
,
revertVersion
}
=
useVersions
(
appId
);
const
{
streamMessage
,
isStreaming
,
error
,
setError
}
=
useStreamChat
();
const
{
streamMessage
,
isStreaming
,
error
,
setError
}
=
useStreamChat
();
const
{
isAnyProviderSetup
}
=
useSettings
();
const
{
isAnyProviderSetup
}
=
useSettings
();
const
selectedChatId
=
useAtomValue
(
selectedChatIdAtom
);
const
selectedChatId
=
useAtomValue
(
selectedChatIdAtom
);
...
@@ -39,11 +44,42 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>(
...
@@ -39,11 +44,42 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>(
<
Button
<
Button
variant=
"ghost"
variant=
"ghost"
size=
"sm"
size=
"sm"
onClick=
{
()
=>
{
onClick=
{
async
()
=>
{
if
(
!
selectedChatId
)
{
if
(
!
selectedChatId
)
{
console
.
error
(
"No chat selected"
);
console
.
error
(
"No chat selected"
);
return
;
return
;
}
}
// The last message is usually an assistant, but it might not be.
const
lastVersion
=
versions
[
0
];
const
lastMessage
=
messages
[
messages
.
length
-
1
];
let
reverted
=
false
;
if
(
lastVersion
.
oid
===
lastMessage
.
commitHash
&&
lastMessage
.
role
===
"assistant"
)
{
if
(
versions
.
length
<
2
)
{
showError
(
"Cannot retry message; no previous version"
);
return
;
}
const
previousAssistantMessage
=
messages
[
messages
.
length
-
3
];
if
(
previousAssistantMessage
?.
role
===
"assistant"
&&
previousAssistantMessage
?.
commitHash
)
{
console
.
debug
(
"Reverting to previous assistant version"
);
await
revertVersion
({
versionId
:
previousAssistantMessage
.
commitHash
,
});
reverted
=
true
;
}
else
{
console
.
debug
(
"Reverting to previous version"
);
await
revertVersion
({
versionId
:
versions
[
1
].
oid
,
});
}
}
// Find the last user message
// Find the last user message
const
lastUserMessage
=
[...
messages
]
const
lastUserMessage
=
[...
messages
]
.
reverse
()
.
reverse
()
...
@@ -52,10 +88,15 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>(
...
@@ -52,10 +88,15 @@ export const MessagesList = forwardRef<HTMLDivElement, MessagesListProps>(
console
.
error
(
"No user message found"
);
console
.
error
(
"No user message found"
);
return
;
return
;
}
}
// If we reverted, we don't need to mark "redo" because
// the old message has already been deleted.
const
redo
=
!
reverted
;
console
.
debug
(
"Streaming message with redo"
,
redo
);
streamMessage
({
streamMessage
({
prompt
:
lastUserMessage
.
content
,
prompt
:
lastUserMessage
.
content
,
chatId
:
selectedChatId
,
chatId
:
selectedChatId
,
redo
:
true
,
redo
,
});
});
}
}
}
}
>
>
...
...
src/ipc/handlers/app_handlers.ts
浏览文件 @
46cb7ca5
...
@@ -494,6 +494,7 @@ export function registerAppHandlers() {
...
@@ -494,6 +494,7 @@ export function registerAppHandlers() {
_
,
_
,
{
appId
,
previousVersionId
}:
{
appId
:
number
;
previousVersionId
:
string
}
{
appId
,
previousVersionId
}:
{
appId
:
number
;
previousVersionId
:
string
}
)
=>
{
)
=>
{
logger
.
log
(
`Reverting to version
${
previousVersionId
}
for app
${
appId
}
`
);
return
withLock
(
appId
,
async
()
=>
{
return
withLock
(
appId
,
async
()
=>
{
const
app
=
await
db
.
query
.
apps
.
findFirst
({
const
app
=
await
db
.
query
.
apps
.
findFirst
({
where
:
eq
(
apps
.
id
,
appId
),
where
:
eq
(
apps
.
id
,
appId
),
...
...
src/ipc/ipc_types.ts
浏览文件 @
46cb7ca5
...
@@ -41,6 +41,7 @@ export interface Message {
...
@@ -41,6 +41,7 @@ export interface Message {
role
:
"user"
|
"assistant"
;
role
:
"user"
|
"assistant"
;
content
:
string
;
content
:
string
;
approvalState
?:
"approved"
|
"rejected"
|
null
;
approvalState
?:
"approved"
|
"rejected"
|
null
;
commitHash
?:
string
|
null
;
}
}
export
interface
Chat
{
export
interface
Chat
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论