Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions app/renderer/src/main/public/locales/en/webFuzzer.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
"webFuzzerDemo": "WebFuzzer Brute-Force Animation Demo",
"bruteForceExample": "Brute-Force Example",
"AI_new_conversation": "New conversation",
"ai_auto_patch_request": "AI auto-update request",
"followRedirects": "Follow Redirects",
"generatePathTemplate": "Generate as Path Template",
"generateRawTemplate": "Generate as Raw Template",
Expand All @@ -100,7 +99,11 @@
"send_request": "Send Request",
"parameter": "Parameter",
"trafficAnalysisMode": "TrafficAnalysis Mode",
"trafficAnalysis": "TrafficAnalysis"
"trafficAnalysis": "TrafficAnalysis",
"aiCasualRejectAll": "Reject all",
"aiCasualAcceptAll": "Accept all",

"aiCasualAcceptAllMetaTitle": "Setting to apply"
},
"FuzzerExtraShow": {
"responsesDiscarded": "Discarded [{{droppedCount}}] responses",
Expand Down
7 changes: 5 additions & 2 deletions app/renderer/src/main/public/locales/zh/webFuzzer.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
"webFuzzerDemo": "WebFuzzer 爆破动画演示",
"bruteForceExample": "爆破示例",
"AI_new_conversation": "新建对话",
"ai_auto_patch_request": "AI 自动改包",
"followRedirects": "跟随重定向",
"generatePathTemplate": "生成为 Path 模板",
"generateRawTemplate": "生成为 Raw 模板",
Expand All @@ -100,7 +99,11 @@
"send_request": "发送请求",
"parameter": "参数",
"trafficAnalysisMode": "流量分析模式",
"trafficAnalysis": "流量分析"
"trafficAnalysis": "流量分析",
"aiCasualRejectAll": "全部放弃",
"aiCasualAcceptAll": "全部应用",

"aiCasualAcceptAllMetaTitle": "即将应用的配置"
},
"FuzzerExtraShow": {
"responsesDiscarded": "已丢弃[{{droppedCount}}]个响应",
Expand Down
3 changes: 1 addition & 2 deletions app/renderer/src/main/src/components/AIReActChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
onGetGlobalNetworkConfig()
getAIModelListOption()
}
}, [inViewport])

Check warning on line 72 in app/renderer/src/main/src/components/AIReActChat.tsx

View workflow job for this annotation

GitHub Actions / ESLint(renderer src/main) / check

React Hook useEffect has missing dependencies: 'getAIModelListOption', 'onGetGlobalNetworkConfig', and 'run'. Either include them or remove the dependency array

const getAIModelListOption = useDebounceFn(
() => {
Expand Down Expand Up @@ -101,11 +101,10 @@
.catch(() => {})
}
return () => {}
}, [inViewport])

Check warning on line 104 in app/renderer/src/main/src/components/AIReActChat.tsx

View workflow job for this annotation

GitHub Actions / ESLint(renderer src/main) / check

React Hook useEffect has a missing dependency: 'setSetting'. Either include it or remove the dependency array

