Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
b4b9556e
Unverified
提交
b4b9556e
authored
5月 19, 2025
作者:
Will Chen
提交者:
GitHub
5月 19, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add a keep going suggestion (#201)
上级
68cb6b3d
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
96 行增加
和
110 行删除
+96
-110
ChatInput.tsx
src/components/chat/ChatInput.tsx
+86
-108
proposal_handlers.ts
src/ipc/handlers/proposal_handlers.ts
+4
-1
schemas.ts
src/lib/schemas.ts
+6
-1
没有找到文件。
src/components/chat/ChatInput.tsx
浏览文件 @
b4b9556e
...
@@ -362,10 +362,39 @@ export function ChatInput({ chatId }: { chatId?: number }) {
...
@@ -362,10 +362,39 @@ export function ChatInput({ chatId }: { chatId?: number }) {
);
);
}
}
function
SuggestionButton
({
children
,
onClick
,
tooltipText
,
}:
{
onClick
:
()
=>
void
;
children
:
React
.
ReactNode
;
tooltipText
:
string
;
})
{
const
{
isStreaming
}
=
useStreamChat
();
return
(
<
TooltipProvider
>
<
Tooltip
>
<
TooltipTrigger
asChild
>
<
Button
disabled=
{
isStreaming
}
variant=
"outline"
size=
"sm"
onClick=
{
onClick
}
>
{
children
}
</
Button
>
</
TooltipTrigger
>
<
TooltipContent
>
{
tooltipText
}
</
TooltipContent
>
</
Tooltip
>
</
TooltipProvider
>
);
}
function
SummarizeInNewChatButton
()
{
function
SummarizeInNewChatButton
()
{
const
chatId
=
useAtomValue
(
selectedChatIdAtom
);
const
chatId
=
useAtomValue
(
selectedChatIdAtom
);
const
appId
=
useAtomValue
(
selectedAppIdAtom
);
const
appId
=
useAtomValue
(
selectedAppIdAtom
);
const
{
streamMessage
,
isStreaming
}
=
useStreamChat
();
const
{
streamMessage
}
=
useStreamChat
();
const
navigate
=
useNavigate
();
const
navigate
=
useNavigate
();
const
onClick
=
async
()
=>
{
const
onClick
=
async
()
=>
{
if
(
!
appId
)
{
if
(
!
appId
)
{
...
@@ -385,38 +414,19 @@ function SummarizeInNewChatButton() {
...
@@ -385,38 +414,19 @@ function SummarizeInNewChatButton() {
}
}
};
};
return
(
return
(
<
TooltipProvider
>
<
SuggestionButton
<
Tooltip
>
<
TooltipTrigger
asChild
>
<
Button
disabled=
{
isStreaming
}
variant=
"outline"
size=
"sm"
onClick=
{
onClick
}
onClick=
{
onClick
}
tooltipText=
"Creating a new chat makes the AI more focused and efficient"
>
>
Summarize to new chat
Summarize to new chat
</
Button
>
</
SuggestionButton
>
</
TooltipTrigger
>
<
TooltipContent
>
<
p
>
Creating a new chat makes the AI more focused and efficient
</
p
>
</
TooltipContent
>
</
Tooltip
>
</
TooltipProvider
>
);
);
}
}
function
RefactorFileButton
({
path
}:
{
path
:
string
})
{
function
RefactorFileButton
({
path
}:
{
path
:
string
})
{
const
chatId
=
useAtomValue
(
selectedChatIdAtom
);
const
chatId
=
useAtomValue
(
selectedChatIdAtom
);
const
{
streamMessage
,
isStreaming
}
=
useStreamChat
();
const
{
streamMessage
}
=
useStreamChat
();
return
(
const
onClick
=
()
=>
{
<
TooltipProvider
>
<
Tooltip
>
<
TooltipTrigger
asChild
>
<
Button
disabled=
{
isStreaming
}
variant=
"outline"
size=
"sm"
onClick=
{
()
=>
{
if
(
!
chatId
)
{
if
(
!
chatId
)
{
console
.
error
(
"No chat id found"
);
console
.
error
(
"No chat id found"
);
return
;
return
;
...
@@ -426,33 +436,23 @@ function RefactorFileButton({ path }: { path: string }) {
...
@@ -426,33 +436,23 @@ function RefactorFileButton({ path }: { path: string }) {
chatId
,
chatId
,
redo
:
false
,
redo
:
false
,
});
});
}
}
};
return
(
<
SuggestionButton
onClick=
{
onClick
}
tooltipText=
"Refactor the file to improve maintainability"
>
>
<
span
className=
"max-w-[180px] overflow-hidden whitespace-nowrap text-ellipsis"
>
<
span
className=
"max-w-[180px] overflow-hidden whitespace-nowrap text-ellipsis"
>
Refactor
{
path
.
split
(
"/"
).
slice
(
-
2
).
join
(
"/"
)
}
Refactor
{
path
.
split
(
"/"
).
slice
(
-
2
).
join
(
"/"
)
}
</
span
>
</
span
>
</
Button
>
</
SuggestionButton
>
</
TooltipTrigger
>
<
TooltipContent
>
<
p
>
Refactor
{
path
}
to improve maintainability
</
p
>
</
TooltipContent
>
</
Tooltip
>
</
TooltipProvider
>
);
);
}
}
function
WriteCodeProperlyButton
()
{
function
WriteCodeProperlyButton
()
{
const
chatId
=
useAtomValue
(
selectedChatIdAtom
);
const
chatId
=
useAtomValue
(
selectedChatIdAtom
);
const
{
streamMessage
,
isStreaming
}
=
useStreamChat
();
const
{
streamMessage
}
=
useStreamChat
();
return
(
const
onClick
=
()
=>
{
<
TooltipProvider
>
<
Tooltip
>
<
TooltipTrigger
asChild
>
<
Button
disabled=
{
isStreaming
}
variant=
"outline"
size=
"sm"
onClick=
{
()
=>
{
if
(
!
chatId
)
{
if
(
!
chatId
)
{
console
.
error
(
"No chat id found"
);
console
.
error
(
"No chat id found"
);
return
;
return
;
...
@@ -462,29 +462,23 @@ function WriteCodeProperlyButton() {
...
@@ -462,29 +462,23 @@ function WriteCodeProperlyButton() {
chatId
,
chatId
,
redo
:
false
,
redo
:
false
,
});
});
}
}
};
return
(
<
SuggestionButton
onClick=
{
onClick
}
tooltipText=
"Write code properly (useful when AI generates the code in the wrong format)"
>
>
Write code properly
Write code properly
</
Button
>
</
SuggestionButton
>
</
TooltipTrigger
>
<
TooltipContent
>
<
p
>
Write code properly (useful when AI generates the code in the wrong
format)
</
p
>
</
TooltipContent
>
</
Tooltip
>
</
TooltipProvider
>
);
);
}
}
function
RebuildButton
()
{
function
RebuildButton
()
{
const
{
restartApp
}
=
useRunApp
();
const
{
restartApp
}
=
useRunApp
();
const
{
isStreaming
}
=
useStreamChat
();
const
posthog
=
usePostHog
();
const
posthog
=
usePostHog
();
const
selectedAppId
=
useAtomValue
(
selectedAppIdAtom
);
const
selectedAppId
=
useAtomValue
(
selectedAppIdAtom
);
const
handleRebuild
=
useCallback
(
async
()
=>
{
const
onClick
=
useCallback
(
async
()
=>
{
if
(
!
selectedAppId
)
return
;
if
(
!
selectedAppId
)
return
;
posthog
.
capture
(
"action:rebuild"
);
posthog
.
capture
(
"action:rebuild"
);
...
@@ -492,33 +486,18 @@ function RebuildButton() {
...
@@ -492,33 +486,18 @@ function RebuildButton() {
},
[
selectedAppId
,
posthog
,
restartApp
]);
},
[
selectedAppId
,
posthog
,
restartApp
]);
return
(
return
(
<
TooltipProvider
>
<
SuggestionButton
onClick=
{
onClick
}
tooltipText=
"Rebuild the application"
>
<
Tooltip
>
<
TooltipTrigger
asChild
>
<
Button
disabled=
{
isStreaming
}
variant=
"outline"
size=
"sm"
onClick=
{
handleRebuild
}
>
Rebuild app
Rebuild app
</
Button
>
</
SuggestionButton
>
</
TooltipTrigger
>
<
TooltipContent
>
<
p
>
Rebuild the application
</
p
>
</
TooltipContent
>
</
Tooltip
>
</
TooltipProvider
>
);
);
}
}
function
RestartButton
()
{
function
RestartButton
()
{
const
{
isStreaming
}
=
useStreamChat
();
const
{
restartApp
}
=
useRunApp
();
const
{
restartApp
}
=
useRunApp
();
const
posthog
=
usePostHog
();
const
posthog
=
usePostHog
();
const
selectedAppId
=
useAtomValue
(
selectedAppIdAtom
);
const
selectedAppId
=
useAtomValue
(
selectedAppIdAtom
);
const
handleRestart
=
useCallback
(
async
()
=>
{
const
onClick
=
useCallback
(
async
()
=>
{
if
(
!
selectedAppId
)
return
;
if
(
!
selectedAppId
)
return
;
posthog
.
capture
(
"action:restart"
);
posthog
.
capture
(
"action:restart"
);
...
@@ -526,54 +505,51 @@ function RestartButton() {
...
@@ -526,54 +505,51 @@ function RestartButton() {
},
[
selectedAppId
,
posthog
,
restartApp
]);
},
[
selectedAppId
,
posthog
,
restartApp
]);
return
(
return
(
<
TooltipProvider
>
<
SuggestionButton
<
Tooltip
>
onClick=
{
onClick
}
<
TooltipTrigger
asChild
>
tooltipText=
"Restart the development server"
<
Button
disabled=
{
isStreaming
}
variant=
"outline"
size=
"sm"
onClick=
{
handleRestart
}
>
>
Restart app
Restart app
</
Button
>
</
SuggestionButton
>
</
TooltipTrigger
>
<
TooltipContent
>
<
p
>
Restart the development server
</
p
>
</
TooltipContent
>
</
Tooltip
>
</
TooltipProvider
>
);
);
}
}
function
RefreshButton
()
{
function
RefreshButton
()
{
const
{
refreshAppIframe
}
=
useRunApp
();
const
{
refreshAppIframe
}
=
useRunApp
();
const
{
isStreaming
}
=
useStreamChat
();
const
posthog
=
usePostHog
();
const
posthog
=
usePostHog
();
const
handleRefresh
=
useCallback
(()
=>
{
const
onClick
=
useCallback
(()
=>
{
posthog
.
capture
(
"action:refresh"
);
posthog
.
capture
(
"action:refresh"
);
refreshAppIframe
();
refreshAppIframe
();
},
[
posthog
,
refreshAppIframe
]);
},
[
posthog
,
refreshAppIframe
]);
return
(
return
(
<
TooltipProvider
>
<
SuggestionButton
<
Tooltip
>
onClick=
{
onClick
}
<
TooltipTrigger
asChild
>
tooltipText=
"Refresh the application preview"
<
Button
disabled=
{
isStreaming
}
variant=
"outline"
size=
"sm"
onClick=
{
handleRefresh
}
>
>
Refresh app
Refresh app
</
Button
>
</
SuggestionButton
>
</
TooltipTrigger
>
);
<
TooltipContent
>
}
<
p
>
Refresh the application preview
</
p
>
</
TooltipContent
>
function
KeepGoingButton
()
{
</
Tooltip
>
const
{
streamMessage
}
=
useStreamChat
();
</
TooltipProvider
>
const
chatId
=
useAtomValue
(
selectedChatIdAtom
);
const
onClick
=
()
=>
{
if
(
!
chatId
)
{
console
.
error
(
"No chat id found"
);
return
;
}
streamMessage
({
prompt
:
"Keep going"
,
chatId
,
});
};
return
(
<
SuggestionButton
onClick=
{
onClick
}
tooltipText=
"Keep going"
>
Keep going
</
SuggestionButton
>
);
);
}
}
...
@@ -591,6 +567,8 @@ function mapActionToButton(action: SuggestedAction) {
...
@@ -591,6 +567,8 @@ function mapActionToButton(action: SuggestedAction) {
return
<
RestartButton
/>;
return
<
RestartButton
/>;
case
"refresh"
:
case
"refresh"
:
return
<
RefreshButton
/>;
return
<
RefreshButton
/>;
case
"keep-going"
:
return
<
KeepGoingButton
/>;
default
:
default
:
console
.
error
(
`Unsupported action:
${
action
.
id
}
`
);
console
.
error
(
`Unsupported action:
${
action
.
id
}
`
);
return
(
return
(
...
@@ -603,8 +581,8 @@ function mapActionToButton(action: SuggestedAction) {
...
@@ -603,8 +581,8 @@ function mapActionToButton(action: SuggestedAction) {
function
ActionProposalActions
({
proposal
}:
{
proposal
:
ActionProposal
})
{
function
ActionProposalActions
({
proposal
}:
{
proposal
:
ActionProposal
})
{
return
(
return
(
<
div
className=
"border-b border-border p-2 flex items-center justify-between"
>
<
div
className=
"border-b border-border p-2
pb-0
flex items-center justify-between"
>
<
div
className=
"flex items-center space-x-2"
>
<
div
className=
"flex items-center space-x-2
overflow-x-auto pb-2
"
>
{
proposal
.
actions
.
map
((
action
)
=>
mapActionToButton
(
action
))
}
{
proposal
.
actions
.
map
((
action
)
=>
mapActionToButton
(
action
))
}
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/ipc/handlers/proposal_handlers.ts
浏览文件 @
b4b9556e
...
@@ -297,7 +297,10 @@ const getProposalHandler = async (
...
@@ -297,7 +297,10 @@ const getProposalHandler = async (
});
});
}
}
}
}
if
(
actions
.
length
>
0
&&
latestAssistantMessage
)
{
if
(
latestAssistantMessage
)
{
actions
.
push
({
id
:
"keep-going"
,
});
return
{
return
{
proposal
:
{
proposal
:
{
type
:
"action-proposal"
,
type
:
"action-proposal"
,
...
...
src/lib/schemas.ts
浏览文件 @
b4b9556e
...
@@ -166,7 +166,8 @@ export type SuggestedAction =
...
@@ -166,7 +166,8 @@ export type SuggestedAction =
|
WriteCodeProperlyAction
|
WriteCodeProperlyAction
|
RebuildAction
|
RebuildAction
|
RestartAction
|
RestartAction
|
RefreshAction
;
|
RefreshAction
|
KeepGoingAction
;
export
interface
RestartAppAction
{
export
interface
RestartAppAction
{
id
:
"restart-app"
;
id
:
"restart-app"
;
...
@@ -197,6 +198,10 @@ export interface RefreshAction {
...
@@ -197,6 +198,10 @@ export interface RefreshAction {
id
:
"refresh"
;
id
:
"refresh"
;
}
}
export
interface
KeepGoingAction
{
id
:
"keep-going"
;
}
export
interface
ActionProposal
{
export
interface
ActionProposal
{
type
:
"action-proposal"
;
type
:
"action-proposal"
;
actions
:
SuggestedAction
[];
actions
:
SuggestedAction
[];
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论