@p-dsh-market/conversation-knowledge-map 0.1.6 → 0.1.7
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.
- package/lib/generation-orchestrator.js +8 -6
- package/lib/session-source.js +51 -15
- package/package.json +1 -1
|
@@ -474,8 +474,10 @@ export class KnowledgeGenerationOrchestrator {
|
|
|
474
474
|
const sources = await this.sourceReader({ sessionQuery: this.sessionQuery, sessions: this.sessions }, {
|
|
475
475
|
cwd: request.cwd,
|
|
476
476
|
sessionIds: request.selectedSessionIds,
|
|
477
|
+
fallbackSessionId: request.anchorSessionId,
|
|
477
478
|
includeSubagents: request.includeSubagents === true
|
|
478
479
|
})
|
|
480
|
+
const sourceSessionIds = [...new Set(sources.map((source) => source.sessionId))]
|
|
479
481
|
this.assertNotCancelled(task)
|
|
480
482
|
logMessage(this.logger, 'info', 'generation sources loaded id=%s sources=%d events=%d', logId(task.id), sources.length, sources.reduce((total, source) => total + (Array.isArray(source.events) ? source.events.length : 0), 0))
|
|
481
483
|
this.update(task, 'summarizing', { sourceCount: sources.length })
|
|
@@ -488,7 +490,7 @@ export class KnowledgeGenerationOrchestrator {
|
|
|
488
490
|
prompt: summaryPrompt(source, chunk, request.strict === true),
|
|
489
491
|
cwd: request.cwd,
|
|
490
492
|
strict: request.strict === true,
|
|
491
|
-
selectedSessionIds:
|
|
493
|
+
selectedSessionIds: sourceSessionIds,
|
|
492
494
|
model: request.model,
|
|
493
495
|
signal: task.controller.signal
|
|
494
496
|
})
|
|
@@ -505,11 +507,11 @@ export class KnowledgeGenerationOrchestrator {
|
|
|
505
507
|
prompt: outputPrompt('mind-map', summaries, request.prompt, request.strict === true),
|
|
506
508
|
cwd: request.cwd,
|
|
507
509
|
strict: request.strict === true,
|
|
508
|
-
selectedSessionIds:
|
|
510
|
+
selectedSessionIds: sourceSessionIds,
|
|
509
511
|
model: request.model,
|
|
510
512
|
signal: task.controller.signal
|
|
511
513
|
})
|
|
512
|
-
mindMap = validateMindMap(value, { selectedSessionIds:
|
|
514
|
+
mindMap = validateMindMap(value, { selectedSessionIds: sourceSessionIds, strict: request.strict === true })
|
|
513
515
|
}
|
|
514
516
|
if (request.outputMode === 'knowledge-graph' || request.outputMode === 'both') {
|
|
515
517
|
this.update(task, 'building-knowledge-graph')
|
|
@@ -518,11 +520,11 @@ export class KnowledgeGenerationOrchestrator {
|
|
|
518
520
|
prompt: outputPrompt('knowledge-graph', summaries, request.prompt, request.strict === true),
|
|
519
521
|
cwd: request.cwd,
|
|
520
522
|
strict: request.strict === true,
|
|
521
|
-
selectedSessionIds:
|
|
523
|
+
selectedSessionIds: sourceSessionIds,
|
|
522
524
|
model: request.model,
|
|
523
525
|
signal: task.controller.signal
|
|
524
526
|
})
|
|
525
|
-
knowledgeGraph = validateKnowledgeGraph(value, { selectedSessionIds:
|
|
527
|
+
knowledgeGraph = validateKnowledgeGraph(value, { selectedSessionIds: sourceSessionIds, strict: request.strict === true })
|
|
526
528
|
}
|
|
527
529
|
assertOutputSourceRefs({ mindMap, knowledgeGraph }, sources)
|
|
528
530
|
this.assertNotCancelled(task)
|
|
@@ -532,7 +534,7 @@ export class KnowledgeGenerationOrchestrator {
|
|
|
532
534
|
cwd: request.cwd,
|
|
533
535
|
expectedRevision: request.expectedRevision,
|
|
534
536
|
generationId: task.id,
|
|
535
|
-
sourceSessionIds
|
|
537
|
+
sourceSessionIds,
|
|
536
538
|
prompt: request.prompt,
|
|
537
539
|
strict: request.strict,
|
|
538
540
|
outputMode: request.outputMode,
|
package/lib/session-source.js
CHANGED
|
@@ -112,8 +112,10 @@ function sourceSeqsOf(event) {
|
|
|
112
112
|
return Array.isArray(value) ? value.filter((item) => Number.isInteger(item) && item >= 0) : []
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
export function surfaceEventView(event) {
|
|
115
|
+
export function surfaceEventView(event, { fullSession = false } = {}) {
|
|
116
116
|
const role = eventRole(String(event?.type || ''))
|
|
117
|
+
const data = event?.data?.message || event?.data || {}
|
|
118
|
+
if (fullSession && role === 'user' && data?.source?.kind !== 'user') return null
|
|
117
119
|
const text = shortText(eventMessageText(event), 12000)
|
|
118
120
|
if (!role || !text) return null
|
|
119
121
|
return {
|
|
@@ -125,42 +127,76 @@ export function surfaceEventView(event) {
|
|
|
125
127
|
}
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
export async function readSelectedSurfaces({ sessionQuery, sessions }, { cwd, sessionIds, includeSubagents = false }) {
|
|
130
|
+
export async function readSelectedSurfaces({ sessionQuery, sessions }, { cwd, sessionIds, fallbackSessionId = '', includeSubagents = false }) {
|
|
129
131
|
const selected = [...new Set((sessionIds || []).map((id) => String(id || '').trim()).filter(Boolean))]
|
|
130
132
|
if (selected.length === 0) throw new Error('至少选择一个对话。')
|
|
131
133
|
const normalizedCwd = normalizeWorkspacePath(cwd)
|
|
132
134
|
if (!normalizedCwd) throw new Error('当前工作路径无效。')
|
|
135
|
+
const fallbackId = String(fallbackSessionId || '').trim()
|
|
136
|
+
const resolvedIds = [...new Set([...selected, ...(fallbackId ? [fallbackId] : [])])]
|
|
133
137
|
const records = []
|
|
134
138
|
if (typeof sessionQuery?.filterSessions === 'function') {
|
|
135
|
-
records.push(...await sessionQuery.filterSessions([{ kind: 'id', values:
|
|
139
|
+
records.push(...await sessionQuery.filterSessions([{ kind: 'id', values: resolvedIds }]))
|
|
136
140
|
} else if (typeof sessionQuery?.listSessions === 'function') {
|
|
137
141
|
const all = await sessionQuery.listSessions()
|
|
138
|
-
records.push(...all.filter((record) =>
|
|
142
|
+
records.push(...all.filter((record) => resolvedIds.includes(String(headerOf(record)?.id || ''))))
|
|
139
143
|
}
|
|
140
144
|
const recordMap = new Map(records.map((record) => [String(headerOf(record)?.id || record?.id || ''), record]))
|
|
141
|
-
const
|
|
142
|
-
for (const id of selected) {
|
|
145
|
+
const readSource = async (id) => {
|
|
143
146
|
const record = recordMap.get(id)
|
|
144
147
|
const header = headerOf(record) || sessions?.get?.(id)?.header
|
|
145
148
|
if (!header?.id) throw new Error(`所选对话不存在或已不可读:${id}`)
|
|
146
149
|
if (!sameWorkspacePath(header.cwd, normalizedCwd)) throw new Error(`所选对话不属于当前工作路径:${id}`)
|
|
147
150
|
if (!includeSubagents && header.origin === 'subagent') throw new Error(`不能选择子 Agent 对话:${id}`)
|
|
148
|
-
if (typeof sessionQuery?.readSurface !== 'function'
|
|
149
|
-
|
|
151
|
+
if (typeof sessionQuery?.readSurface !== 'function' && typeof sessionQuery?.readSession !== 'function') {
|
|
152
|
+
throw new Error('当前 DSH Runtime 未提供 sessionQuery.readSurface/readSession。')
|
|
153
|
+
}
|
|
154
|
+
let snapshot
|
|
155
|
+
let events = []
|
|
156
|
+
let surfaceError = null
|
|
150
157
|
try {
|
|
151
|
-
|
|
158
|
+
if (typeof sessionQuery?.readSurface === 'function') {
|
|
159
|
+
snapshot = await sessionQuery.readSurface(id)
|
|
160
|
+
events = (snapshot?.events || []).map((event) => surfaceEventView(event)).filter(Boolean)
|
|
161
|
+
}
|
|
152
162
|
} catch (error) {
|
|
153
|
-
|
|
163
|
+
surfaceError = error
|
|
154
164
|
}
|
|
155
|
-
|
|
156
|
-
|
|
165
|
+
if (events.length === 0 && typeof sessionQuery?.readSession === 'function') {
|
|
166
|
+
try {
|
|
167
|
+
const full = await sessionQuery.readSession(id)
|
|
168
|
+
snapshot = full || snapshot
|
|
169
|
+
events = (full?.events || []).map((event) => surfaceEventView(event, { fullSession: true })).filter(Boolean)
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (surfaceError) throw new Error(`读取对话“${id}”失败:surface=${errorMessage(surfaceError)};session=${errorMessage(error)}`)
|
|
172
|
+
throw new Error(`读取对话“${id}”完整记录失败:${errorMessage(error)}`)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (surfaceError && events.length === 0) throw new Error(`读取对话“${id}”失败:${errorMessage(surfaceError)}`)
|
|
176
|
+
return {
|
|
157
177
|
sessionId: id,
|
|
158
178
|
title: `对话 ${id.slice(0, 8)}`,
|
|
159
|
-
cwd: normalizeWorkspacePath(
|
|
160
|
-
capturedThroughSeq: Number.isInteger(
|
|
179
|
+
cwd: normalizeWorkspacePath(snapshot?.session?.cwd || header.cwd),
|
|
180
|
+
capturedThroughSeq: Number.isInteger(snapshot?.capturedThroughSeq) ? snapshot.capturedThroughSeq : null,
|
|
161
181
|
events,
|
|
162
182
|
text: events.map((event) => `${event.role === 'user' ? '用户' : '助手'}:${event.text}`).join('\n\n')
|
|
163
|
-
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const sources = []
|
|
186
|
+
let needsFallback = false
|
|
187
|
+
for (const id of selected) {
|
|
188
|
+
const source = await readSource(id)
|
|
189
|
+
if (source.events.length > 0) sources.push(source)
|
|
190
|
+
else needsFallback = true
|
|
191
|
+
}
|
|
192
|
+
if (needsFallback && fallbackId && !sources.some((source) => source.sessionId === fallbackId)) {
|
|
193
|
+
const fallback = await readSource(fallbackId)
|
|
194
|
+
if (fallback.events.length > 0) sources.push(fallback)
|
|
195
|
+
}
|
|
196
|
+
if (sources.length === 0) {
|
|
197
|
+
throw new Error(fallbackId
|
|
198
|
+
? `所选对话及当前对话都没有可读取的用户/助手消息:${selected.join(', ')}`
|
|
199
|
+
: `所选对话没有可读取的用户/助手消息:${selected.join(', ')}`)
|
|
164
200
|
}
|
|
165
201
|
if (typeof sessionQuery?.readTitleSnapshots === 'function' && sources.length) {
|
|
166
202
|
const results = await sessionQuery.readTitleSnapshots(sources.map((source) => source.sessionId))
|