dsh-ant 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/client.js +144 -118
- package/conversation.js +106 -35
- package/delegation.js +464 -6
- package/index.js +10 -4
- package/locale/messages.json +885 -68
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -622,15 +622,15 @@ window.__ModuleLoader__.load({
|
|
|
622
622
|
const [defaults, setDefaults] = useState(null)
|
|
623
623
|
const [localConcurrency, setLocalConcurrency] = useState(null)
|
|
624
624
|
const [repositoryCacheLimitGib, setRepositoryCacheLimitGib] = useState(10)
|
|
625
|
+
const [ownerChallengeCode, setOwnerChallengeCode] = useState('')
|
|
625
626
|
const [botId, setBotId] = useState('')
|
|
626
627
|
const [conversationKind, setConversationKind] = useState('dm')
|
|
627
628
|
const [groupId, setGroupId] = useState('')
|
|
628
629
|
const [ruleDescription, setRuleDescription] = useState('')
|
|
630
|
+
const [triggerPhrases, setTriggerPhrases] = useState('')
|
|
629
631
|
const recognizedBaselineRef = useRef(null)
|
|
630
632
|
const recognizedDescriptionRef = useRef(null)
|
|
631
|
-
const autoAnalyzeDescriptionRef = useRef(null)
|
|
632
633
|
const recognitionRequestRef = useRef(0)
|
|
633
|
-
const recognitionTimerRef = useRef(null)
|
|
634
634
|
const [recognitionBusy, setRecognitionBusy] = useState(false)
|
|
635
635
|
const [recognitionMessage, setRecognitionMessage] = useState('')
|
|
636
636
|
const [missingRequired, setMissingRequired] = useState([])
|
|
@@ -642,7 +642,6 @@ window.__ModuleLoader__.load({
|
|
|
642
642
|
const [runner, setRunner] = useState('dsh')
|
|
643
643
|
const [reviewers, setReviewers] = useState(['dsh'])
|
|
644
644
|
const [parameters, setParameters] = useState([])
|
|
645
|
-
const [parallelAgentsOpen, setParallelAgentsOpen] = useState(false)
|
|
646
645
|
const [giteaToken, setGiteaToken] = useState('')
|
|
647
646
|
const [tokenConfigured, setTokenConfigured] = useState(false)
|
|
648
647
|
const [senderScope, setSenderScope] = useState('any')
|
|
@@ -703,6 +702,7 @@ window.__ModuleLoader__.load({
|
|
|
703
702
|
const taskPrOrigins = [...new Set(parameters.filter((item) => item.kind === 'gitea_pr')
|
|
704
703
|
.map((item) => normalizeServiceUrl(item.gitea_origin)).filter(Boolean))]
|
|
705
704
|
const selectedEnrollmentBound = selectedEnrollment?.device_bound_to_current === true
|
|
705
|
+
const ownerApprovalBound = selectedEnrollment?.owner_bound === true
|
|
706
706
|
const dmChatSettingAvailable = typeof selectedEnrollment?.dm_chat_enabled === 'boolean'
|
|
707
707
|
const dmChatEnabled = selectedEnrollment?.dm_chat_enabled !== false
|
|
708
708
|
const dmChatStatus = !selectedBot ? '先选择机器人'
|
|
@@ -714,7 +714,7 @@ window.__ModuleLoader__.load({
|
|
|
714
714
|
: !selectedEnrollmentBound ? '请先把机器人绑定到这台 DSH,再修改私聊设置。'
|
|
715
715
|
: !dmChatSettingAvailable ? '当前团队服务端尚未提供私聊开关,请先升级服务端。'
|
|
716
716
|
: dmChatEnabled
|
|
717
|
-
|
|
717
|
+
? '允许此机器人接收私聊。匹配任务卡的请求按预授权执行;没有匹配卡片的明确任务可转给已绑定主人逐次审批。'
|
|
718
718
|
: '新私聊消息不会交给 DSH;已提交任务仍会在原私聊回复。已开放能力不撤销,重新开启后未过期能力恢复触发。'
|
|
719
719
|
const availableGroups = groups.filter((group) => group.bot_fingerprint === selectedBot?.fingerprint)
|
|
720
720
|
const groupLabel = (group) => {
|
|
@@ -744,9 +744,8 @@ window.__ModuleLoader__.load({
|
|
|
744
744
|
: !selectedBot ? '已有协作机器人;请选择一台,查看已开放的能力和聊天范围。'
|
|
745
745
|
: authorizationLoadError ? `“${selectedBot.name}”已启用协作;已开放任务暂未读取,请刷新状态。`
|
|
746
746
|
: !dmChatEnabled ? `“${selectedBot.name}”已启用协作;私聊已关闭,群聊仍按各自设置工作。`
|
|
747
|
-
: selectedTaskCount === 0 ? `“${selectedBot.name}
|
|
748
|
-
: `“${selectedBot.name}”已启用协作 · ${selectedTaskCount}
|
|
749
|
-
const nativeReviewerSelected = reviewers.some((item) => ['codex', 'claude-code'].includes(item))
|
|
747
|
+
: selectedTaskCount === 0 ? `“${selectedBot.name}”已启用协作;绑定审批私聊后,未配置的明确任务会先问你。常用任务可建卡直接放行。`
|
|
748
|
+
: `“${selectedBot.name}”已启用协作 · ${selectedTaskCount} 项预授权能力。其他明确任务可交给主人逐次审批。`
|
|
750
749
|
const hasPrParameter = parameters.some((item) => item.kind === 'gitea_pr')
|
|
751
750
|
const hasSelectedPrRule = activeCards.some((card) => card.bot_fingerprint === selectedBot?.fingerprint
|
|
752
751
|
&& Array.isArray(card.parameters) && card.parameters.some((rule) => rule.kind === 'gitea_pr'))
|
|
@@ -756,17 +755,21 @@ window.__ModuleLoader__.load({
|
|
|
756
755
|
const codexAvailable = executors.some((item) => item.id === 'codex' && item.available)
|
|
757
756
|
const claudeCodeAvailable = executors.some((item) => item.id === 'claude-code' && item.available)
|
|
758
757
|
const dshAvailable = executors.some((item) => item.id === 'dsh' && item.available)
|
|
759
|
-
const
|
|
758
|
+
const executorUnavailableReason = executors.find((item) => item.reason)?.reason || null
|
|
760
759
|
const reviewerLabel = (id) => ({ dsh: 'DSH', codex: 'Codex', 'claude-code': 'Claude Code' })[id] || id
|
|
761
760
|
const cardReviewerSummary = (card) => {
|
|
762
761
|
const selected = Array.isArray(card.reviewers) && card.reviewers.length ? card.reviewers : [card.runner]
|
|
763
|
-
const unavailable = selected.filter((runner) => runner
|
|
764
|
-
if (card.runner
|
|
762
|
+
const unavailable = selected.filter((runner) => !executors.some((item) => item.id === runner && item.available))
|
|
763
|
+
if (unavailable.includes(card.runner)) return translateLocaleText('{executor} 默认执行方暂不可用',
|
|
765
764
|
{ executor: reviewerLabel(card.runner) })
|
|
765
|
+
const additional = selected.filter((runner) => runner !== card.runner)
|
|
766
|
+
const selectedSummary = additional.length
|
|
767
|
+
? translateLocaleText('默认 {executor};交叉审查:{reviewers}',
|
|
768
|
+
{ executor: reviewerLabel(card.runner), reviewers: additional.map(reviewerLabel).join('、') })
|
|
769
|
+
: translateLocaleText('{executor} 默认执行', { executor: reviewerLabel(card.runner) })
|
|
766
770
|
return unavailable.length
|
|
767
|
-
?
|
|
768
|
-
|
|
769
|
-
: translateLocaleText('DSH 任务 Agent')
|
|
771
|
+
? `${selectedSummary};${unavailable.map(reviewerLabel).join('、')} 暂不可用`
|
|
772
|
+
: selectedSummary
|
|
770
773
|
}
|
|
771
774
|
const requesterSummary = senderScope === 'allowlist'
|
|
772
775
|
? translateLocaleText('仅指定成员:{member_ids}',
|
|
@@ -775,8 +778,11 @@ window.__ModuleLoader__.load({
|
|
|
775
778
|
const resultRouteSummary = translateLocaleText(conversationKind === 'group'
|
|
776
779
|
? '回复到原群(群内可见)' : '回复到发起任务的私聊')
|
|
777
780
|
const ruleSummaryCurrent = recognizedDescriptionRef.current === ruleDescription.trim()
|
|
778
|
-
const ruleSummaryPending =
|
|
779
|
-
const
|
|
781
|
+
const ruleSummaryPending = recognitionBusy
|
|
782
|
+
const ruleSummaryDirty = Boolean(ruleDescription.trim() && !ruleSummaryCurrent)
|
|
783
|
+
const ruleTriggerSummary = triggerPhrases.split('\n').map((item) => item.trim()).filter(Boolean)
|
|
784
|
+
const ruleSummaryReady = Boolean(ruleSummaryCurrent
|
|
785
|
+
&& (title || intent || ruleTriggerSummary.length || parameters.length || taskPrompt))
|
|
780
786
|
const missingHarnessInputs = [...new Set([
|
|
781
787
|
...missingRequired,
|
|
782
788
|
...(parameters.some((rule) => rule.kind === 'gitea_pr'
|
|
@@ -809,26 +815,26 @@ window.__ModuleLoader__.load({
|
|
|
809
815
|
? `请求时还需提供:${parameters.map(parameterSummary).join(';')}`
|
|
810
816
|
: '无需额外参数,按请求中的内容处理'
|
|
811
817
|
const ruleSummaryNarrative = ruleSummaryReady
|
|
812
|
-
? `${intent.trim() || title.trim()}${taskPrompt.trim() ? `;${taskPrompt.trim()}` : ''};${recognizedInputsSummary}`
|
|
818
|
+
? `${ruleTriggerSummary.length ? `消息以“${ruleTriggerSummary.join('”或“')}”开头时,` : ''}${intent.trim() || title.trim()}${taskPrompt.trim() ? `;${taskPrompt.trim()}` : ''};${recognizedInputsSummary}`
|
|
813
819
|
: '识别后会用一段摘要呈现系统理解的任务。'
|
|
814
820
|
const executorSummary = translateLocaleText(runner === 'codex' ? 'DSH Codex 子 Agent'
|
|
815
821
|
: runner === 'claude-code' ? 'DSH Claude Code 子 Agent' : 'DSH · 当前授权模型'
|
|
816
822
|
)
|
|
817
|
-
const parallelAgentsSummary = reviewers.filter((item) => item !== runner).map(reviewerLabel).join('、')
|
|
818
823
|
const cardBlockReason = enrollmentLoadError ? '暂时无法核对机器人是否已启用协作,请刷新状态后再试。'
|
|
819
824
|
: !botConnected || !selectedEnrollmentBound ? '先在上方把机器人绑定到这台 DSH。'
|
|
820
825
|
: loadFailures.includes('settings') || defaults?.task_rule_schema_version !== 3
|
|
821
|
-
? '
|
|
826
|
+
? '团队服务端尚未支持任务触发规则与运行时授权核验;请先升级 ANT 服务端。'
|
|
822
827
|
: !ruleDescription.trim() ? '请先用自然语言描述要做的任务。'
|
|
823
828
|
: recognizedDescriptionRef.current !== ruleDescription.trim()
|
|
824
|
-
? 'AI
|
|
829
|
+
? recognitionBusy ? 'AI 正在检查当前描述;分析完成后再开放。' : '描述已修改,请点击“立即分析”更新任务理解后再开放。'
|
|
825
830
|
: !title.trim() || !intent.trim() || !taskPrompt.trim() ? '等待 AI 生成任务理解和处理要求。'
|
|
831
|
+
: !ruleTriggerSummary.length ? '任务没有明确触发开头;请在描述中写清楚请求消息以什么短语开头,再重新分析。'
|
|
826
832
|
: missingHarnessInputs.length ? `任务范围还有必需信息未明确:${missingHarnessInputs.join('、')}。请补充描述。`
|
|
827
833
|
: conversationKind === 'group' && loadFailures.includes('groups') ? '暂时无法核对目标群,请刷新状态后再试。'
|
|
828
834
|
: conversationKind === 'group' && !groupId ? '请在“请求范围”中选择目标群;若列表为空,让群成员先 @机器人,再刷新群列表。'
|
|
829
835
|
: senderScope === 'allowlist' && !senderIds.trim() ? '请填写可请求成员的 IM ID。'
|
|
830
|
-
|
|
831
|
-
?
|
|
836
|
+
: reviewers.some((item) => !executors.some((executor) => executor.id === item && executor.available))
|
|
837
|
+
? `这台 DSH 尚未启用所选执行器。${executorUnavailableReason || '请先启用对应 DSH 子 Agent 提供方。'}`
|
|
832
838
|
: parameters.some((rule) => rule.kind === 'gitea_pr') && !tokenConfigured ? '请先在“本机与任务”中保存本机 Gitea 只读令牌。'
|
|
833
839
|
: parameters.some((rule) => rule.kind === 'gitea_pr'
|
|
834
840
|
&& (typeof rule.gitea_origin !== 'string' || !normalizeServiceUrl(rule.gitea_origin) || !rule.repository))
|
|
@@ -838,11 +844,6 @@ window.__ModuleLoader__.load({
|
|
|
838
844
|
? `${translateLocaleText('任务描述中的 Gitea 来源必须与此机器人的连接器主机一致({origin});为保护令牌,ANT 不会向其他主机发送凭据。', { origin: selectedGiteaOrigin })} ${translateLocaleText('请在描述中改用该主机下的 PR 链接并重新分析。')}`
|
|
839
845
|
: taskPrOrigins.length > 1
|
|
840
846
|
? '同一任务中的 PR 资源必须来自同一个 Gitea 主机。'
|
|
841
|
-
: nativeReviewerSelected && (parameters.filter((rule) => rule.kind === 'gitea_pr').length !== 1
|
|
842
|
-
|| parameters.some((rule) => !['gitea_pr', 'git_sha'].includes(rule.kind)))
|
|
843
|
-
? 'Codex 和 Claude Code 当前只支持一个 Gitea PR 资源连接器;任务具体做审查、总结或解释仍由自然语言描述决定。'
|
|
844
|
-
: nativeReviewerSelected && !parameters.find((rule) => rule.kind === 'gitea_pr')?.required
|
|
845
|
-
? '使用本机 Provider 时,Gitea PR 资源必须是必填项。'
|
|
846
847
|
: reviewers.includes('dsh') && !dshAvailable
|
|
847
848
|
? '这台 DSH 尚未准备好任务执行器。'
|
|
848
849
|
: ''
|
|
@@ -856,10 +857,8 @@ window.__ModuleLoader__.load({
|
|
|
856
857
|
if (!next.includes(runner)) setRunner(next[0])
|
|
857
858
|
}
|
|
858
859
|
const selectRunner = (id) => {
|
|
860
|
+
if (!reviewers.includes(id)) return
|
|
859
861
|
setRunner(id)
|
|
860
|
-
setReviewers((current) => current.length > 1
|
|
861
|
-
? [...new Set([...current, id])]
|
|
862
|
-
: [id])
|
|
863
862
|
}
|
|
864
863
|
const startNewCard = (context = {}) => {
|
|
865
864
|
setEditingCardId(null); setEditingExpiresAt(null)
|
|
@@ -868,12 +867,12 @@ window.__ModuleLoader__.load({
|
|
|
868
867
|
setRecognitionMessage('')
|
|
869
868
|
recognizedBaselineRef.current = null
|
|
870
869
|
recognizedDescriptionRef.current = null
|
|
871
|
-
autoAnalyzeDescriptionRef.current = null
|
|
872
870
|
recognitionRequestRef.current += 1
|
|
873
871
|
setRuleDescription('')
|
|
872
|
+
setTriggerPhrases('')
|
|
874
873
|
setMissingRequired([]); setSuggestions([]); setRuleExamples([])
|
|
875
874
|
setTitle(''); setIntent(''); setTaskPrompt(''); setRunner('dsh')
|
|
876
|
-
setReviewers(['dsh'])
|
|
875
|
+
setReviewers(['dsh'])
|
|
877
876
|
setParameters([]); setConversationKind(context.conversationKind || 'dm')
|
|
878
877
|
setGroupId(context.groupId || '')
|
|
879
878
|
setSenderScope('any'); setSenderIds(''); setDays(7); setCreateOpen(true)
|
|
@@ -896,6 +895,7 @@ window.__ModuleLoader__.load({
|
|
|
896
895
|
else if (headIndex < 0 && rules.length < 12) rules.push(headRule)
|
|
897
896
|
}
|
|
898
897
|
return { title: title || '', intent: card.intent || '', task_prompt: card.task_prompt || '',
|
|
898
|
+
trigger_phrases: Array.isArray(card.trigger_phrases) ? card.trigger_phrases.map((item) => item.trim()).filter(Boolean) : [],
|
|
899
899
|
parameters: rules, examples: Array.isArray(card.examples) ? card.examples : [],
|
|
900
900
|
missing_required: [], suggestions: [] }
|
|
901
901
|
}
|
|
@@ -903,23 +903,24 @@ window.__ModuleLoader__.load({
|
|
|
903
903
|
setSubmissionError('')
|
|
904
904
|
setBotId(card.bot_id)
|
|
905
905
|
setRecognitionMessage('')
|
|
906
|
-
autoAnalyzeDescriptionRef.current = null
|
|
907
906
|
recognitionRequestRef.current += 1
|
|
908
907
|
setEditingCardId(copy ? null : card.id); setEditingExpiresAt(copy ? null : card.expires_at)
|
|
909
908
|
const taskDraft = taskRuleDraftFromCard(card, copy ? `${card.title.slice(0, 94)}(副本)` : card.title)
|
|
910
909
|
recognizedBaselineRef.current = taskDraft
|
|
911
910
|
const existingDescription = card.rule_description || ''
|
|
912
911
|
recognizedDescriptionRef.current = existingDescription.trim() || null
|
|
913
|
-
setDraftNotice(
|
|
914
|
-
|
|
912
|
+
setDraftNotice(!taskDraft.trigger_phrases.length
|
|
913
|
+
? '这项旧任务没有明确触发短语;新版不会按它启动任务。请重新分析描述并检查生成的触发开头。'
|
|
914
|
+
: existingDescription.trim() ? ''
|
|
915
|
+
: '这项旧任务没有自然语言描述。请补充任务描述,让 AI 生成 Harness 后再开放。')
|
|
915
916
|
setRuleDescription(existingDescription)
|
|
917
|
+
setTriggerPhrases(taskDraft.trigger_phrases.join('\n'))
|
|
916
918
|
setMissingRequired([]); setSuggestions(taskDraft.suggestions); setRuleExamples(taskDraft.examples)
|
|
917
919
|
setTitle(taskDraft.title)
|
|
918
920
|
if (copy) setDays(7)
|
|
919
921
|
setIntent(taskDraft.intent)
|
|
920
922
|
setTaskPrompt(taskDraft.task_prompt); setRunner(card.runner)
|
|
921
923
|
setReviewers(Array.isArray(card.reviewers) && card.reviewers.length ? card.reviewers : [card.runner])
|
|
922
|
-
setParallelAgentsOpen(false)
|
|
923
924
|
setParameters(taskDraft.parameters)
|
|
924
925
|
setConversationKind(card.conversation_kind); setGroupId(card.conversation_id || '')
|
|
925
926
|
setSenderScope(card.sender_scope); setSenderIds((card.sender_ids || []).join(', '))
|
|
@@ -928,6 +929,7 @@ window.__ModuleLoader__.load({
|
|
|
928
929
|
const applyRuleDraft = (draft) => {
|
|
929
930
|
setTitle(draft.title)
|
|
930
931
|
setIntent(draft.intent)
|
|
932
|
+
setTriggerPhrases(draft.trigger_phrases.join('\n'))
|
|
931
933
|
setTaskPrompt(draft.task_prompt)
|
|
932
934
|
setParameters(draft.parameters)
|
|
933
935
|
setMissingRequired(draft.missing_required || [])
|
|
@@ -940,7 +942,6 @@ window.__ModuleLoader__.load({
|
|
|
940
942
|
setRecognitionMessage('先描述这项任务何时触发、要做什么以及涉及哪些资料。')
|
|
941
943
|
return
|
|
942
944
|
}
|
|
943
|
-
if (recognitionTimerRef.current) clearTimeout(recognitionTimerRef.current)
|
|
944
945
|
const requestNumber = ++recognitionRequestRef.current
|
|
945
946
|
setRecognitionBusy(true); setMessage(''); setRecognitionMessage('AI 正在分析必需范围、可选条件和执行方式…')
|
|
946
947
|
try {
|
|
@@ -953,6 +954,7 @@ window.__ModuleLoader__.load({
|
|
|
953
954
|
const candidate = {
|
|
954
955
|
title: typeof result.title === 'string' ? result.title : '',
|
|
955
956
|
intent: typeof result.intent === 'string' ? result.intent : '',
|
|
957
|
+
trigger_phrases: Array.isArray(result.trigger_phrases) ? result.trigger_phrases : [],
|
|
956
958
|
task_prompt: typeof result.task_prompt === 'string' ? result.task_prompt : '',
|
|
957
959
|
missing_required: Array.isArray(result.missing_required) ? result.missing_required : [],
|
|
958
960
|
suggestions: Array.isArray(result.suggestions) ? result.suggestions : [],
|
|
@@ -985,8 +987,8 @@ window.__ModuleLoader__.load({
|
|
|
985
987
|
}
|
|
986
988
|
}
|
|
987
989
|
if (requestNumber !== recognitionRequestRef.current || requestedDescription !== ruleDescription.trim()) return
|
|
988
|
-
if (!candidate.title || !candidate.intent || !candidate.task_prompt) {
|
|
989
|
-
throw new Error('AI
|
|
990
|
+
if (!candidate.title || !candidate.intent || !candidate.task_prompt || !candidate.trigger_phrases.length) {
|
|
991
|
+
throw new Error('AI 返回的任务理解或触发开头不完整。请补充描述后重试。')
|
|
990
992
|
}
|
|
991
993
|
const previous = recognizedBaselineRef.current
|
|
992
994
|
applyRuleDraft(candidate)
|
|
@@ -1001,14 +1003,6 @@ window.__ModuleLoader__.load({
|
|
|
1001
1003
|
if (requestNumber === recognitionRequestRef.current) setRecognitionBusy(false)
|
|
1002
1004
|
}
|
|
1003
1005
|
}
|
|
1004
|
-
useEffect(() => {
|
|
1005
|
-
if (autoAnalyzeDescriptionRef.current !== ruleDescription || !ruleDescription.trim()) return undefined
|
|
1006
|
-
const description = ruleDescription
|
|
1007
|
-
recognitionTimerRef.current = setTimeout(() => {
|
|
1008
|
-
if (autoAnalyzeDescriptionRef.current === description) void identifyRule(description)
|
|
1009
|
-
}, 900)
|
|
1010
|
-
return () => clearTimeout(recognitionTimerRef.current)
|
|
1011
|
-
}, [ruleDescription])
|
|
1012
1006
|
const saveGiteaToken = async () => {
|
|
1013
1007
|
if (!giteaToken.trim()) return
|
|
1014
1008
|
setBusy(true)
|
|
@@ -1033,7 +1027,22 @@ window.__ModuleLoader__.load({
|
|
|
1033
1027
|
const result = await readLocalJsonResponse(response)
|
|
1034
1028
|
if (!response.ok) throw new Error(result.message || '协作机器人启用失败。')
|
|
1035
1029
|
await load()
|
|
1036
|
-
setMessage('
|
|
1030
|
+
setMessage('协作机器人已启用。任务卡可预授权固定任务;绑定审批私聊后,没有匹配卡片的明确任务会逐次询问主人。')
|
|
1031
|
+
} catch (error) { setMessage(error.message) }
|
|
1032
|
+
finally { setBusy(false) }
|
|
1033
|
+
}
|
|
1034
|
+
const requestOwnerApprovalBinding = async () => {
|
|
1035
|
+
if (!selectedBot || !selectedEnrollmentBound) return
|
|
1036
|
+
setBusy(true); setOwnerChallengeCode('')
|
|
1037
|
+
try {
|
|
1038
|
+
const response = await fetch('/api/ant-teams/delegation/owner-challenge', {
|
|
1039
|
+
method: 'POST', headers: { 'content-type': 'application/json' },
|
|
1040
|
+
body: JSON.stringify({ bot_id: selectedBot.bot_id, bot_fingerprint: selectedBot.fingerprint }),
|
|
1041
|
+
})
|
|
1042
|
+
const result = await readLocalJsonResponse(response)
|
|
1043
|
+
if (!response.ok || typeof result.code !== 'string') throw new Error(result.message || '审批私聊绑定码获取失败。')
|
|
1044
|
+
setOwnerChallengeCode(result.code)
|
|
1045
|
+
setMessage(`请在 5 分钟内私聊此机器人,发送“绑定审批身份 ${result.code}”。绑定成功后,它才能把未配置任务的审批请求发给你。`)
|
|
1037
1046
|
} catch (error) { setMessage(error.message) }
|
|
1038
1047
|
finally { setBusy(false) }
|
|
1039
1048
|
}
|
|
@@ -1173,20 +1182,22 @@ window.__ModuleLoader__.load({
|
|
|
1173
1182
|
setSubmissionError(localizedReason); setMessage(localizedReason)
|
|
1174
1183
|
}
|
|
1175
1184
|
if (!selectedBot || !botConnected || !selectedEnrollmentBound) { reject('请先在这台 DSH 绑定选中的协作机器人。'); return }
|
|
1176
|
-
if (reviewers.some((item) => item !== 'dsh')) {
|
|
1177
|
-
reject('当前无法核验外部子 Agent 的逐任务文件、Git 和网络权限;请将任务执行方设为 DSH。'); return
|
|
1178
|
-
}
|
|
1179
1185
|
if (editingCardId && (!editingExpiresAt || editingExpiresAt <= Math.floor(Date.now() / 1000))) {
|
|
1180
1186
|
reject('这项能力已到期,无法继续编辑;请返回后重新开放一项能力。'); return
|
|
1181
1187
|
}
|
|
1182
1188
|
if (!ruleDescription.trim() || !title.trim() || !intent.trim() || !taskPrompt.trim()) {
|
|
1183
|
-
reject('
|
|
1189
|
+
reject('请填写任务描述并点击“立即分析”,检查摘要后再开放。'); return
|
|
1184
1190
|
}
|
|
1185
1191
|
const bytes = (value) => new TextEncoder().encode(value).length
|
|
1186
1192
|
if (bytes(ruleDescription.trim()) > 4000 || bytes(title.trim()) > 100
|
|
1187
1193
|
|| bytes(intent.trim()) > 1000 || bytes(taskPrompt.trim()) > 4000) {
|
|
1188
1194
|
reject('任务描述或识别摘要过长,请缩短描述并重新识别。'); return
|
|
1189
1195
|
}
|
|
1196
|
+
const triggerLines = triggerPhrases.split('\n').map((item) => item.normalize('NFKC').trim()).filter(Boolean)
|
|
1197
|
+
if (!triggerLines.length || triggerLines.length > 8 || triggerLines.some((item) => bytes(item) > 120)
|
|
1198
|
+
|| new Set(triggerLines.map((item) => item.toLowerCase())).size !== triggerLines.length) {
|
|
1199
|
+
reject('任务没有明确、唯一的触发开头;请在描述中写清楚消息以什么短语开头,再重新分析。'); return
|
|
1200
|
+
}
|
|
1190
1201
|
const normalized = parameters.map((rule) => ({ name: rule.name.trim(), kind: rule.kind,
|
|
1191
1202
|
description: rule.description.trim() || null,
|
|
1192
1203
|
required: rule.required, min: rule.min == null || rule.min === '' ? null : Number(rule.min),
|
|
@@ -1245,21 +1256,17 @@ window.__ModuleLoader__.load({
|
|
|
1245
1256
|
if (!reviewers.length || !reviewers.includes(runner)) {
|
|
1246
1257
|
reject('请至少选择一位任务执行 Agent,并设置普通请求的默认执行方。'); return
|
|
1247
1258
|
}
|
|
1248
|
-
if (nativeReviewerSelected && !((normalized.length === 1
|
|
1249
|
-
&& normalized[0].kind === 'gitea_pr' && normalized[0].required)
|
|
1250
|
-
|| (normalized.length === 2 && normalized.some((rule) => rule.kind === 'gitea_pr' && rule.required)
|
|
1251
|
-
&& normalized.some((rule) => rule.kind === 'git_sha' && rule.name === 'head_sha' && !rule.required)))) {
|
|
1252
|
-
reject('Codex 和 Claude Code 当前只支持一个必填 Gitea PR 资源连接器;任务行为仍由自然语言描述决定。'); return
|
|
1253
|
-
}
|
|
1254
1259
|
const scope = conversationKind === 'group'
|
|
1255
1260
|
? translateLocaleText('群 {group_id}', { group_id: groupId })
|
|
1256
1261
|
: translateLocaleText('私聊')
|
|
1257
1262
|
const resultDestination = translateLocaleText(conversationKind === 'group'
|
|
1258
1263
|
? '原群(群内可见)' : '发起任务的私聊')
|
|
1264
|
+
const triggerSummary = translateLocaleText('只有请求以“{triggers}”开头时才会触发此任务',
|
|
1265
|
+
{ triggers: triggerLines.join('”或“') })
|
|
1259
1266
|
const executionDetails = {
|
|
1260
1267
|
dsh: translateLocaleText('DSH 使用获准的团队模型处理对话内容和 ANT 已核验后提供的资源。'),
|
|
1261
|
-
codex: translateLocaleText('Codex
|
|
1262
|
-
'claude-code': translateLocaleText('Claude Code
|
|
1268
|
+
codex: translateLocaleText('Codex 使用这台 DSH 的 Provider Profile 权限;可访问范围由 Codex/DSH 本机配置决定。任务描述不会限制操作系统权限。'),
|
|
1269
|
+
'claude-code': translateLocaleText('Claude Code 使用这台 DSH 的 Provider Profile 权限;可访问范围由 Claude Code/DSH 本机配置决定。任务描述不会限制操作系统权限。'),
|
|
1263
1270
|
}
|
|
1264
1271
|
const executionInfo = reviewers.length > 1
|
|
1265
1272
|
? translateLocaleText('普通请求默认由 {runner} 执行;请求人明确要求多 Agent 分别处理时,会并行启动 {reviewers},分别返回结果。{details}',
|
|
@@ -1267,10 +1274,10 @@ window.__ModuleLoader__.load({
|
|
|
1267
1274
|
details: reviewers.map((item) => executionDetails[item]).join(' ') })
|
|
1268
1275
|
: executionDetails[reviewers[0]]
|
|
1269
1276
|
const actionDescription = editingCardId
|
|
1270
|
-
? translateLocaleText('更新“{title}”后,{requesterSummary}可在{scope}
|
|
1271
|
-
{ title, requesterSummary, scope, resultDestination, expiry: formatLocaleDate(editingExpiresAt * 1000) })
|
|
1272
|
-
: translateLocaleText('开放“{title}”后,{requesterSummary}可在{scope}
|
|
1273
|
-
{ title, requesterSummary, scope, resultDestination, days: formatLocaleNumber(days) })
|
|
1277
|
+
? translateLocaleText('更新“{title}”后,{requesterSummary}可在{scope}{triggerSummary}。旧待确认请求将失效,已提交任务继续使用提交时的配置。结果{resultDestination}。到期时间保持为 {expiry}。',
|
|
1278
|
+
{ title, requesterSummary, scope, triggerSummary, resultDestination, expiry: formatLocaleDate(editingExpiresAt * 1000) })
|
|
1279
|
+
: translateLocaleText('开放“{title}”后,{requesterSummary}可在{scope}{triggerSummary}有效期 {days} 天;结果{resultDestination}。',
|
|
1280
|
+
{ title, requesterSummary, scope, triggerSummary, resultDestination, days: formatLocaleNumber(days) })
|
|
1274
1281
|
if (!confirmLocalized(`${actionDescription}${executionInfo}${translateLocaleText('请确认。')}`)) return
|
|
1275
1282
|
setBusy(true)
|
|
1276
1283
|
try {
|
|
@@ -1278,7 +1285,7 @@ window.__ModuleLoader__.load({
|
|
|
1278
1285
|
method: editingCardId ? 'PUT' : 'POST', headers: { 'content-type': 'application/json' },
|
|
1279
1286
|
body: JSON.stringify({ ...(editingCardId ? { id: editingCardId } : {}),
|
|
1280
1287
|
bot_id: selectedBot.bot_id, bot_fingerprint: selectedBot.fingerprint,
|
|
1281
|
-
title, rule_description: ruleDescription.trim(), trigger_phrases:
|
|
1288
|
+
title, rule_description: ruleDescription.trim(), trigger_phrases: triggerLines,
|
|
1282
1289
|
intent, examples: ruleExamples,
|
|
1283
1290
|
parameters: normalized, task_prompt: taskPrompt, runner, reviewers, workspace: null,
|
|
1284
1291
|
sender_scope: senderScope, sender_ids: senderScope === 'allowlist'
|
|
@@ -1288,7 +1295,7 @@ window.__ModuleLoader__.load({
|
|
|
1288
1295
|
})
|
|
1289
1296
|
const result = await readLocalJsonResponse(response)
|
|
1290
1297
|
if (!response.ok && result.code === 'IM_TASK_RULE_REQUIRED') {
|
|
1291
|
-
throw new Error('当前 ANT
|
|
1298
|
+
throw new Error('当前 ANT 服务端不支持任务触发规则,请升级服务端后再开放任务。')
|
|
1292
1299
|
}
|
|
1293
1300
|
if (!response.ok && reviewers.includes('claude-code') && result.code === 'INVALID_REQUEST') {
|
|
1294
1301
|
throw new Error('当前团队服务端可能尚不支持 Claude Code 审查配置。请管理员升级服务端后刷新重试。')
|
|
@@ -1311,11 +1318,9 @@ window.__ModuleLoader__.load({
|
|
|
1311
1318
|
}
|
|
1312
1319
|
recognizedBaselineRef.current = null
|
|
1313
1320
|
recognizedDescriptionRef.current = null
|
|
1314
|
-
autoAnalyzeDescriptionRef.current = null
|
|
1315
1321
|
recognitionRequestRef.current += 1
|
|
1316
1322
|
setRuleDescription(''); setMissingRequired([]); setSuggestions([]); setRuleExamples([])
|
|
1317
1323
|
setTitle(''); setIntent(''); setTaskPrompt(''); setParameters([]); setRunner('dsh'); setReviewers(['dsh'])
|
|
1318
|
-
setParallelAgentsOpen(false)
|
|
1319
1324
|
setEditingCardId(null); setEditingExpiresAt(null)
|
|
1320
1325
|
await load()
|
|
1321
1326
|
setCreateOpen(false)
|
|
@@ -1340,14 +1345,15 @@ window.__ModuleLoader__.load({
|
|
|
1340
1345
|
}
|
|
1341
1346
|
const copyCardToDraft = (card) => {
|
|
1342
1347
|
setEditingCardId(null); setEditingExpiresAt(null)
|
|
1343
|
-
setParallelAgentsOpen(false)
|
|
1344
1348
|
const copiedDescription = card.rule_description || ''
|
|
1345
1349
|
recognizedDescriptionRef.current = copiedDescription.trim() || null
|
|
1346
|
-
autoAnalyzeDescriptionRef.current = null
|
|
1347
1350
|
recognitionRequestRef.current += 1
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
+
const hasTriggerRule = Array.isArray(card.trigger_phrases) && card.trigger_phrases.length > 0
|
|
1352
|
+
setDraftNotice(!hasTriggerRule
|
|
1353
|
+
? '已复制旧规则。它没有明确触发短语;请重新分析并检查生成的触发开头。'
|
|
1354
|
+
: copiedDescription.trim()
|
|
1355
|
+
? '已复制到新草稿。复制不保留原有效期;请检查任务描述和请求范围。'
|
|
1356
|
+
: '这项旧任务没有自然语言描述。请补充任务描述,让 AI 生成 Harness 后再开放。')
|
|
1351
1357
|
const cardBot = bots.find((bot) => bot.fingerprint === card.bot_fingerprint)
|
|
1352
1358
|
const titleChars = Array.from(translateLocaleText('复制:{title}', {
|
|
1353
1359
|
title: card.title || translateLocaleText('未命名能力'),
|
|
@@ -1357,6 +1363,7 @@ window.__ModuleLoader__.load({
|
|
|
1357
1363
|
recognizedBaselineRef.current = taskDraft
|
|
1358
1364
|
setBotId(card.bot_id || cardBot?.bot_id || '')
|
|
1359
1365
|
setRuleDescription(copiedDescription)
|
|
1366
|
+
setTriggerPhrases(taskDraft.trigger_phrases.join('\n'))
|
|
1360
1367
|
setMissingRequired([]); setSuggestions(taskDraft.suggestions); setRuleExamples(taskDraft.examples)
|
|
1361
1368
|
setTitle(taskDraft.title)
|
|
1362
1369
|
setIntent(taskDraft.intent)
|
|
@@ -1404,7 +1411,16 @@ window.__ModuleLoader__.load({
|
|
|
1404
1411
|
style: secondaryButtonStyle }, '检查 DSH-IM 连接') : null,
|
|
1405
1412
|
selectedBot && !selectedEnrollmentBound ? h('button', { type: 'button', disabled: busy || !botConnected || enrollmentLoadError,
|
|
1406
1413
|
onClick: () => void enrollBot(), style: primaryButtonStyle },
|
|
1407
|
-
selectedEnrollment ? '绑定原协作配置到这台 DSH' : '启用并绑定到这台 DSH') : null
|
|
1414
|
+
selectedEnrollment ? '绑定原协作配置到这台 DSH' : '启用并绑定到这台 DSH') : null,
|
|
1415
|
+
selectedEnrollmentBound && botConnected ? h('div', { style: { display: 'grid', gap: 6 } },
|
|
1416
|
+
h('p', { style: mutedTextStyle }, ownerApprovalBound
|
|
1417
|
+
? '审批私聊已绑定;没有匹配任务卡的明确任务会发给你逐次审批。'
|
|
1418
|
+
: '绑定一次你的 IM 私聊身份后,就能审批没有匹配任务卡的明确任务。'),
|
|
1419
|
+
h('button', { type: 'button', disabled: busy,
|
|
1420
|
+
onClick: () => void requestOwnerApprovalBinding(), style: secondaryButtonStyle },
|
|
1421
|
+
ownerApprovalBound ? '重新绑定审批私聊' : '绑定审批私聊'),
|
|
1422
|
+
ownerChallengeCode ? h('p', { role: 'status', style: feedbackNoticeStyle },
|
|
1423
|
+
`请在 5 分钟内私聊此机器人发送:绑定审批身份 ${ownerChallengeCode}`) : null) : null)
|
|
1408
1424
|
const groupTaskStatusPanel = selectedEnrollmentBound && botConnected ? h('section', {
|
|
1409
1425
|
id: 'ant-group-task-status', role: 'region', 'aria-label': '各群聊天与任务状态', tabIndex: -1,
|
|
1410
1426
|
style: { ...collaborationCardStyle, gap: 10 } },
|
|
@@ -1415,7 +1431,7 @@ window.__ModuleLoader__.load({
|
|
|
1415
1431
|
loading ? '读取中…' : '刷新群列表')),
|
|
1416
1432
|
h('p', { style: mutedTextStyle }, groupChatLoadFailed
|
|
1417
1433
|
? '群列表暂不可用,请刷新状态后重试。'
|
|
1418
|
-
: availableGroups.length ? '
|
|
1434
|
+
: availableGroups.length ? '此开关只控制普通聊天。任务卡可预授权固定任务;绑定主人审批私聊后,群成员 @机器人发起的其他明确任务也可逐次审批。名称取自 DSH-IM 已保存目标。'
|
|
1419
1435
|
: '先在目标群 @机器人,再刷新状态发现群。'),
|
|
1420
1436
|
availableGroups.length ? h('div', { id: 'ant-group-card-grid', style: collaborationGridStyle },
|
|
1421
1437
|
...availableGroups.map((group) => {
|
|
@@ -1447,7 +1463,7 @@ window.__ModuleLoader__.load({
|
|
|
1447
1463
|
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'start', gap: 12, flexWrap: 'wrap' } },
|
|
1448
1464
|
h('div', { style: { display: 'grid', gap: 4 } },
|
|
1449
1465
|
h('h3', { style: sectionTitleStyle }, '协作总览'),
|
|
1450
|
-
h('p', { style: mutedTextStyle }, '
|
|
1466
|
+
h('p', { style: mutedTextStyle }, '选择机器人并绑定一次主人审批私聊。任务卡可预授权常用任务;其他请求由主人逐次决定。')),
|
|
1451
1467
|
h('span', { style: { ...mutedTextStyle, padding: '4px 9px', borderRadius: 999,
|
|
1452
1468
|
backgroundColor: 'var(--dsw-alias-bg-layer-2)' } }, selectedBot ? selectedBot.name : '尚未选择机器人')),
|
|
1453
1469
|
loadFailures.length ? h('p', { role: 'status', style: mutedTextStyle },
|
|
@@ -1485,9 +1501,14 @@ window.__ModuleLoader__.load({
|
|
|
1485
1501
|
: translateLocaleText('私聊')
|
|
1486
1502
|
const requester = translateLocaleText(card.sender_scope === 'allowlist' ? '指定成员可请求'
|
|
1487
1503
|
: card.conversation_kind === 'group' ? '群成员可请求' : '可私聊者可请求')
|
|
1488
|
-
const
|
|
1504
|
+
const missingTriggerPhrase = !Array.isArray(card.trigger_phrases) || card.trigger_phrases.length === 0
|
|
1505
|
+
const configuredCardRunners = Array.isArray(card.reviewers) && card.reviewers.length
|
|
1506
|
+
? card.reviewers : [card.runner]
|
|
1507
|
+
const blockedExternalExecutor = !configuredCardRunners.every((runner) =>
|
|
1508
|
+
executors.some((executor) => executor.id === runner && executor.available))
|
|
1489
1509
|
const examplesText = Array.isArray(card.examples) ? card.examples.join('、') : ''
|
|
1490
1510
|
const requesterIds = card.sender_scope === 'allowlist' && Array.isArray(card.sender_ids) ? card.sender_ids.join('、') : ''
|
|
1511
|
+
const triggerSummary = Array.isArray(card.trigger_phrases) ? card.trigger_phrases.join('、') : ''
|
|
1491
1512
|
const remainingDaysLabel = remainingDays <= 7 ? 'var(--dsw-alias-state-warning-primary, var(--dsw-alias-label-secondary))'
|
|
1492
1513
|
: 'var(--dsw-alias-label-secondary)'
|
|
1493
1514
|
return h('article', { key: card.id, style: { ...collaborationCardStyle, padding: 12, gap: 8 } },
|
|
@@ -1504,7 +1525,10 @@ window.__ModuleLoader__.load({
|
|
|
1504
1525
|
})),
|
|
1505
1526
|
blockedExternalExecutor ? h('p', { role: 'status', style: { ...mutedTextStyle,
|
|
1506
1527
|
color: 'var(--dsw-alias-state-warning-primary, var(--dsw-alias-label-secondary))' } },
|
|
1507
|
-
'
|
|
1528
|
+
'此任务暂不可执行:这台 DSH 尚未启用所选的全部执行器。请启用对应的 DSH 子 Agent 提供方后刷新。') : null,
|
|
1529
|
+
missingTriggerPhrase ? h('p', { role: 'status', style: { ...mutedTextStyle,
|
|
1530
|
+
color: 'var(--dsw-alias-state-warning-primary, var(--dsw-alias-label-secondary))' } },
|
|
1531
|
+
'这项旧任务没有明确触发开头,不会自动启动。点击“编辑”,重新分析并复核触发短语。') : null,
|
|
1508
1532
|
card.rule_description
|
|
1509
1533
|
? h('span', { style: { ...mutedTextStyle, overflowWrap: 'anywhere' } }, rawLocaleText(card.rule_description))
|
|
1510
1534
|
: h('span', { role: 'status', style: { ...mutedTextStyle, color: 'var(--dsw-alias-state-warning-primary, var(--dsw-alias-label-secondary))' } },
|
|
@@ -1513,6 +1537,7 @@ window.__ModuleLoader__.load({
|
|
|
1513
1537
|
h('summary', { style: { cursor: 'pointer', color: 'var(--dsw-alias-link)', fontSize: 13 } }, '查看规则说明'),
|
|
1514
1538
|
h('div', { style: { display: 'grid', gap: 4, paddingTop: 6 } },
|
|
1515
1539
|
card.rule_description ? h('p', { style: { ...mutedTextStyle, overflowWrap: 'anywhere' } }, rawLocaleText(card.rule_description)) : null,
|
|
1540
|
+
triggerSummary ? h('p', { style: { ...mutedTextStyle, overflowWrap: 'anywhere' } }, '触发开头:', rawLocaleText(triggerSummary)) : null,
|
|
1516
1541
|
requesterIds ? h('p', { style: { ...mutedTextStyle, overflowWrap: 'anywhere' } }, '允许请求的 IM 用户:', rawLocaleText(requesterIds)) : null,
|
|
1517
1542
|
examplesText ? h('p', { style: mutedTextStyle }, '请求示例:', rawLocaleText(examplesText)) : null,
|
|
1518
1543
|
Array.isArray(card.parameters) && card.parameters.length
|
|
@@ -1599,25 +1624,26 @@ window.__ModuleLoader__.load({
|
|
|
1599
1624
|
h('div', { style: { display: 'grid', gap: 9, minWidth: 0 } },
|
|
1600
1625
|
h('label', null, '描述规则', h('textarea', { required: true, maxLength: 4000, rows: 4, value: ruleDescription,
|
|
1601
1626
|
onChange: (event) => {
|
|
1602
|
-
autoAnalyzeDescriptionRef.current = event.target.value
|
|
1603
1627
|
recognitionRequestRef.current += 1
|
|
1604
1628
|
setRuleDescription(event.target.value)
|
|
1605
1629
|
setRecognitionBusy(false)
|
|
1606
|
-
setRecognitionMessage(event.target.value.trim() ? '
|
|
1630
|
+
setRecognitionMessage(event.target.value.trim() ? '描述已更新,点击“立即分析”检查任务。' : '')
|
|
1607
1631
|
},
|
|
1608
1632
|
placeholder: '用日常语言说明要完成什么、可处理哪些资料和希望怎样返回。例如:审查来自 https://gitea.example.com/team/shop 的 PR,指出可定位的问题,不修改代码;请求人可指定 Head SHA,未指定时用最新 Head。', style: inputStyle })),
|
|
1609
|
-
h('p', { style: mutedTextStyle }, 'AI
|
|
1633
|
+
h('p', { style: mutedTextStyle }, 'AI 不会自动分析;点击“立即分析”后才会检查必需范围、缺失信息和可选条件。执行方、请求人、群范围和有效期由下方通用授权控制。'),
|
|
1610
1634
|
h('div', { style: { display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' } },
|
|
1611
1635
|
h('button', { type: 'button', disabled: recognitionBusy || busy || !ruleDescription.trim(),
|
|
1612
1636
|
onClick: () => void identifyRule(), style: secondaryButtonStyle }, recognitionBusy ? 'AI 正在分析…' : ruleSummaryReady ? '立即重新分析' : '立即分析'),
|
|
1613
|
-
h('span', { style: mutedTextStyle }, '
|
|
1637
|
+
h('span', { style: mutedTextStyle }, '每次点击都会调用当前团队模型并计入用量;只生成建议和待复核草稿,不会开放任务。修改描述后需再次点击。')),
|
|
1614
1638
|
recognitionMessage ? h('p', { role: 'status', 'aria-live': 'polite', style: feedbackNoticeStyle }, recognitionMessage) : null),
|
|
1615
1639
|
h('section', { role: 'region', 'aria-label': 'AI 任务助手', style: { ...panelStyle, padding: 10, gap: 7, minWidth: 0 } },
|
|
1616
1640
|
h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 } },
|
|
1617
1641
|
h('strong', null, ruleSummaryPending ? 'AI 正在检查当前描述' : title || 'AI 任务助手'),
|
|
1618
|
-
h('span', { style: mutedTextStyle }, ruleSummaryPending ? '
|
|
1642
|
+
h('span', { style: mutedTextStyle }, ruleSummaryPending ? '正在分析' : ruleSummaryReady ? '待复核 · 尚未开放'
|
|
1643
|
+
: ruleSummaryDirty ? '描述已更新' : '填写描述后点击分析')),
|
|
1619
1644
|
h('p', { style: { ...mutedTextStyle, overflowWrap: 'anywhere' } }, ruleSummaryPending
|
|
1620
|
-
? 'AI 正在根据当前描述更新任务理解。上一次分析结果暂不用于授权开放。'
|
|
1645
|
+
? 'AI 正在根据当前描述更新任务理解。上一次分析结果暂不用于授权开放。'
|
|
1646
|
+
: ruleSummaryDirty ? '描述已更新。点击“立即分析”生成当前任务理解;旧结果暂不用于授权开放。' : ruleSummaryNarrative),
|
|
1621
1647
|
ruleSummaryReady && missingHarnessInputs.length ? h('p', { role: 'status', style: { ...mutedTextStyle,
|
|
1622
1648
|
color: 'var(--dsw-alias-state-warning-primary, var(--dsw-alias-label-secondary))' } },
|
|
1623
1649
|
`还需要明确:${missingHarnessInputs.join(';')}`) : ruleSummaryReady
|
|
@@ -1626,40 +1652,40 @@ window.__ModuleLoader__.load({
|
|
|
1626
1652
|
ruleSummaryReady && ruleExamples.length ? h('p', { style: mutedTextStyle }, `自然请求示例:${ruleExamples.join(';')}`) : null,
|
|
1627
1653
|
h('p', { style: mutedTextStyle }, ruleSummaryReady
|
|
1628
1654
|
? '草稿未开放。检查任务理解、必需范围和建议;有误就改描述,AI 会重新分析。'
|
|
1629
|
-
: ruleSummaryPending ? '分析完成前不能开放任务。'
|
|
1655
|
+
: ruleSummaryPending ? '分析完成前不能开放任务。'
|
|
1656
|
+
: ruleSummaryDirty ? '点击“立即分析”完成复核后才能开放任务。' : '填写描述后点击“立即分析”生成任务理解;草稿不会自动开放。'))),
|
|
1630
1657
|
h('section', { style: { ...panelStyle, padding: 10, gap: 9, display: 'grid',
|
|
1631
1658
|
gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 280px), 1fr))' } },
|
|
1632
1659
|
h('strong', { style: { gridColumn: '1 / -1' } }, '通用授权'),
|
|
1633
1660
|
h('p', { style: { ...mutedTextStyle, gridColumn: '1 / -1' } },
|
|
1634
1661
|
'上方描述规则任务要做什么;这里限定谁能请求、在哪里请求、由谁执行和授权多久。'),
|
|
1635
|
-
h('
|
|
1636
|
-
|
|
1637
|
-
h('
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
`${nativePrUnavailableReason}。当前仍可使用 DSH 团队模型处理任务。`) : null,
|
|
1662
|
+
h('div', { role: 'group', 'aria-label': '执行方', style: { display: 'grid', gap: 7 } },
|
|
1663
|
+
h('strong', null, '执行方 · 可多选'),
|
|
1664
|
+
h('p', { style: mutedTextStyle }, '勾选可用于此任务的执行方,并从已勾选项中设一个默认。普通请求只运行默认项;请求人明确要求交叉审查时并行运行其他已选项。'),
|
|
1665
|
+
...[
|
|
1666
|
+
{ id: 'dsh', title: 'DSH', detail: '使用获准的团队模型处理对话内容和 ANT 已核验资源。', available: dshAvailable },
|
|
1667
|
+
{ id: 'codex', title: 'Codex', detail: '使用本机 DSH Provider Profile 权限;ANT 不会将文件、Git 和网络权限缩小到单项任务。', available: codexAvailable },
|
|
1668
|
+
{ id: 'claude-code', title: 'Claude Code', detail: '使用本机 DSH Provider Profile 权限;ANT 不会将文件、Git 和网络权限缩小到单项任务。', available: claudeCodeAvailable },
|
|
1669
|
+
].map((option) => {
|
|
1670
|
+
const checked = reviewers.includes(option.id)
|
|
1671
|
+
return h('div', { key: option.id, style: { display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) auto',
|
|
1672
|
+
gap: 8, alignItems: 'center', border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 8,
|
|
1673
|
+
padding: '9px 11px' } },
|
|
1674
|
+
h('label', { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
|
|
1675
|
+
h('input', { type: 'checkbox', 'aria-label': `任务 Agent ${option.title}`, checked,
|
|
1676
|
+
disabled: !option.available && !checked,
|
|
1677
|
+
onChange: (event) => changeReviewer(option.id, event.target.checked) }),
|
|
1678
|
+
h('strong', null, option.title),
|
|
1679
|
+
h('span', { style: mutedTextStyle }, option.available ? '可用' : '未在本机启用')),
|
|
1680
|
+
h('label', { style: { display: 'flex', alignItems: 'center', gap: 6, color: mutedTextStyle.color } },
|
|
1681
|
+
h('input', { type: 'radio', name: 'ant-default-runner', 'aria-label': `默认执行方 ${option.title}`,
|
|
1682
|
+
checked: runner === option.id, disabled: !checked || !option.available,
|
|
1683
|
+
onChange: () => selectRunner(option.id) }), '默认'),
|
|
1684
|
+
checked ? h('span', { style: { ...mutedTextStyle, gridColumn: '1 / -1' } }, option.detail) : null)
|
|
1685
|
+
}),
|
|
1686
|
+
),
|
|
1687
|
+
executorUnavailableReason ? h('p', { role: 'status', style: { ...mutedTextStyle, gridColumn: '1 / -1' } },
|
|
1688
|
+
`${executorUnavailableReason} 当前仍可使用 DSH 团队模型。`) : null,
|
|
1663
1689
|
h('label', null, '使用场景', h('select', { value: conversationKind,
|
|
1664
1690
|
onChange: (event) => { setConversationKind(event.target.value); setGroupId('') }, style: inputStyle },
|
|
1665
1691
|
h('option', { value: 'dm' }, '私聊'), h('option', { value: 'group' }, '指定群聊'))),
|
|
@@ -1731,7 +1757,7 @@ window.__ModuleLoader__.load({
|
|
|
1731
1757
|
h('p', { style: mutedTextStyle }, tokenConfigured
|
|
1732
1758
|
? '令牌由 DSH 本机凭据服务保存。ANT Host 在读取已授权 PR 时会使用它;不会同步到 ANT 服务端或写入审查提示词。'
|
|
1733
1759
|
: '读取 Gitea PR 需要只读访问令牌。保存后由 DSH 本机凭据服务管理,ANT Host 只在读取已授权 PR 时使用。'),
|
|
1734
|
-
h('p', { role: 'note', style: mutedTextStyle }, 'DSH 默认将凭据保存在 DSH Home 的私有文件中,环境变量也可作为回退来源。文件权限只隔离其他 OS 用户;同一用户权限下的 Agent 进程可能读取它。
|
|
1760
|
+
h('p', { role: 'note', style: mutedTextStyle }, 'DSH 默认将凭据保存在 DSH Home 的私有文件中,环境变量也可作为回退来源。文件权限只隔离其他 OS 用户;同一用户权限下的 Agent 进程可能读取它。Codex 和 Claude Code 会使用本机 DSH Provider Profile 的文件、Git、网络及工具权限;任务描述和单次审批不会创建操作系统沙箱,也不会缩小这些权限。ANT Gitea 凭据只由 Host Connector 使用,不会放入 Agent 请求。'),
|
|
1735
1761
|
h('p', { role: 'note', style: mutedTextStyle }, selectedGiteaOrigin
|
|
1736
1762
|
? `这枚只读令牌仅用于已绑定主机 ${selectedGiteaOrigin};任务来源来自自然语言描述,但必须匹配该主机。`
|
|
1737
1763
|
: '首次确认并开放包含 PR 来源的任务时,会将该来源绑定到这台机器人;确认前 ANT 不会把只读令牌发送到任务描述中的地址。'),
|
|
@@ -1765,21 +1791,21 @@ window.__ModuleLoader__.load({
|
|
|
1765
1791
|
style: { ...inputStyle, width: 128, maxWidth: '100%', boxSizing: 'border-box' } })),
|
|
1766
1792
|
h('button', { disabled: busy, style: secondaryButtonStyle }, '保存本机处理设置'),
|
|
1767
1793
|
h('p', { style: { ...mutedTextStyle, flex: '1 1 100%', margin: 0 } },
|
|
1768
|
-
'
|
|
1794
|
+
'需要完整 PR 文件时,ANT 会在本机准备已核验 Head 的临时快照;刷新授权状态时会清理已停用或到期能力的旧缓存。')),
|
|
1769
1795
|
),
|
|
1770
1796
|
h('section', { 'aria-label': '执行方状态与权限边界', style: { ...settingsPanelStyle, padding: 14, gap: 8 } },
|
|
1771
1797
|
h('strong', null, '执行方状态与权限边界'),
|
|
1772
|
-
h('p', { style: mutedTextStyle }, '这里显示 DSH
|
|
1798
|
+
h('p', { style: mutedTextStyle }, '这里显示 DSH 本机的执行器状态。已注册的 Codex 或 Claude Code 可由主人选入预授权任务卡,或在本次 IM 审批中选择。'),
|
|
1773
1799
|
loadFailures.includes('executors') ? h('p', { role: 'status', style: mutedTextStyle }, '暂时无法读取执行方状态,请刷新后重试。') : null,
|
|
1774
1800
|
...executors.filter((item) => ['dsh', 'codex', 'claude-code'].includes(item.id)).map((item) => h('div', {
|
|
1775
1801
|
key: item.id, style: { display: 'grid', gap: 3, paddingTop: 8, borderTop: '1px solid var(--dsw-alias-border-l2)' } },
|
|
1776
1802
|
h('strong', null, item.title + ' · ' + (item.id === 'dsh'
|
|
1777
1803
|
? item.available ? '可用' : item.reason || '未就绪'
|
|
1778
|
-
: item.available ? '已注册 ·
|
|
1804
|
+
: item.available ? '已注册 · 可用于协作' : '尚未注册')),
|
|
1779
1805
|
h('span', { style: mutedTextStyle }, item.id === 'codex'
|
|
1780
|
-
? '
|
|
1806
|
+
? 'Codex 使用本机 Provider Profile 权限;ANT 不会把文件、Git 或网络权限缩小到任务范围。'
|
|
1781
1807
|
: item.id === 'claude-code'
|
|
1782
|
-
? '
|
|
1808
|
+
? 'Claude Code 使用本机 Provider Profile 权限;ANT 不会把文件、Git 或网络权限缩小到任务范围。'
|
|
1783
1809
|
: '处理授权任务提供的内容,不调用本机工具。'))))))
|
|
1784
1810
|
}
|
|
1785
1811
|
|