返回 oh-my-ppt
result.ts
根目录 / src / main / agent-runtime / model / result.ts
1 export const extractModelText = (value: unknown): string => {
2 if (typeof value === 'string') return value
3 if (!value || typeof value !== 'object') return ''
4 const content = 'content' in value ? (value as { content?: unknown }).content : undefined
5 if (typeof content === 'string') return content
6 if (Array.isArray(content)) {
7 return content
8 .map((item) => {
9 if (typeof item === 'string') return item
10 if (item && typeof item === 'object' && 'text' in item) {
11 return typeof (item as { text?: unknown }).text === 'string'
12 ? String((item as { text?: unknown }).text)
13 : ''
14 }
15 return ''
16 })
17 .join('\n')
18 .trim()
19 }
20 return ''
21 }
22
23 export const extractJsonBlock = (raw: string): string => {
24 const fenced = raw.match(/```(?:json)?\s*([\s\S]*?)```/i)
25 if (fenced?.[1]) return fenced[1].trim()
26
27 const extractBalanced = (
28 start: number,
29 open: '{' | '[',
30 close: '}' | ']'
31 ): string | null => {
32 let depth = 0
33 let inString = false
34 let escaped = false
35
36 for (let index = start; index < raw.length; index += 1) {
37 const char = raw[index]
38 if (inString) {
39 if (escaped) {
40 escaped = false
41 } else if (char === '\\') {
42 escaped = true
43 } else if (char === '"') {
44 inString = false
45 }
46 continue
47 }
48 if (char === '"') {
49 inString = true
50 continue
51 }
52 if (char === open) depth += 1
53 if (char === close) {
54 depth -= 1
55 if (depth === 0) return raw.slice(start, index + 1)
56 }
57 }
58 return null
59 }
60
61 for (let start = 0; start < raw.length; start += 1) {
62 const char = raw[start]
63 const block =
64 char === '{'
65 ? extractBalanced(start, '{', '}')
66 : char === '['
67 ? extractBalanced(start, '[', ']')
68 : null
69 if (!block) continue
70 try {
71 JSON.parse(block)
72 return block.trim()
73 } catch {
74 // This can be a prose bracket or malformed model output; keep scanning.
75 }
76 }
77 return raw.trim()
78 }
79
79 lines TYPESCRIPT