Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
c425daf8
Unverified
提交
c425daf8
authored
5月 06, 2025
作者:
Will Chen
提交者:
GitHub
5月 06, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Show warning if there's uncommitted changes (#92)
上级
43ec6a45
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
65 行增加
和
10 行删除
+65
-10
ChatInput.tsx
src/components/chat/ChatInput.tsx
+7
-1
useStreamChat.ts
src/hooks/useStreamChat.ts
+4
-1
chat_stream_handlers.ts
src/ipc/handlers/chat_stream_handlers.ts
+1
-0
proposal_handlers.ts
src/ipc/handlers/proposal_handlers.ts
+6
-2
ipc_client.ts
src/ipc/ipc_client.ts
+12
-4
ipc_types.ts
src/ipc/ipc_types.ts
+1
-0
response_processor.ts
src/ipc/processors/response_processor.ts
+18
-2
toast.ts
src/lib/toast.ts
+16
-0
没有找到文件。
src/components/chat/ChatInput.tsx
浏览文件 @
c425daf8
...
@@ -58,7 +58,10 @@ import { useVersions } from "@/hooks/useVersions";
...
@@ -58,7 +58,10 @@ import { useVersions } from "@/hooks/useVersions";
import
{
useAttachments
}
from
"@/hooks/useAttachments"
;
import
{
useAttachments
}
from
"@/hooks/useAttachments"
;
import
{
AttachmentsList
}
from
"./AttachmentsList"
;
import
{
AttachmentsList
}
from
"./AttachmentsList"
;
import
{
DragDropOverlay
}
from
"./DragDropOverlay"
;
import
{
DragDropOverlay
}
from
"./DragDropOverlay"
;
import
{
showError
as
showErrorToast
,
showUncommittedFilesWarning
,
}
from
"@/lib/toast"
;
const
showTokenBarAtom
=
atom
(
false
);
const
showTokenBarAtom
=
atom
(
false
);
export
function
ChatInput
({
chatId
}:
{
chatId
?:
number
})
{
export
function
ChatInput
({
chatId
}:
{
chatId
?:
number
})
{
...
@@ -189,6 +192,9 @@ export function ChatInput({ chatId }: { chatId?: number }) {
...
@@ -189,6 +192,9 @@ export function ChatInput({ chatId }: { chatId?: number }) {
console
.
error
(
"Failed to approve proposal:"
,
result
.
error
);
console
.
error
(
"Failed to approve proposal:"
,
result
.
error
);
setError
(
result
.
error
||
"Failed to approve proposal"
);
setError
(
result
.
error
||
"Failed to approve proposal"
);
}
}
if
(
result
.
uncommittedFiles
)
{
showUncommittedFilesWarning
(
result
.
uncommittedFiles
);
}
}
catch
(
err
)
{
}
catch
(
err
)
{
console
.
error
(
"Error approving proposal:"
,
err
);
console
.
error
(
"Error approving proposal:"
,
err
);
setError
((
err
as
Error
)?.
message
||
"An error occurred while approving"
);
setError
((
err
as
Error
)?.
message
||
"An error occurred while approving"
);
...
...
src/hooks/useStreamChat.ts
浏览文件 @
c425daf8
...
@@ -14,7 +14,7 @@ import { useChats } from "./useChats";
...
@@ -14,7 +14,7 @@ import { useChats } from "./useChats";
import
{
useLoadApp
}
from
"./useLoadApp"
;
import
{
useLoadApp
}
from
"./useLoadApp"
;
import
{
selectedAppIdAtom
}
from
"@/atoms/appAtoms"
;
import
{
selectedAppIdAtom
}
from
"@/atoms/appAtoms"
;
import
{
useVersions
}
from
"./useVersions"
;
import
{
useVersions
}
from
"./useVersions"
;
import
{
showError
}
from
"@/lib/toast"
;
import
{
showError
,
showUncommittedFilesWarning
}
from
"@/lib/toast"
;
import
{
useProposal
}
from
"./useProposal"
;
import
{
useProposal
}
from
"./useProposal"
;
import
{
useSearch
}
from
"@tanstack/react-router"
;
import
{
useSearch
}
from
"@tanstack/react-router"
;
import
{
useRunApp
}
from
"./useRunApp"
;
import
{
useRunApp
}
from
"./useRunApp"
;
...
@@ -87,6 +87,9 @@ export function useStreamChat({
...
@@ -87,6 +87,9 @@ export function useStreamChat({
setIsPreviewOpen
(
true
);
setIsPreviewOpen
(
true
);
refreshAppIframe
();
refreshAppIframe
();
}
}
if
(
response
.
uncommittedFiles
)
{
showUncommittedFilesWarning
(
response
.
uncommittedFiles
);
}
refreshProposal
(
chatId
);
refreshProposal
(
chatId
);
// Keep the same as below
// Keep the same as below
...
...
src/ipc/handlers/chat_stream_handlers.ts
浏览文件 @
c425daf8
...
@@ -486,6 +486,7 @@ This conversation includes one or more image attachments. When the user uploads
...
@@ -486,6 +486,7 @@ This conversation includes one or more image attachments. When the user uploads
event
.
sender
.
send
(
"chat:response:end"
,
{
event
.
sender
.
send
(
"chat:response:end"
,
{
chatId
:
req
.
chatId
,
chatId
:
req
.
chatId
,
updatedFiles
:
status
.
updatedFiles
??
false
,
updatedFiles
:
status
.
updatedFiles
??
false
,
uncommittedFiles
:
status
.
uncommittedFiles
,
}
satisfies
ChatResponseEnd
);
}
satisfies
ChatResponseEnd
);
}
else
{
}
else
{
event
.
sender
.
send
(
"chat:response:end"
,
{
event
.
sender
.
send
(
"chat:response:end"
,
{
...
...
src/ipc/handlers/proposal_handlers.ts
浏览文件 @
c425daf8
...
@@ -331,7 +331,11 @@ const getProposalHandler = async (
...
@@ -331,7 +331,11 @@ const getProposalHandler = async (
const
approveProposalHandler
=
async
(
const
approveProposalHandler
=
async
(
_event
:
IpcMainInvokeEvent
,
_event
:
IpcMainInvokeEvent
,
{
chatId
,
messageId
}:
{
chatId
:
number
;
messageId
:
number
}
{
chatId
,
messageId
}:
{
chatId
:
number
;
messageId
:
number
}
):
Promise
<
{
success
:
boolean
;
error
?:
string
}
>
=>
{
):
Promise
<
{
success
:
boolean
;
error
?:
string
;
uncommittedFiles
?:
string
[];
}
>
=>
{
logger
.
log
(
logger
.
log
(
`IPC: approve-proposal called for chatId:
${
chatId
}
, messageId:
${
messageId
}
`
`IPC: approve-proposal called for chatId:
${
chatId
}
, messageId:
${
messageId
}
`
);
);
...
@@ -380,7 +384,7 @@ const approveProposalHandler = async (
...
@@ -380,7 +384,7 @@ const approveProposalHandler = async (
};
};
}
}
return
{
success
:
true
};
return
{
success
:
true
,
uncommittedFiles
:
processResult
.
uncommittedFiles
};
}
catch
(
error
)
{
}
catch
(
error
)
{
logger
.
error
(
`Error approving proposal for messageId
${
messageId
}
:`
,
error
);
logger
.
error
(
`Error approving proposal for messageId
${
messageId
}
:`
,
error
);
return
{
return
{
...
...
src/ipc/ipc_client.ts
浏览文件 @
c425daf8
...
@@ -111,10 +111,10 @@ export class IpcClient {
...
@@ -111,10 +111,10 @@ export class IpcClient {
});
});
this
.
ipcRenderer
.
on
(
"chat:response:end"
,
(
payload
)
=>
{
this
.
ipcRenderer
.
on
(
"chat:response:end"
,
(
payload
)
=>
{
const
{
chatId
,
updatedFiles
}
=
payload
as
unknown
as
ChatResponseEnd
;
const
{
chatId
}
=
payload
as
unknown
as
ChatResponseEnd
;
const
callbacks
=
this
.
chatStreams
.
get
(
chatId
);
const
callbacks
=
this
.
chatStreams
.
get
(
chatId
);
if
(
callbacks
)
{
if
(
callbacks
)
{
callbacks
.
onEnd
(
{
chatId
,
updatedFiles
}
);
callbacks
.
onEnd
(
payload
as
unknown
as
ChatResponseEnd
);
console
.
debug
(
"chat:response:end"
);
console
.
debug
(
"chat:response:end"
);
this
.
chatStreams
.
delete
(
chatId
);
this
.
chatStreams
.
delete
(
chatId
);
}
else
{
}
else
{
...
@@ -734,13 +734,21 @@ export class IpcClient {
...
@@ -734,13 +734,21 @@ export class IpcClient {
}:
{
}:
{
chatId
:
number
;
chatId
:
number
;
messageId
:
number
;
messageId
:
number
;
}):
Promise
<
{
success
:
boolean
;
error
?:
string
}
>
{
}):
Promise
<
{
success
:
boolean
;
error
?:
string
;
uncommittedFiles
?:
string
[];
}
>
{
try
{
try
{
const
result
=
await
this
.
ipcRenderer
.
invoke
(
"approve-proposal"
,
{
const
result
=
await
this
.
ipcRenderer
.
invoke
(
"approve-proposal"
,
{
chatId
,
chatId
,
messageId
,
messageId
,
});
});
return
result
as
{
success
:
boolean
;
error
?:
string
};
return
result
as
{
success
:
boolean
;
error
?:
string
;
uncommittedFiles
?:
string
[];
};
}
catch
(
error
)
{
}
catch
(
error
)
{
showError
(
error
);
showError
(
error
);
return
{
success
:
false
,
error
:
(
error
as
Error
).
message
};
return
{
success
:
false
,
error
:
(
error
as
Error
).
message
};
...
...
src/ipc/ipc_types.ts
浏览文件 @
c425daf8
...
@@ -24,6 +24,7 @@ export interface ChatStreamParams {
...
@@ -24,6 +24,7 @@ export interface ChatStreamParams {
export
interface
ChatResponseEnd
{
export
interface
ChatResponseEnd
{
chatId
:
number
;
chatId
:
number
;
updatedFiles
:
boolean
;
updatedFiles
:
boolean
;
uncommittedFiles
?:
string
[];
}
}
export
interface
CreateAppParams
{
export
interface
CreateAppParams
{
...
...
src/ipc/processors/response_processor.ts
浏览文件 @
c425daf8
...
@@ -175,7 +175,11 @@ export async function processFullResponseActions(
...
@@ -175,7 +175,11 @@ export async function processFullResponseActions(
chatSummary
,
chatSummary
,
messageId
,
messageId
,
}:
{
chatSummary
:
string
|
undefined
;
messageId
:
number
}
}:
{
chatSummary
:
string
|
undefined
;
messageId
:
number
}
):
Promise
<
{
updatedFiles
?:
boolean
;
error
?:
string
}
>
{
):
Promise
<
{
updatedFiles
?:
boolean
;
error
?:
string
;
uncommittedFiles
?:
string
[];
}
>
{
logger
.
log
(
"processFullResponseActions for chatId"
,
chatId
);
logger
.
log
(
"processFullResponseActions for chatId"
,
chatId
);
// Get the app associated with the chat
// Get the app associated with the chat
const
chatWithApp
=
await
db
.
query
.
chats
.
findFirst
({
const
chatWithApp
=
await
db
.
query
.
chats
.
findFirst
({
...
@@ -453,6 +457,13 @@ export async function processFullResponseActions(
...
@@ -453,6 +457,13 @@ export async function processFullResponseActions(
})
})
.
where
(
eq
(
messages
.
id
,
messageId
));
.
where
(
eq
(
messages
.
id
,
messageId
));
}
}
// Check for any uncommitted changes after the commit
const
statusMatrix
=
await
git
.
statusMatrix
({
fs
,
dir
:
appPath
});
const
uncommittedFiles
=
statusMatrix
.
filter
((
row
)
=>
row
[
1
]
!==
1
||
row
[
2
]
!==
1
||
row
[
3
]
!==
1
)
.
map
((
row
)
=>
row
[
0
]);
// Get just the file paths
logger
.
log
(
"mark as approved: hasChanges"
,
hasChanges
);
logger
.
log
(
"mark as approved: hasChanges"
,
hasChanges
);
// Update the message to approved
// Update the message to approved
await
db
await
db
...
@@ -461,7 +472,12 @@ export async function processFullResponseActions(
...
@@ -461,7 +472,12 @@ export async function processFullResponseActions(
approvalState
:
"approved"
,
approvalState
:
"approved"
,
})
})
.
where
(
eq
(
messages
.
id
,
messageId
));
.
where
(
eq
(
messages
.
id
,
messageId
));
return
{
updatedFiles
:
hasChanges
};
return
{
updatedFiles
:
hasChanges
,
uncommittedFiles
:
uncommittedFiles
.
length
>
0
?
uncommittedFiles
:
undefined
,
};
}
catch
(
error
:
unknown
)
{
}
catch
(
error
:
unknown
)
{
logger
.
error
(
"Error processing files:"
,
error
);
logger
.
error
(
"Error processing files:"
,
error
);
return
{
error
:
(
error
as
any
).
toString
()
};
return
{
error
:
(
error
as
any
).
toString
()
};
...
...
src/lib/toast.ts
浏览文件 @
c425daf8
...
@@ -21,6 +21,15 @@ export const showError = (message: any) => {
...
@@ -21,6 +21,15 @@ export const showError = (message: any) => {
console
.
error
(
message
);
console
.
error
(
message
);
};
};
/**
* Show a warning toast
* @param message The warning message to display
*/
export
const
showWarning
=
(
message
:
string
)
=>
{
toast
.
warning
(
message
);
console
.
warn
(
message
);
};
/**
/**
* Show an info toast
* Show an info toast
* @param message The info message to display
* @param message The info message to display
...
@@ -49,5 +58,12 @@ export const showLoading = <T>(
...
@@ -49,5 +58,12 @@ export const showLoading = <T>(
});
});
};
};
export
const
showUncommittedFilesWarning
=
(
files
:
string
[])
=>
{
showWarning
(
`Some changed files were not committed. Please use git to manually commit them.
\n\n
${
files
.
join
(
"
\
n"
)}
`
);
};
// Re-export for direct use
// Re-export for direct use
export
{
toast
};
export
{
toast
};
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论