@p-dsh-market/conversation-knowledge-map 0.1.8 → 0.1.9

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.
@@ -68,7 +68,16 @@ function textFromContent(value) {
68
68
  return ''
69
69
  }
70
70
 
71
- function findJsonObject(text) {
71
+ function expectedObject(value, kind = '') {
72
+ if (!kind) return true
73
+ if (kind === 'summary') return typeof value?.summary === 'string' || typeof value?.narrative === 'string' || typeof value?.text === 'string'
74
+ if (kind === 'mind-map') return Array.isArray(value?.nodes)
75
+ if (kind === 'knowledge-graph') return Array.isArray(value?.entities) && Array.isArray(value?.relations)
76
+ if (kind === 'follow-up') return typeof value?.question === 'string'
77
+ return true
78
+ }
79
+
80
+ function findJsonObject(text, kind = '') {
72
81
  const candidates = []
73
82
  const fenced = String(text || '').match(/```(?:json)?\s*([\s\S]*?)```/i)
74
83
  if (fenced) candidates.push(fenced[1])
@@ -98,7 +107,7 @@ function findJsonObject(text) {
98
107
  const fragment = candidate.slice(start, index + 1)
99
108
  try {
100
109
  const parsed = JSON.parse(fragment)
101
- if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) return parsed
110
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed) && expectedObject(parsed, kind)) return parsed
102
111
  } catch {
103
112
  // Try the next opening brace in case prose contained an example.
104
113
  }
@@ -111,11 +120,11 @@ function findJsonObject(text) {
111
120
  return null
112
121
  }
113
122
 
114
- export function parseStructuredOutput(value) {
123
+ export function parseStructuredOutput(value, kind = '') {
115
124
  const object = asObject(value)
116
- if (object) return object
125
+ if (object && expectedObject(object, kind)) return object
117
126
  const text = textFromContent(value).replace(/^\uFEFF/, '').trim()
118
- const parsed = findJsonObject(text)
127
+ const parsed = findJsonObject(text, kind)
119
128
  if (parsed) return parsed
120
129
  if (!text) throw new Error('模型没有返回 JSON 对象。')
121
130
  throw new Error('模型返回了文本,但其中没有可解析的 JSON 对象。')
@@ -198,6 +207,7 @@ function summaryPrompt(source, chunk, strict) {
198
207
  return [
199
208
  '请把一段 DSH 对话整理成带来源的结构化摘要。不要复述完整聊天,不要添加对话中没有的事实。',
200
209
  '只输出 JSON:{"summary":"完整阶段性说明","keyPoints":["..."],"sourceRefs":[{"sessionId":"...","eventSeqs":[1]}]}。',
210
+ 'summary 控制在 1200 字以内;keyPoints 最多 8 条,每条不超过 160 字。不要增加其他字段。字符串中的双引号必须正确转义,确保整个输出可以被 JSON.parse 直接解析。',
201
211
  strict ? '严格模式:每个关键点都要能回指给定事件。' : '允许标记尚未确认的冲突,但不能编造事件序号。',
202
212
  `Session:${source.sessionId}`,
203
213
  `标题:${source.title}`,
@@ -493,16 +503,25 @@ export class KnowledgeGenerationOrchestrator {
493
503
  })
494
504
  for (const chunk of chunkSourceText(source)) {
495
505
  this.assertNotCancelled(task)
496
- const value = await this.runModel({
497
- kind: 'summary',
498
- prompt: summaryPrompt(source, chunk, request.strict === true),
499
- cwd: request.cwd,
500
- strict: request.strict === true,
501
- selectedSessionIds: sourceSessionIds,
502
- model: request.model,
503
- signal: task.controller.signal
506
+ const prompt = summaryPrompt(source, chunk, request.strict === true)
507
+ const generateSummary = async (summaryInput) => this.runModel({
508
+ kind: 'summary', prompt: summaryInput, cwd: request.cwd, strict: request.strict === true,
509
+ selectedSessionIds: sourceSessionIds, model: request.model, signal: task.controller.signal
504
510
  })
505
- summaries.push(normalizeSummary(value, source, chunk))
511
+ try {
512
+ const value = await generateSummary(prompt)
513
+ summaries.push(normalizeSummary(value, source, chunk))
514
+ } catch (error) {
515
+ this.assertNotCancelled(task)
516
+ logMessage(this.logger, 'warn', 'summary first attempt invalid id=%s session=%s error=%s', logId(task.id), logId(source.sessionId), errorMessage(error))
517
+ this.update(task, 'summarizing', {
518
+ message: `对话 ${sourceIndex + 1}/${sources.length} 摘要结构无效,正在自动修复…`,
519
+ progress: { percent: 10 + Math.floor(60 * sourceIndex / sources.length), current: sourceIndex, total: sources.length, label: `自动修复:${source.title}` }
520
+ })
521
+ const retryPrompt = `${prompt}\n\n上一次输出未通过校验:${shortText(errorMessage(error), 500)}。请从头重新整理,缩短内容,只输出严格合法的顶层摘要 JSON。`
522
+ const retryValue = await generateSummary(retryPrompt)
523
+ summaries.push(normalizeSummary(retryValue, source, chunk))
524
+ }
506
525
  }
507
526
  this.update(task, 'summarizing', {
508
527
  sourceCount: sources.length,
@@ -581,7 +600,7 @@ export class KnowledgeGenerationOrchestrator {
581
600
  async runModel(input) {
582
601
  const parseModelOutput = (value, source, diagnostics = {}) => {
583
602
  try {
584
- const result = parseStructuredOutput(value)
603
+ const result = parseStructuredOutput(value, input.kind)
585
604
  logMessage(this.logger, 'info', 'agent output parsed kind=%s source=%s value=%s result=%s', input.kind, source, diagnosticSummary(value), diagnosticSummary(result))
586
605
  return result
587
606
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@p-dsh-market/conversation-knowledge-map",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "DSH 多对话思维导图与静态知识图谱",
5
5
  "keywords": [
6
6
  "dsh",