Merge pull request #2253 into stage-355
[codex] Show skill detail API errors (franksong2702) # Conflicts: # CHANGELOG.md
This commit is contained in:
commit
6f5f5edb56
4 changed files with 54 additions and 0 deletions
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -3244,6 +3244,21 @@ function _renderSkillDetail(name, content, linkedFiles) {
|
|||
_setSkillHeaderButtons('read');
|
||||
}
|
||||
|
||||
function _renderSkillError(name, message) {
|
||||
const title = $('skillDetailTitle');
|
||||
const body = $('skillDetailBody');
|
||||
const empty = $('skillDetailEmpty');
|
||||
if (title) title.textContent = name;
|
||||
if (body) {
|
||||
body.innerHTML = `<div class="main-view-content"><div class="detail-form-error" style="display:block">${esc(message || t('skill_load_failed'))}</div></div>`;
|
||||
body.style.display = '';
|
||||
}
|
||||
if (empty) empty.style.display = 'none';
|
||||
_currentSkillDetail = null;
|
||||
_skillMode = 'empty';
|
||||
_setSkillHeaderButtons('empty');
|
||||
}
|
||||
|
||||
function _setSkillHeaderButtons(mode) {
|
||||
const editBtn = $('btnEditSkillDetail');
|
||||
const delBtn = $('btnDeleteSkillDetail');
|
||||
|
|
@ -3264,6 +3279,12 @@ async function openSkill(name, el) {
|
|||
_editingSkillName = null;
|
||||
try {
|
||||
const data = await api(`/api/skills/content?name=${encodeURIComponent(name)}`);
|
||||
if (data && (data.success === false || data.error)) {
|
||||
const message = data.error || t('skill_load_failed');
|
||||
_renderSkillError(name, message);
|
||||
setStatus(t('skill_load_failed') + message);
|
||||
return;
|
||||
}
|
||||
_currentSkillDetail = { name, content: data.content || '', linked_files: data.linked_files || {} };
|
||||
_renderSkillDetail(name, data.content || '', data.linked_files || {});
|
||||
} catch(e) { setStatus(t('skill_load_failed') + e.message); }
|
||||
|
|
@ -3272,6 +3293,11 @@ async function openSkill(name, el) {
|
|||
async function openSkillFile(skillName, filePath) {
|
||||
try {
|
||||
const data = await api(`/api/skills/content?name=${encodeURIComponent(skillName)}&file=${encodeURIComponent(filePath)}`);
|
||||
if (data && data.error) {
|
||||
_renderSkillError(skillName, data.error);
|
||||
setStatus(t('skill_file_load_failed') + data.error);
|
||||
return;
|
||||
}
|
||||
const body = $('skillDetailBody');
|
||||
if (!body) return;
|
||||
const ext = (filePath.split('.').pop() || '').toLowerCase();
|
||||
|
|
|
|||
28
tests/test_skill_detail_error_guard.py
Normal file
28
tests/test_skill_detail_error_guard.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
PANELS_JS = (ROOT / "static" / "panels.js").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_skill_detail_api_error_renders_in_detail_pane():
|
||||
assert "function _renderSkillError(name, message)" in PANELS_JS
|
||||
assert "data.success === false || data.error" in PANELS_JS
|
||||
assert "_renderSkillError(name, message);" in PANELS_JS
|
||||
assert "_currentSkillDetail = null;" in PANELS_JS
|
||||
assert "_setSkillHeaderButtons('empty');" in PANELS_JS
|
||||
|
||||
|
||||
def test_skill_detail_no_longer_silently_falls_back_on_error_payload():
|
||||
success_guard = PANELS_JS.index("data.success === false || data.error")
|
||||
render_detail = PANELS_JS.index("_renderSkillDetail(name, data.content || ''")
|
||||
assert success_guard < render_detail
|
||||
|
||||
|
||||
def test_skill_linked_file_api_error_renders_in_detail_pane():
|
||||
file_fetch = PANELS_JS.index("/api/skills/content?name=${encodeURIComponent(skillName)}&file=")
|
||||
file_error_guard = PANELS_JS.index("if (data && data.error)", file_fetch)
|
||||
file_render = PANELS_JS.index("_renderSkillError(skillName, data.error);", file_fetch)
|
||||
body_lookup = PANELS_JS.index("const body = $('skillDetailBody');", file_fetch)
|
||||
assert file_error_guard < body_lookup
|
||||
assert file_render < body_lookup
|
||||
Loading…
Reference in a new issue