deepseek-harness/packages/session-query/session-query/src/documents.ts
Hypatia May 0a0f19cf57 Merge remote-tracking branch 'origin/master' into session-query-search
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-10-session-query-service.md
#	.agents/notes/implemented/feature/2026-07-10-sqlite-session-query-provider.md
#	.agents/notes/proposed/feature/2026-07-10-sqlite-session-query-provider.md
#	docs/architecture.md
#	docs/capability-seams.md
#	docs/config-catalog.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.md
#	docs/core-data-structures/persistence.md
#	docs/core-data-structures/session-query.md
#	docs/module-graph.md
#	docs/rfc/INDEX.md
#	packages/README.md
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/hooks/hooks-claude/tests/coverage.spec.ts
#	packages/session-persistence/session-persistence-jsonl/src/index.ts
#	packages/session-persistence/session-persistence-jsonl/tests/jsonl.spec.ts
#	packages/session-persistence/session-persistence-sqlite/README.md
#	packages/session-persistence/session-persistence-sqlite/src/index.ts
#	packages/session-persistence/session-persistence-sqlite/src/schema.ts
#	packages/session-persistence/session-persistence-sqlite/tests/sqlite.spec.ts
#	packages/session-persistence/session-persistence/README.md
#	packages/session-persistence/session-persistence/package.json
#	packages/session-query/README.md
#	packages/session-query/session-query/README.md
#	packages/session-query/session-query/package.json
#	packages/session-query/session-query/src/config.ts
#	packages/session-query/session-query/src/index.ts
#	packages/session-query/session-query/src/types.ts
#	pnpm-lock.yaml
#	scripts/gen-doc-graphs.ts
#	scripts/type-equiv.manifest.json
#	tsconfig.host.json
#	tsconfig.json
2026-07-23 13:56:56 +08:00

74 lines
2.5 KiB
TypeScript

/** Shared event metadata and semantic-document projection. */
import { foldSurface } from '@deepseek-ai/dsh-session'
import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session'
import type { SessionEventRecord, SessionEventSearchDocument, SessionEventSurface } from './types.ts'
import { SessionQueryError } from './config.ts'
import { extractSessionEventText } from './extraction.ts'
/**
* Project a raw log into lightweight surface-aware event records.
* @param sessionId - session that owns the log.
* @param events - complete contiguous raw event log.
* @returns one record per event in ascending seq order.
*/
export function buildSessionEventRecords(
sessionId: SessionId,
events: readonly SessionEvent[],
): SessionEventRecord[] {
const surfaceBySeq = classifySurface(events)
return events.map(event => ({
sessionId,
seq: event.seq,
type: event.type,
time: event.time,
surface: surfaceBySeq.get(event.seq) ?? 'log-only',
}))
}
/**
* Build first-party semantic documents for one complete raw event log.
* @param sessionId - session that owns the log.
* @param events - complete contiguous raw event log.
* @returns searchable documents in ascending seq order; structural events are omitted.
*/
export function buildSessionEventSearchDocuments(
sessionId: SessionId,
events: readonly SessionEvent[],
): SessionEventSearchDocument[] {
const surfaceBySeq = classifySurface(events)
const documents: SessionEventSearchDocument[] = []
for (const event of events) {
const text = extractSessionEventText(event)
if (text.length === 0) continue
documents.push({
sessionId,
seq: event.seq,
type: event.type,
time: event.time,
surface: surfaceBySeq.get(event.seq) ?? 'log-only',
text,
})
}
return documents
}
function classifySurface(events: readonly SessionEvent[]): Map<number, SessionEventSurface> {
let folded: ReturnType<typeof foldSurface>
try {
folded = foldSurface(events)
} catch (error: unknown) {
throw new SessionQueryError(
/* v8 ignore next -- foldSurface throws Error instances */
`invalid session surface: ${error instanceof Error ? error.message : 'unknown error'}`,
'SESSION_QUERY_INVALID_SURFACE',
{ cause: error },
)
}
const result = new Map<number, SessionEventSurface>()
for (const seq of folded.nodes) result.set(seq, 'current')
for (const replacement of folded.replacements) {
for (const seq of replacement.shadowedSeqs) result.set(seq, 'shadowed')
}
return result
}