mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
feat: enhance CLI discussion agent and multi-CLI planning with JSON string support; improve error handling and internationalization
This commit is contained in:
@@ -24,21 +24,25 @@ You are a multi-CLI collaborative discussion agent. You orchestrate multiple CLI
|
|||||||
task_description: string, // User's task or requirement
|
task_description: string, // User's task or requirement
|
||||||
round_number: number, // Current discussion round (1, 2, 3...)
|
round_number: number, // Current discussion round (1, 2, 3...)
|
||||||
session: { id, folder }, // Session metadata
|
session: { id, folder }, // Session metadata
|
||||||
ace_context: { // From ACE semantic search
|
ace_context: { // From ACE semantic search (may be JSON string from orchestrator)
|
||||||
relevant_files: string[],
|
relevant_files: string[],
|
||||||
detected_patterns: string[],
|
detected_patterns: string[],
|
||||||
architecture_insights: string
|
architecture_insights: string
|
||||||
},
|
},
|
||||||
|
|
||||||
// Optional
|
// Optional
|
||||||
previous_rounds: RoundResult[], // Results from previous rounds
|
previous_rounds: RoundResult[], // Results from previous rounds (may be JSON string from orchestrator)
|
||||||
user_feedback: string | null, // User's feedback/clarification from last round
|
user_feedback: string | null, // User's feedback/clarification from last round
|
||||||
cli_config: {
|
cli_config: { // CLI configuration (may be JSON string from orchestrator)
|
||||||
tools: string[], // CLI tools to use (default: ['gemini', 'codex'])
|
tools: string[], // CLI tools to use (default: ['gemini', 'codex'])
|
||||||
timeout: number, // CLI timeout in ms
|
timeout: number, // CLI timeout in ms
|
||||||
fallback_chain: string[] // Fallback order
|
fallback_chain: string[] // Fallback order
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: When called from orchestrator, ace_context, previous_rounds, and cli_config
|
||||||
|
// may be passed as JSON strings (via JSON.stringify). The execute function parses
|
||||||
|
// these automatically - see "Input Parsing" section in Main Execution.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Output Schema
|
## Output Schema
|
||||||
@@ -475,7 +479,21 @@ function createDegradedAnalysis() {
|
|||||||
```javascript
|
```javascript
|
||||||
async function execute(input) {
|
async function execute(input) {
|
||||||
const startTime = Date.now()
|
const startTime = Date.now()
|
||||||
const { task_description, round_number, session, ace_context, previous_rounds, user_feedback, cli_config } = input
|
const { task_description, round_number, session, user_feedback, cli_config: cli_config_raw } = input
|
||||||
|
|
||||||
|
// === Input Parsing ===
|
||||||
|
// Parse stringified inputs from orchestrator (may be passed as JSON.stringify'd strings)
|
||||||
|
const ace_context = typeof input.ace_context === 'string'
|
||||||
|
? JSON.parse(input.ace_context)
|
||||||
|
: (input.ace_context || {})
|
||||||
|
|
||||||
|
const previous_rounds = typeof input.previous_rounds === 'string'
|
||||||
|
? JSON.parse(input.previous_rounds)
|
||||||
|
: (input.previous_rounds || [])
|
||||||
|
|
||||||
|
const cli_config = typeof cli_config_raw === 'string'
|
||||||
|
? JSON.parse(cli_config_raw)
|
||||||
|
: (cli_config_raw || { tools: ['gemini', 'codex'], timeout: 600000, fallback_chain: ['gemini', 'codex', 'qwen'] })
|
||||||
|
|
||||||
const roundFolder = `${session.folder}/rounds/${round_number}`
|
const roundFolder = `${session.folder}/rounds/${round_number}`
|
||||||
Bash(`mkdir -p ${roundFolder}`)
|
Bash(`mkdir -p ${roundFolder}`)
|
||||||
|
|||||||
@@ -206,16 +206,18 @@ ${JSON.stringify(contextPackage, null, 2)}
|
|||||||
|
|
||||||
## Previous Rounds
|
## Previous Rounds
|
||||||
${analysisResults.length > 0
|
${analysisResults.length > 0
|
||||||
? analysisResults.map(r => `Round ${r.round}: ${r.summary}`).join('\n')
|
? JSON.stringify(analysisResults, null, 2)
|
||||||
: 'None (first round)'}
|
: 'None (first round)'}
|
||||||
|
|
||||||
## User Feedback
|
## User Feedback
|
||||||
${userFeedback || 'None'}
|
${userFeedback || 'None'}
|
||||||
|
|
||||||
## CLI Configuration
|
## CLI Configuration
|
||||||
- Tools: ${effectiveTools.join(', ')}
|
${JSON.stringify({
|
||||||
- Timeout: 600000ms
|
tools: effectiveTools,
|
||||||
- Fallback Chain: gemini → codex → qwen
|
timeout: 600000,
|
||||||
|
fallback_chain: ['gemini', 'codex', 'qwen']
|
||||||
|
}, null, 2)}
|
||||||
|
|
||||||
## Output Requirements
|
## Output Requirements
|
||||||
Write: ${sessionFolder}/rounds/${currentRound}/synthesis.json
|
Write: ${sessionFolder}/rounds/${currentRound}/synthesis.json
|
||||||
@@ -461,7 +463,7 @@ const planningContext = {
|
|||||||
task_description: taskDescription,
|
task_description: taskDescription,
|
||||||
selected_solution: selectedSolution,
|
selected_solution: selectedSolution,
|
||||||
analysis_rounds: analysisResults,
|
analysis_rounds: analysisResults,
|
||||||
consensus_points: finalSynthesis.consensus_points,
|
consensus_points: finalSynthesis._internal?.cross_verification?.agreements || [],
|
||||||
user_constraints: userDecision.constraints || null,
|
user_constraints: userDecision.constraints || null,
|
||||||
ace_context: contextPackage,
|
ace_context: contextPackage,
|
||||||
clarifications: sessionState.user_decisions
|
clarifications: sessionState.user_decisions
|
||||||
@@ -514,7 +516,7 @@ ${selectedSolution.cons.map(c => `- ${c}`).join('\n')}
|
|||||||
${selectedSolution.affected_files.map(f => `- ${f.file}:${f.line} - ${f.reason}`).join('\n')}
|
${selectedSolution.affected_files.map(f => `- ${f.file}:${f.line} - ${f.reason}`).join('\n')}
|
||||||
|
|
||||||
### Analysis Consensus
|
### Analysis Consensus
|
||||||
${finalSynthesis.consensus_points.map(p => `- ${p}`).join('\n')}
|
${(finalSynthesis._internal?.cross_verification?.agreements || []).map(p => `- ${p}`).join('\n')}
|
||||||
|
|
||||||
### User Constraints
|
### User Constraints
|
||||||
${userDecision.constraints ? JSON.stringify(userDecision.constraints) : 'None specified'}
|
${userDecision.constraints ? JSON.stringify(userDecision.constraints) : 'None specified'}
|
||||||
|
|||||||
@@ -746,8 +746,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file-browser-loading,
|
.file-browser-loading,
|
||||||
.file-browser-empty,
|
.file-browser-empty {
|
||||||
.file-browser-error {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -758,9 +757,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file-browser-error {
|
.file-browser-error {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 200px;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-align: center;
|
||||||
|
padding: 1rem;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-browser-error p {
|
||||||
|
margin: 0;
|
||||||
color: hsl(var(--destructive));
|
color: hsl(var(--destructive));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file-browser-hint {
|
||||||
|
color: hsl(var(--muted-foreground));
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
.file-browser-item {
|
.file-browser-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -278,6 +278,8 @@ const i18n = {
|
|||||||
'cli.fileBrowserUp': 'Parent Directory',
|
'cli.fileBrowserUp': 'Parent Directory',
|
||||||
'cli.fileBrowserHome': 'Home',
|
'cli.fileBrowserHome': 'Home',
|
||||||
'cli.fileBrowserShowHidden': 'Show hidden files',
|
'cli.fileBrowserShowHidden': 'Show hidden files',
|
||||||
|
'cli.fileBrowserApiError': 'Server restart required to enable file browser',
|
||||||
|
'cli.fileBrowserManualHint': 'Type the full path above and click Select (e.g., C:\\Users\\name\\.gemini)',
|
||||||
|
|
||||||
// CodexLens Configuration
|
// CodexLens Configuration
|
||||||
'codexlens.config': 'CodexLens Configuration',
|
'codexlens.config': 'CodexLens Configuration',
|
||||||
@@ -2517,6 +2519,8 @@ const i18n = {
|
|||||||
'cli.fileBrowserUp': '上级目录',
|
'cli.fileBrowserUp': '上级目录',
|
||||||
'cli.fileBrowserHome': '主目录',
|
'cli.fileBrowserHome': '主目录',
|
||||||
'cli.fileBrowserShowHidden': '显示隐藏文件',
|
'cli.fileBrowserShowHidden': '显示隐藏文件',
|
||||||
|
'cli.fileBrowserApiError': '需要重启服务器以启用文件浏览器',
|
||||||
|
'cli.fileBrowserManualHint': '请在上方输入完整路径后点击选择(如 C:\\Users\\用户名\\.gemini)',
|
||||||
|
|
||||||
// CodexLens 配置
|
// CodexLens 配置
|
||||||
'codexlens.config': 'CodexLens 配置',
|
'codexlens.config': 'CodexLens 配置',
|
||||||
|
|||||||
@@ -659,7 +659,17 @@ async function loadFileBrowserDirectory(path) {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to load directory:', err);
|
console.error('Failed to load directory:', err);
|
||||||
if (listContainer) {
|
if (listContainer) {
|
||||||
listContainer.innerHTML = '<div class="file-browser-error">Failed to load directory</div>';
|
listContainer.innerHTML = '<div class="file-browser-error">' +
|
||||||
|
'<p>' + t('cli.fileBrowserApiError') + '</p>' +
|
||||||
|
'<p class="file-browser-hint">' + t('cli.fileBrowserManualHint') + '</p>' +
|
||||||
|
'</div>';
|
||||||
|
}
|
||||||
|
// Enable manual path entry mode - enable select button when path is typed
|
||||||
|
var selectBtn = document.getElementById('fileBrowserSelectBtn');
|
||||||
|
var pathInput = document.getElementById('fileBrowserPathInput');
|
||||||
|
if (selectBtn && pathInput) {
|
||||||
|
selectBtn.disabled = false;
|
||||||
|
pathInput.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -744,8 +754,17 @@ function initFileBrowserEvents() {
|
|||||||
var selectBtn = document.getElementById('fileBrowserSelectBtn');
|
var selectBtn = document.getElementById('fileBrowserSelectBtn');
|
||||||
if (selectBtn) {
|
if (selectBtn) {
|
||||||
selectBtn.onclick = function() {
|
selectBtn.onclick = function() {
|
||||||
|
// First try selected path from list, then fall back to path input
|
||||||
var path = selectBtn.getAttribute('data-selected-path');
|
var path = selectBtn.getAttribute('data-selected-path');
|
||||||
closeFileBrowserModal(path);
|
if (!path) {
|
||||||
|
var pathInput = document.getElementById('fileBrowserPathInput');
|
||||||
|
if (pathInput && pathInput.value.trim()) {
|
||||||
|
path = pathInput.value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (path) {
|
||||||
|
closeFileBrowserModal(path);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user