Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
ebf87437
提交
ebf87437
authored
4月 18, 2025
作者:
Will Chen
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refresh proposal & loaders for proposal action
上级
4a158417
显示空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
315 行增加
和
33 行删除
+315
-33
ChatInput.tsx
src/components/chat/ChatInput.tsx
+81
-9
useProposal.ts
src/hooks/useProposal.ts
+43
-14
useStreamChat.ts
src/hooks/useStreamChat.ts
+3
-1
proposal_handlers.ts
src/ipc/handlers/proposal_handlers.ts
+136
-6
ipc_client.ts
src/ipc/ipc_client.ts
+50
-3
preload.ts
src/preload.ts
+2
-0
没有找到文件。
src/components/chat/ChatInput.tsx
浏览文件 @
ebf87437
...
@@ -8,6 +8,7 @@ import {
...
@@ -8,6 +8,7 @@ import {
AlertOctagon
,
AlertOctagon
,
FileText
,
FileText
,
Check
,
Check
,
Loader2
,
}
from
"lucide-react"
;
}
from
"lucide-react"
;
import
type
React
from
"react"
;
import
type
React
from
"react"
;
import
{
useEffect
,
useRef
,
useState
}
from
"react"
;
import
{
useEffect
,
useRef
,
useState
}
from
"react"
;
...
@@ -31,6 +32,8 @@ interface ChatInputActionsProps {
...
@@ -31,6 +32,8 @@ interface ChatInputActionsProps {
onApprove
:
()
=>
void
;
onApprove
:
()
=>
void
;
onReject
:
()
=>
void
;
onReject
:
()
=>
void
;
isApprovable
:
boolean
;
// Can be used to enable/disable buttons
isApprovable
:
boolean
;
// Can be used to enable/disable buttons
isApproving
:
boolean
;
// State for approving
isRejecting
:
boolean
;
// State for rejecting
}
}
interface
ChatInputProps
{
interface
ChatInputProps
{
...
@@ -46,12 +49,16 @@ export function ChatInput({ chatId, onSubmit }: ChatInputProps) {
...
@@ -46,12 +49,16 @@ export function ChatInput({ chatId, onSubmit }: ChatInputProps) {
useStreamChat
();
useStreamChat
();
const
[
selectedAppId
]
=
useAtom
(
selectedAppIdAtom
);
const
[
selectedAppId
]
=
useAtom
(
selectedAppIdAtom
);
const
[
showError
,
setShowError
]
=
useState
(
true
);
const
[
showError
,
setShowError
]
=
useState
(
true
);
const
[
isApproving
,
setIsApproving
]
=
useState
(
false
);
// State for approving
const
[
isRejecting
,
setIsRejecting
]
=
useState
(
false
);
// State for rejecting
// Use the hook to fetch the proposal
// Use the hook to fetch the proposal
const
{
const
{
proposal
,
proposal
,
messageId
,
isLoading
:
isProposalLoading
,
isLoading
:
isProposalLoading
,
error
:
proposalError
,
error
:
proposalError
,
refreshProposal
,
}
=
useProposal
(
chatId
);
}
=
useProposal
(
chatId
);
const
adjustHeight
=
()
=>
{
const
adjustHeight
=
()
=>
{
...
@@ -102,14 +109,60 @@ export function ChatInput({ chatId, onSubmit }: ChatInputProps) {
...
@@ -102,14 +109,60 @@ export function ChatInput({ chatId, onSubmit }: ChatInputProps) {
setShowError
(
false
);
setShowError
(
false
);
};
};
const
handleApprove
=
()
=>
{
const
handleApprove
=
async
()
=>
{
console
.
log
(
"Approve clicked"
);
if
(
!
chatId
||
!
messageId
||
isApproving
||
isRejecting
||
isStreaming
)
// Add approve logic here
return
;
console
.
log
(
`Approving proposal for chatId:
${
chatId
}
, messageId:
${
messageId
}
`
);
setIsApproving
(
true
);
try
{
const
result
=
await
IpcClient
.
getInstance
().
approveProposal
({
chatId
,
messageId
,
});
if
(
result
.
success
)
{
console
.
log
(
"Proposal approved successfully"
);
// TODO: Maybe refresh proposal state or show confirmation?
}
else
{
console
.
error
(
"Failed to approve proposal:"
,
result
.
error
);
setError
(
result
.
error
||
"Failed to approve proposal"
);
}
}
catch
(
err
)
{
console
.
error
(
"Error approving proposal:"
,
err
);
setError
((
err
as
Error
)?.
message
||
"An error occurred while approving"
);
}
finally
{
setIsApproving
(
false
);
refreshProposal
();
}
};
};
const
handleReject
=
()
=>
{
const
handleReject
=
async
()
=>
{
console
.
log
(
"Reject clicked"
);
if
(
!
chatId
||
!
messageId
||
isApproving
||
isRejecting
||
isStreaming
)
// Add reject logic here
return
;
console
.
log
(
`Rejecting proposal for chatId:
${
chatId
}
, messageId:
${
messageId
}
`
);
setIsRejecting
(
true
);
try
{
const
result
=
await
IpcClient
.
getInstance
().
rejectProposal
({
chatId
,
messageId
,
});
if
(
result
.
success
)
{
console
.
log
(
"Proposal rejected successfully"
);
// TODO: Maybe refresh proposal state or show confirmation?
}
else
{
console
.
error
(
"Failed to reject proposal:"
,
result
.
error
);
setError
(
result
.
error
||
"Failed to reject proposal"
);
}
}
catch
(
err
)
{
console
.
error
(
"Error rejecting proposal:"
,
err
);
setError
((
err
as
Error
)?.
message
||
"An error occurred while rejecting"
);
}
finally
{
setIsRejecting
(
false
);
refreshProposal
();
}
};
};
if
(
!
settings
)
{
if
(
!
settings
)
{
...
@@ -150,7 +203,16 @@ export function ChatInput({ chatId, onSubmit }: ChatInputProps) {
...
@@ -150,7 +203,16 @@ export function ChatInput({ chatId, onSubmit }: ChatInputProps) {
proposal=
{
proposal
}
proposal=
{
proposal
}
onApprove=
{
handleApprove
}
onApprove=
{
handleApprove
}
onReject=
{
handleReject
}
onReject=
{
handleReject
}
isApprovable=
{
!
isProposalLoading
&&
!!
proposal
}
isApprovable=
{
!
isProposalLoading
&&
!!
proposal
&&
!!
messageId
&&
!
isApproving
&&
!
isRejecting
&&
!
isStreaming
}
isApproving=
{
isApproving
}
isRejecting=
{
isRejecting
}
/>
/>
)
}
)
}
<
div
className=
"flex items-start space-x-2 "
>
<
div
className=
"flex items-start space-x-2 "
>
...
@@ -202,6 +264,8 @@ function ChatInputActions({
...
@@ -202,6 +264,8 @@ function ChatInputActions({
onApprove
,
onApprove
,
onReject
,
onReject
,
isApprovable
,
isApprovable
,
isApproving
,
isRejecting
,
}:
ChatInputActionsProps
)
{
}:
ChatInputActionsProps
)
{
const
[
autoApprove
,
setAutoApprove
]
=
useState
(
false
);
const
[
autoApprove
,
setAutoApprove
]
=
useState
(
false
);
const
[
isDetailsVisible
,
setIsDetailsVisible
]
=
useState
(
false
);
const
[
isDetailsVisible
,
setIsDetailsVisible
]
=
useState
(
false
);
...
@@ -236,9 +300,13 @@ function ChatInputActions({
...
@@ -236,9 +300,13 @@ function ChatInputActions({
size=
"sm"
size=
"sm"
variant=
"outline"
variant=
"outline"
onClick=
{
onApprove
}
onClick=
{
onApprove
}
disabled=
{
!
isApprovable
}
disabled=
{
!
isApprovable
||
isApproving
||
isRejecting
}
>
>
{
isApproving
?
(
<
Loader2
size=
{
16
}
className=
"mr-1 animate-spin"
/>
)
:
(
<
Check
size=
{
16
}
className=
"mr-1"
/>
<
Check
size=
{
16
}
className=
"mr-1"
/>
)
}
Approve
Approve
</
Button
>
</
Button
>
<
Button
<
Button
...
@@ -246,9 +314,13 @@ function ChatInputActions({
...
@@ -246,9 +314,13 @@ function ChatInputActions({
size=
"sm"
size=
"sm"
variant=
"outline"
variant=
"outline"
onClick=
{
onReject
}
onClick=
{
onReject
}
disabled=
{
!
isApprovable
}
disabled=
{
!
isApprovable
||
isApproving
||
isRejecting
}
>
>
{
isRejecting
?
(
<
Loader2
size=
{
16
}
className=
"mr-1 animate-spin"
/>
)
:
(
<
X
size=
{
16
}
className=
"mr-1"
/>
<
X
size=
{
16
}
className=
"mr-1"
/>
)
}
Reject
Reject
</
Button
>
</
Button
>
<
div
className=
"flex items-center space-x-1 ml-auto"
>
<
div
className=
"flex items-center space-x-1 ml-auto"
>
...
...
src/hooks/useProposal.ts
浏览文件 @
ebf87437
import
{
useState
,
useEffect
}
from
"react"
;
import
{
useState
,
useEffect
,
useCallback
}
from
"react"
;
import
{
IpcClient
}
from
"@/ipc/ipc_client"
;
import
{
IpcClient
}
from
"@/ipc/ipc_client"
;
import
type
{
Proposal
}
from
"@/lib/schemas"
;
// Import Proposal type
import
type
{
Proposal
}
from
"@/lib/schemas"
;
// Import Proposal type
export
function
useProposal
(
chatId
:
number
|
undefined
)
{
// Define the structure returned by the IPC call
const
[
proposal
,
setProposal
]
=
useState
<
Proposal
|
null
>
(
null
);
interface
ProposalResult
{
proposal
:
Proposal
;
messageId
:
number
;
}
export
function
useProposal
(
chatId
?:
number
|
undefined
)
{
const
[
proposalData
,
setProposalData
]
=
useState
<
ProposalResult
|
null
>
(
null
);
const
[
isLoading
,
setIsLoading
]
=
useState
<
boolean
>
(
false
);
const
[
isLoading
,
setIsLoading
]
=
useState
<
boolean
>
(
false
);
const
[
error
,
setError
]
=
useState
<
string
|
null
>
(
null
);
const
[
error
,
setError
]
=
useState
<
string
|
null
>
(
null
);
useEffect
(()
=>
{
const
fetchProposal
=
useCallback
(
async
(
innerChatId
?:
number
)
=>
{
chatId
=
chatId
??
innerChatId
;
if
(
chatId
===
undefined
)
{
if
(
chatId
===
undefined
)
{
setProposal
(
null
);
setProposalData
(
null
);
setIsLoading
(
false
);
setIsLoading
(
false
);
setError
(
null
);
setError
(
null
);
return
;
return
;
}
}
const
fetchProposal
=
async
()
=>
{
setIsLoading
(
true
);
setIsLoading
(
true
);
setError
(
null
);
setError
(
null
);
setProposalData
(
null
);
// Reset on new fetch
try
{
try
{
const
fetchedProposal
=
await
IpcClient
.
getInstance
().
getProposal
(
// Type assertion might be needed depending on how IpcClient is typed
const
result
=
(
await
IpcClient
.
getInstance
().
getProposal
(
chatId
chatId
);
))
as
ProposalResult
|
null
;
setProposal
(
fetchedProposal
);
if
(
result
)
{
setProposalData
(
result
);
}
else
{
setProposalData
(
null
);
// Explicitly set to null if IPC returns null
}
}
catch
(
err
:
any
)
{
}
catch
(
err
:
any
)
{
console
.
error
(
"Error fetching proposal:"
,
err
);
console
.
error
(
"Error fetching proposal:"
,
err
);
setError
(
err
.
message
||
"Failed to fetch proposal"
);
setError
(
err
.
message
||
"Failed to fetch proposal"
);
setProposal
(
null
);
// Clear proposal
on error
setProposal
Data
(
null
);
// Clear proposal data
on error
}
finally
{
}
finally
{
setIsLoading
(
false
);
setIsLoading
(
false
);
}
}
};
},
[
chatId
]
);
// Depend on chatId
useEffect
(()
=>
{
fetchProposal
();
fetchProposal
();
// Cleanup function if needed (e.g., for aborting requests)
// Cleanup function if needed (e.g., for aborting requests)
// return () => {
// return () => {
// // Abort logic here
// // Abort logic here
// };
// };
},
[
chatId
]);
// Re-run effect if chatId changes
},
[
fetchProposal
]);
// Re-run effect if fetchProposal changes (due to chatId change)
return
{
proposal
,
isLoading
,
error
};
const
refreshProposal
=
useCallback
(
(
chatId
?:
number
)
=>
{
fetchProposal
(
chatId
);
},
[
fetchProposal
]
);
return
{
proposal
:
proposalData
?.
proposal
??
null
,
messageId
:
proposalData
?.
messageId
,
isLoading
,
error
,
refreshProposal
,
// Expose the refresh function
};
}
}
src/hooks/useStreamChat.ts
浏览文件 @
ebf87437
...
@@ -15,6 +15,7 @@ import { useLoadApp } from "./useLoadApp";
...
@@ -15,6 +15,7 @@ import { useLoadApp } from "./useLoadApp";
import
{
selectedAppIdAtom
}
from
"@/atoms/appAtoms"
;
import
{
selectedAppIdAtom
}
from
"@/atoms/appAtoms"
;
import
{
useLoadVersions
}
from
"./useLoadVersions"
;
import
{
useLoadVersions
}
from
"./useLoadVersions"
;
import
{
showError
}
from
"@/lib/toast"
;
import
{
showError
}
from
"@/lib/toast"
;
import
{
useProposal
}
from
"./useProposal"
;
export
function
getRandomString
()
{
export
function
getRandomString
()
{
return
Math
.
random
().
toString
(
36
).
substring
(
2
,
15
);
return
Math
.
random
().
toString
(
36
).
substring
(
2
,
15
);
...
@@ -30,7 +31,7 @@ export function useStreamChat() {
...
@@ -30,7 +31,7 @@ export function useStreamChat() {
const
{
refreshApp
}
=
useLoadApp
(
selectedAppId
);
const
{
refreshApp
}
=
useLoadApp
(
selectedAppId
);
const
setStreamCount
=
useSetAtom
(
chatStreamCountAtom
);
const
setStreamCount
=
useSetAtom
(
chatStreamCountAtom
);
const
{
refreshVersions
}
=
useLoadVersions
(
selectedAppId
);
const
{
refreshVersions
}
=
useLoadVersions
(
selectedAppId
);
const
{
refreshProposal
}
=
useProposal
();
const
streamMessage
=
useCallback
(
const
streamMessage
=
useCallback
(
async
({
async
({
prompt
,
prompt
,
...
@@ -94,6 +95,7 @@ export function useStreamChat() {
...
@@ -94,6 +95,7 @@ export function useStreamChat() {
// Keep the same as below
// Keep the same as below
setIsStreaming
(
false
);
setIsStreaming
(
false
);
refreshProposal
(
chatId
);
refreshChats
();
refreshChats
();
refreshApp
();
refreshApp
();
refreshVersions
();
refreshVersions
();
...
...
src/ipc/handlers/proposal_handlers.ts
浏览文件 @
ebf87437
...
@@ -2,12 +2,13 @@ import { ipcMain, type IpcMainInvokeEvent } from "electron";
...
@@ -2,12 +2,13 @@ import { ipcMain, type IpcMainInvokeEvent } from "electron";
import
type
{
Proposal
}
from
"@/lib/schemas"
;
import
type
{
Proposal
}
from
"@/lib/schemas"
;
import
{
db
}
from
"../../db"
;
import
{
db
}
from
"../../db"
;
import
{
messages
}
from
"../../db/schema"
;
import
{
messages
}
from
"../../db/schema"
;
import
{
desc
,
eq
,
and
}
from
"drizzle-orm"
;
import
{
desc
,
eq
,
and
,
Update
}
from
"drizzle-orm"
;
import
path
from
"node:path"
;
// Import path for basename
import
path
from
"node:path"
;
// Import path for basename
// Import tag parsers
// Import tag parsers
import
{
import
{
getDyadChatSummaryTag
,
getDyadChatSummaryTag
,
getDyadWriteTags
,
getDyadWriteTags
,
processFullResponseActions
,
}
from
"../processors/response_processor"
;
}
from
"../processors/response_processor"
;
// Placeholder Proposal data (can be removed or kept for reference)
// Placeholder Proposal data (can be removed or kept for reference)
...
@@ -19,6 +20,12 @@ interface ParsedProposal {
...
@@ -19,6 +20,12 @@ interface ParsedProposal {
files
:
string
[];
files
:
string
[];
}
}
// Define return type for getProposalHandler
interface
ProposalResult
{
proposal
:
Proposal
;
messageId
:
number
;
}
function
isParsedProposal
(
obj
:
any
):
obj
is
ParsedProposal
{
function
isParsedProposal
(
obj
:
any
):
obj
is
ParsedProposal
{
return
(
return
(
obj
&&
obj
&&
...
@@ -32,7 +39,7 @@ function isParsedProposal(obj: any): obj is ParsedProposal {
...
@@ -32,7 +39,7 @@ function isParsedProposal(obj: any): obj is ParsedProposal {
const
getProposalHandler
=
async
(
const
getProposalHandler
=
async
(
_event
:
IpcMainInvokeEvent
,
_event
:
IpcMainInvokeEvent
,
{
chatId
}:
{
chatId
:
number
}
{
chatId
}:
{
chatId
:
number
}
):
Promise
<
Proposal
|
null
>
=>
{
):
Promise
<
Proposal
Result
|
null
>
=>
{
console
.
log
(
`IPC: get-proposal called for chatId:
${
chatId
}
`
);
console
.
log
(
`IPC: get-proposal called for chatId:
${
chatId
}
`
);
try
{
try
{
...
@@ -41,12 +48,16 @@ const getProposalHandler = async (
...
@@ -41,12 +48,16 @@ const getProposalHandler = async (
where
:
and
(
eq
(
messages
.
chatId
,
chatId
),
eq
(
messages
.
role
,
"assistant"
)),
where
:
and
(
eq
(
messages
.
chatId
,
chatId
),
eq
(
messages
.
role
,
"assistant"
)),
orderBy
:
[
desc
(
messages
.
createdAt
)],
orderBy
:
[
desc
(
messages
.
createdAt
)],
columns
:
{
columns
:
{
id
:
true
,
// Fetch the ID
content
:
true
,
// Fetch the content to parse
content
:
true
,
// Fetch the content to parse
},
},
});
});
if
(
latestAssistantMessage
?.
content
)
{
if
(
latestAssistantMessage
?.
content
&&
latestAssistantMessage
.
id
)
{
console
.
log
(
"Found latest assistant message, parsing content..."
);
const
messageId
=
latestAssistantMessage
.
id
;
// Get the message ID
console
.
log
(
`Found latest assistant message (ID:
${
messageId
}
), parsing content...`
);
const
messageContent
=
latestAssistantMessage
.
content
;
const
messageContent
=
latestAssistantMessage
.
content
;
// Parse tags directly from message content
// Parse tags directly from message content
...
@@ -66,7 +77,7 @@ const getProposalHandler = async (
...
@@ -66,7 +77,7 @@ const getProposalHandler = async (
})),
})),
};
};
console
.
log
(
"Generated proposal on the fly:"
,
proposal
);
console
.
log
(
"Generated proposal on the fly:"
,
proposal
);
return
proposal
;
return
{
proposal
,
messageId
};
// Return proposal and messageId
}
else
{
}
else
{
console
.
log
(
console
.
log
(
"No relevant tags found in the latest assistant message content."
"No relevant tags found in the latest assistant message content."
...
@@ -83,8 +94,127 @@ const getProposalHandler = async (
...
@@ -83,8 +94,127 @@ const getProposalHandler = async (
}
}
};
};
// Handler to approve a proposal (process actions and update message)
const
approveProposalHandler
=
async
(
_event
:
IpcMainInvokeEvent
,
{
chatId
,
messageId
}:
{
chatId
:
number
;
messageId
:
number
}
):
Promise
<
{
success
:
boolean
;
error
?:
string
}
>
=>
{
console
.
log
(
`IPC: approve-proposal called for chatId:
${
chatId
}
, messageId:
${
messageId
}
`
);
try
{
// 1. Fetch the specific assistant message
const
messageToApprove
=
await
db
.
query
.
messages
.
findFirst
({
where
:
and
(
eq
(
messages
.
id
,
messageId
),
eq
(
messages
.
chatId
,
chatId
),
eq
(
messages
.
role
,
"assistant"
)
),
columns
:
{
content
:
true
,
},
});
if
(
!
messageToApprove
?.
content
)
{
console
.
error
(
`Assistant message not found for chatId:
${
chatId
}
, messageId:
${
messageId
}
`
);
return
{
success
:
false
,
error
:
"Assistant message not found."
};
}
// 2. Process the actions defined in the message content
const
chatSummary
=
getDyadChatSummaryTag
(
messageToApprove
.
content
);
const
processResult
=
await
processFullResponseActions
(
messageToApprove
.
content
,
chatId
,
{
chatSummary
:
chatSummary
??
undefined
}
// Pass summary if found
);
if
(
processResult
.
error
)
{
console
.
error
(
`Error processing actions for message
${
messageId
}
:`
,
processResult
.
error
);
// Optionally: Update message state to 'error' or similar?
// For now, just return error to frontend
return
{
success
:
false
,
error
:
`Action processing failed:
${
processResult
.
error
}
`
,
};
}
// 3. Update the message's approval state to 'approved'
await
db
.
update
(
messages
)
.
set
({
approvalState
:
"approved"
})
.
where
(
eq
(
messages
.
id
,
messageId
));
console
.
log
(
`Message
${
messageId
}
marked as approved.`
);
return
{
success
:
true
};
}
catch
(
error
)
{
console
.
error
(
`Error approving proposal for messageId
${
messageId
}
:`
,
error
);
return
{
success
:
false
,
error
:
(
error
as
Error
)?.
message
||
"Unknown error"
,
};
}
};
// Handler to reject a proposal (just update message state)
const
rejectProposalHandler
=
async
(
_event
:
IpcMainInvokeEvent
,
{
chatId
,
messageId
}:
{
chatId
:
number
;
messageId
:
number
}
):
Promise
<
{
success
:
boolean
;
error
?:
string
}
>
=>
{
console
.
log
(
`IPC: reject-proposal called for chatId:
${
chatId
}
, messageId:
${
messageId
}
`
);
try
{
// 1. Verify the message exists and is an assistant message
const
messageToReject
=
await
db
.
query
.
messages
.
findFirst
({
where
:
and
(
eq
(
messages
.
id
,
messageId
),
eq
(
messages
.
chatId
,
chatId
),
eq
(
messages
.
role
,
"assistant"
)
),
columns
:
{
id
:
true
},
// Only need to confirm existence
});
if
(
!
messageToReject
)
{
console
.
error
(
`Assistant message not found for chatId:
${
chatId
}
, messageId:
${
messageId
}
`
);
return
{
success
:
false
,
error
:
"Assistant message not found."
};
}
// 2. Update the message's approval state to 'rejected'
await
db
.
update
(
messages
)
.
set
({
approvalState
:
"rejected"
})
.
where
(
eq
(
messages
.
id
,
messageId
));
console
.
log
(
`Message
${
messageId
}
marked as rejected.`
);
return
{
success
:
true
};
}
catch
(
error
)
{
console
.
error
(
`Error rejecting proposal for messageId
${
messageId
}
:`
,
error
);
return
{
success
:
false
,
error
:
(
error
as
Error
)?.
message
||
"Unknown error"
,
};
}
};
// Function to register proposal-related handlers
// Function to register proposal-related handlers
export
function
registerProposalHandlers
()
{
export
function
registerProposalHandlers
()
{
ipcMain
.
handle
(
"get-proposal"
,
getProposalHandler
);
ipcMain
.
handle
(
"get-proposal"
,
getProposalHandler
);
console
.
log
(
"Registered proposal IPC handlers"
);
ipcMain
.
handle
(
"approve-proposal"
,
approveProposalHandler
);
ipcMain
.
handle
(
"reject-proposal"
,
rejectProposalHandler
);
console
.
log
(
"Registered proposal IPC handlers (get, approve, reject)"
);
}
}
src/ipc/ipc_client.ts
浏览文件 @
ebf87437
...
@@ -20,6 +20,12 @@ import type {
...
@@ -20,6 +20,12 @@ import type {
import
type
{
Proposal
}
from
"@/lib/schemas"
;
import
type
{
Proposal
}
from
"@/lib/schemas"
;
import
{
showError
}
from
"@/lib/toast"
;
import
{
showError
}
from
"@/lib/toast"
;
// Define the structure returned by getProposal
interface
ProposalResult
{
proposal
:
Proposal
;
messageId
:
number
;
}
export
interface
ChatStreamCallbacks
{
export
interface
ChatStreamCallbacks
{
onUpdate
:
(
messages
:
Message
[])
=>
void
;
onUpdate
:
(
messages
:
Message
[])
=>
void
;
onEnd
:
(
response
:
ChatResponseEnd
)
=>
void
;
onEnd
:
(
response
:
ChatResponseEnd
)
=>
void
;
...
@@ -616,11 +622,12 @@ export class IpcClient {
...
@@ -616,11 +622,12 @@ export class IpcClient {
}
}
// Get proposal details
// Get proposal details
public
async
getProposal
(
chatId
:
number
):
Promise
<
Proposal
>
{
public
async
getProposal
(
chatId
:
number
):
Promise
<
Proposal
Result
|
null
>
{
try
{
try
{
const
data
=
await
this
.
ipcRenderer
.
invoke
(
"get-proposal"
,
{
chatId
});
const
data
=
await
this
.
ipcRenderer
.
invoke
(
"get-proposal"
,
{
chatId
});
// Assuming the main process returns data matching the Proposal interface
// Assuming the main process returns data matching the ProposalResult interface
return
data
as
Proposal
;
// Add a type check/guard if necessary for robustness
return
data
as
ProposalResult
|
null
;
}
catch
(
error
)
{
}
catch
(
error
)
{
showError
(
error
);
showError
(
error
);
throw
error
;
throw
error
;
...
@@ -629,4 +636,44 @@ export class IpcClient {
...
@@ -629,4 +636,44 @@ export class IpcClient {
// Example methods for listening to events (if needed)
// Example methods for listening to events (if needed)
// public on(channel: string, func: (...args: any[]) => void): void {
// public on(channel: string, func: (...args: any[]) => void): void {
// --- Proposal Management ---
public
async
approveProposal
({
chatId
,
messageId
,
}:
{
chatId
:
number
;
messageId
:
number
;
}):
Promise
<
{
success
:
boolean
;
error
?:
string
}
>
{
try
{
const
result
=
await
this
.
ipcRenderer
.
invoke
(
"approve-proposal"
,
{
chatId
,
messageId
,
});
return
result
as
{
success
:
boolean
;
error
?:
string
};
}
catch
(
error
)
{
showError
(
error
);
return
{
success
:
false
,
error
:
(
error
as
Error
).
message
};
}
}
public
async
rejectProposal
({
chatId
,
messageId
,
}:
{
chatId
:
number
;
messageId
:
number
;
}):
Promise
<
{
success
:
boolean
;
error
?:
string
}
>
{
try
{
const
result
=
await
this
.
ipcRenderer
.
invoke
(
"reject-proposal"
,
{
chatId
,
messageId
,
});
return
result
as
{
success
:
boolean
;
error
?:
string
};
}
catch
(
error
)
{
showError
(
error
);
return
{
success
:
false
,
error
:
(
error
as
Error
).
message
};
}
}
// --- End Proposal Management ---
}
}
src/preload.ts
浏览文件 @
ebf87437
...
@@ -39,6 +39,8 @@ const validInvokeChannels = [
...
@@ -39,6 +39,8 @@ const validInvokeChannels = [
"get-app-version"
,
"get-app-version"
,
"reload-env-path"
,
"reload-env-path"
,
"get-proposal"
,
"get-proposal"
,
"approve-proposal"
,
"reject-proposal"
,
]
as
const
;
]
as
const
;
// Add valid receive channels
// Add valid receive channels
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论