fix(web): parse markdown responses as text in WebPlatformAdapter.fetchRemoteConfig

Importing a skill from the cloud market failed with
'SyntaxError: No number after minus sign in JSON at position 1 (line 1 column 2)'
because the WebPlatformAdapter hard-coded res.json() for every response, while
the same IPC handler on Electron already routes by Content-Type / .json suffix
(see apps/desktop/main/ipc/window.ts: '支持 JSON 和纯文本/Markdown').

The Electron path handled skill bodies (.md) correctly; the Web path only
worked for the catalog (skill.json). Aligning the Web adapter with the same
Content-Type / .json-suffix rule fixes both fetchCloudCatalog and
importFromCloud at once, with no new abstraction.
This commit is contained in:
axzhang1216 authored and digua committed 2026-07-10 20:25:54 +08:00
1 parent e00c9a4503
commit 6f051813e3
2 files changed
+34 -1

No files matched your search

+31
View File
@@ -71,4 +71,35 @@ describe('WebPlatformAdapter', () => {
globalThis.fetch = originalFetch
}
})
it('parses markdown skill bodies as text instead of JSON', async () => {
// Regression: importing a skill from the cloud market failed with
// "SyntaxError: No number after minus sign in JSON..." because
// fetchRemoteConfig hard-coded res.json() for every response.
const originalFetch = globalThis.fetch
const md = `---\nid: skill_md\nname: Markdown Skill\ndescription: desc\n---\nbody text`
globalThis.fetch = (() =>
Promise.resolve(new Response(md, { headers: { 'content-type': 'text/markdown' } }))) as typeof fetch
try {
const result = await new WebPlatformAdapter().fetchRemoteConfig('https://example.com/skills/skill_md.md')
assert.equal(result.success, true)
assert.equal(result.data, md)
} finally {
globalThis.fetch = originalFetch
}
})
it('parses .json URLs as JSON even without an application/json content-type', async () => {
const originalFetch = globalThis.fetch
globalThis.fetch = (() =>
Promise.resolve(new Response('[1,2,3]', { headers: { 'content-type': 'text/plain' } }))) as typeof fetch
try {
const result = await new WebPlatformAdapter().fetchRemoteConfig('https://example.com/cn/skill.json')
assert.deepEqual(result.data, [1, 2, 3])
} finally {
globalThis.fetch = originalFetch
}
})
})
+3 -1
View File
@@ -25,7 +25,9 @@ export class WebPlatformAdapter implements PlatformAdapter {
try {
const res = await fetch(url)
if (!res.ok) return { success: false, error: `HTTP ${res.status}` }
const data = await res.json()
const contentType = res.headers.get('content-type') || ''
const isJson = contentType.includes('application/json') || url.split('?')[0].endsWith('.json')
const data = isJson ? await res.json() : await res.text()
return { success: true, data }
} catch (e) {
return { success: false, error: String(e) }