const resultRender = useMemo(() => {
// 未完成检查,不渲染任何业务 UI
if (loading) return null
if (loading && data === undefined) return null

// 无模型 → 配置引导
if (data) {
Expand Down
49 changes: 45 additions & 4 deletions app/renderer/src/main/src/components/withHistoryAIReActChat.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { createContext, memo, useCallback, useContext, useMemo, useRef } from 'react'
import React, { createContext, memo, useCallback, useContext, useEffect, useMemo, useRef } from 'react'
import { useCreation, useInViewport, useMemoizedFn, useSafeState } from 'ahooks'
import { cloneDeep } from 'lodash'

Expand Down Expand Up @@ -27,8 +27,12 @@ import {
AISendParams,
AISendResProps,
} from '@/pages/ai-re-act/aiReActChat/AIReActChatType'
import { AIInputEvent } from '@/pages/ai-re-act/hooks/grpcApi'
import { getWebFuzzerPageRequestString } from '@/pages/fuzzer/webFuzzerAiRequestApplyBridge'
import { AIAgentGrpcApi, AIInputEvent } from '@/pages/ai-re-act/hooks/grpcApi'
import {
applyHttpFuzzRequestChangeToWebFuzzerPage,
getWebFuzzerPageRequestString,
enqueueWebFuzzerCasualReplaceReview,
} from '@/pages/fuzzer/webFuzzerAiRequestApplyBridge'
import { ChatIPCSendType, UseChatIPCEvents } from '@/pages/ai-re-act/hooks/type'
import useChatIPC from '@/pages/ai-re-act/hooks/useChatIPC'
import useGetSetState from '@/pages/pluginHub/hooks/useGetSetState'
Expand Down Expand Up @@ -118,12 +122,49 @@ export const HistoryAIReActChatProvider = memo(function HistoryAIReActChatProvid
const [setting, setSetting, getSetting] = useGetSetState<AIAgentSetting>(cloneDeep(AIAgentSettingDefault))
const [chats, setChats, getChats] = useGetSetState<AISession[]>([])
const [activeChat, setActiveChat] = useSafeState<AISession>()
const casualLoadingRef = useRef(false)
const initialRequestInCasualRef = useRef<string | null>(null)

const onHttpFuzzRequestChange = useMemoizedFn((data: AIAgentGrpcApi.HttpFuzzRequestChange) => {
if (!httpFuzzTabPageId) return

// casual 问答期间:`replace` 不自动写包;入队审阅(页内合并为「问答开始前快照 vs 最新一条 raw」)
if (casualLoadingRef.current && data?.op === 'replace') {
const nextRaw = data?.request?.raw
if (nextRaw != null && String(nextRaw).trim() !== '' && initialRequestInCasualRef.current != null) {
enqueueWebFuzzerCasualReplaceReview(httpFuzzTabPageId, {
original: initialRequestInCasualRef.current ?? '',
change: data,
})
}
return
}

applyHttpFuzzRequestChangeToWebFuzzerPage(httpFuzzTabPageId, data)
})

const [chatIPCData, events] = useChatIPC({
cacheDataStore,
onHttpFuzzRequestChange,
})

const { execute } = chatIPCData
const { execute, casualStatus } = chatIPCData

useEffect(() => {
if (!httpFuzzTabPageId) {
casualLoadingRef.current = false
initialRequestInCasualRef.current = null
return
}

if (!casualLoadingRef.current && casualStatus.loading) {
initialRequestInCasualRef.current = getWebFuzzerPageRequestString(httpFuzzTabPageId) ?? ''
} else if (casualLoadingRef.current && !casualStatus.loading) {
initialRequestInCasualRef.current = null
}

casualLoadingRef.current = casualStatus.loading
}, [casualStatus.loading, httpFuzzTabPageId])

const activeID = useCreation(() => {
return activeChat?.SessionID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const YakitDiffEditor: React.FC<YakitDiffEditorProps> = memo((props) => {
noWrap,
leftReadOnly = false,
rightReadOnly = false,
renderSideBySide = true,
} = props

const { t, i18n } = useI18nNamespaces(['yakitUi'])
Expand Down Expand Up @@ -119,6 +120,7 @@ export const YakitDiffEditor: React.FC<YakitDiffEditorProps> = memo((props) => {

diffEditorRef.current = monaco.createDiffEditor(diffDivRef.current, {
enableSplitViewResizing: false,
renderSideBySide,
originalEditable: !leftReadOnly,
readOnly: rightReadOnly,
automaticLayout: true,
Expand Down Expand Up @@ -185,13 +187,14 @@ export const YakitDiffEditor: React.FC<YakitDiffEditorProps> = memo((props) => {
useUpdateEffect(() => {
if (diffEditorRef.current) {
diffEditorRef.current.updateOptions({
renderSideBySide,
originalEditable: !leftReadOnly,
readOnly: rightReadOnly,
wordWrap: !!noWrap ? 'off' : 'on',
fontSize: fontSize,
})
}
}, [noWrap, leftReadOnly, rightReadOnly, fontSize])
}, [noWrap, leftReadOnly, rightReadOnly, fontSize, renderSideBySide])

// 强制更新默认值
useUpdateEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ export interface YakitDiffEditorProps {
leftReadOnly?: boolean
/** 右侧是否只读 */
rightReadOnly?: boolean
/** `false` 时为上下内联 diff(非左右分栏),默认 `true` */
renderSideBySide?: boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
.outerHost {
width: 100%;
height: 100%;
min-height: 0;
position: relative;
}

.editorHost {
width: 100%;
height: 100%;
min-height: 0;
}

.floatingBar {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 5px 10px;
border-radius: 6px;
background: var(--Colors-Use-Neutral-Bg-Hover);
border: 1px solid var(--Colors-Use-Neutral-Border);
box-shadow: 0 6px 28px var(--Colors-Use-Neutral-Shadow) 0 0 0 1px var(--Colors-Use-Neutral-Shadow);
font-size: 12px;
line-height: 1.35;
color: var(--Colors-Use-Neutral-Text-1-Title);
white-space: nowrap;
position: absolute;
right: 48px;
z-index: 50;
max-width: calc(100% - 24px);
}

.floatingNav {
color: var(--Colors-Use-Neutral-Text-3-Secondary);
font-variant-numeric: tabular-nums;
letter-spacing: 0.02em;
user-select: none;
min-width: 28px;
text-align: center;
}

.btnNav {
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin: 0;
padding: 0;
width: 20px;
height: 20px;
border: none;
border-radius: 4px;
font: inherit;
font-size: 14px;
line-height: 1;
color: var(--Colors-Use-Neutral-Text-3-Secondary);
background: transparent;
}

.btnNav:hover:not(:disabled) {
color: var(--Colors-Use-Main-Primary);
background: var(--Colors-Use-Neutral-Bg-Hover);
}

.btnNav:disabled {
cursor: default;
opacity: 0.4;
}

.floatingSep {
width: 1px;
height: 14px;
background: var(--Colors-Use-Neutral-Border);
flex-shrink: 0;
}

.btnUndo {
display: inline-flex;
align-items: center;
cursor: pointer;
margin: 0;
padding: 3px 8px;
border: none;
border-radius: 4px;
font: inherit;
color: var(--Colors-Use-Neutral-Text-3-Secondary);
background: transparent;
}

.btnUndo:hover:not(:disabled) {
color: var(--Colors-Use-Neutral-Text-1-Title);
background: var(--Colors-Use-Neutral-Bg-Hover);
}

.btnKeep {
display: inline-flex;
align-items: center;
cursor: pointer;
margin: 0;
padding: 4px 10px;
border: none;
border-radius: 4px;
font: inherit;
font-weight: 500;
color: var(--Colors-Use-Main-On-Primary);
background: var(--Colors-Use-Main-Primary);
box-shadow: 0 1px 0 var(--Colors-Use-Neutral-Shadow);
}

.btnKeep:hover:not(:disabled) {
filter: brightness(1.06);
}

.btnKeep:disabled,
.btnUndo:disabled {
cursor: default;
opacity: 0.55;
}
Loading
Loading