mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
256 lines
8.3 KiB
TypeScript
256 lines
8.3 KiB
TypeScript
/**
|
|
* Model text rendering and generic tool-call presentation.
|
|
*
|
|
* @module @deepseek-ai/dsh-tool-session-query/presentation
|
|
*/
|
|
|
|
import {
|
|
extractSessionEventText,
|
|
type SessionEventSearchHit,
|
|
type SessionEventTraceObservation,
|
|
type SessionEventWindow,
|
|
type SessionLineageTrace,
|
|
type SessionRecord,
|
|
type SessionSearchHit,
|
|
} from '@deepseek-ai/dsh-session-query'
|
|
import type {
|
|
SessionEvent,
|
|
SessionId,
|
|
} from '@deepseek-ai/dsh-session'
|
|
import type { GenericCallView } from '@deepseek-ai/dsh-tools'
|
|
import { workspaceAccess } from './workspace-access.ts'
|
|
|
|
type TitleView = Awaited<ReturnType<typeof workspaceAccess.readTitle>>
|
|
type CompleteTitleMap = Awaited<ReturnType<typeof workspaceAccess.readTitles>>
|
|
type AuthorizedDescendants = ReturnType<typeof workspaceAccess.authorizeDescendants>
|
|
|
|
interface SearchCollection<T> {
|
|
readonly items: T[]
|
|
readonly capped: boolean
|
|
}
|
|
|
|
interface SessionSearchCallArgs {
|
|
readonly query: string
|
|
}
|
|
|
|
interface EventSearchCallArgs {
|
|
readonly query: string
|
|
}
|
|
|
|
interface SessionTargetCallArgs {
|
|
readonly session_id?: string
|
|
}
|
|
|
|
interface EventTargetCallArgs extends SessionTargetCallArgs {
|
|
readonly seq: number
|
|
}
|
|
|
|
function formatSessionSearch(
|
|
collected: SearchCollection<SessionSearchHit>,
|
|
titles: CompleteTitleMap,
|
|
authorizedParents: ReadonlySet<SessionId>,
|
|
): string {
|
|
if (collected.items.length === 0) return formatEmptySessionSearch()
|
|
const lines = [`Session search results (${collected.items.length}):`]
|
|
for (const [index, hit] of collected.items.entries()) {
|
|
const parent = hit.header.parentSession === undefined
|
|
? 'root'
|
|
: authorizedParents.has(hit.header.parentSession)
|
|
? hit.header.parentSession
|
|
: '[outside workspace]'
|
|
const availability = [
|
|
hit.live ? 'live' : undefined,
|
|
hit.persisted ? 'persisted' : undefined,
|
|
].filter((value): value is string => value !== undefined).join(', ') || 'unavailable'
|
|
lines.push(
|
|
'',
|
|
`${index + 1}. Session ${hit.header.id} — ${workspaceAccess.titleText(titles.get(hit.header.id))}`,
|
|
` Created: ${formatTime(hit.header.createdAt)}`,
|
|
` Parent: ${parent}`,
|
|
` Availability: ${availability}`,
|
|
` Best match: seq ${hit.bestMatch.seq} | ${hit.bestMatch.type} | ${hit.bestMatch.surface} | ${formatTime(hit.bestMatch.time)}`,
|
|
` Snippet: ${hit.bestMatch.snippet}`,
|
|
)
|
|
}
|
|
if (collected.capped) {
|
|
lines.push('', 'Result cap reached. Narrow the query or add filters to find additional matches.')
|
|
}
|
|
return lines.join('\n')
|
|
}
|
|
|
|
function formatEmptySessionSearch(): string {
|
|
return 'No prior session matches found.'
|
|
}
|
|
|
|
function formatEventSearch(
|
|
sessionId: SessionId,
|
|
title: TitleView,
|
|
collected: SearchCollection<SessionEventSearchHit>,
|
|
): string {
|
|
const lines = [`Session ${sessionId} — ${workspaceAccess.titleText(title)}`]
|
|
if (collected.items.length === 0) {
|
|
lines.push('', 'No prior event matches found.')
|
|
return lines.join('\n')
|
|
}
|
|
lines.push('', `Event search results (${collected.items.length}):`)
|
|
for (const [index, hit] of collected.items.entries()) {
|
|
lines.push(
|
|
`${index + 1}. seq ${hit.seq} | ${hit.type} | ${hit.surface} | ${formatTime(hit.time)}`,
|
|
` Snippet: ${hit.snippet}`,
|
|
)
|
|
}
|
|
if (collected.capped) {
|
|
lines.push('', 'Result cap reached. Narrow the query or add filters to find additional matches.')
|
|
}
|
|
return lines.join('\n')
|
|
}
|
|
|
|
function formatSessionTrace(
|
|
trace: SessionLineageTrace,
|
|
ancestors: readonly SessionRecord[],
|
|
ancestorBoundary: boolean,
|
|
descendants: AuthorizedDescendants,
|
|
titles: CompleteTitleMap,
|
|
): string {
|
|
const lines = [
|
|
`Session ${trace.target.header.id} — ${workspaceAccess.titleText(titles.get(trace.target.header.id))}`,
|
|
`Created: ${formatTime(trace.target.header.createdAt)}`,
|
|
`Availability: ${availabilityText(trace.target)}`,
|
|
'',
|
|
'Ancestors (nearest first):',
|
|
]
|
|
if (ancestors.length === 0 && !ancestorBoundary) lines.push('- none (target is a root session)')
|
|
for (const record of ancestors) {
|
|
lines.push(`- ${record.header.id} — ${workspaceAccess.titleText(titles.get(record.header.id))} | ${formatTime(record.header.createdAt)} | ${availabilityText(record)}`)
|
|
}
|
|
if (ancestorBoundary) lines.push('- [outside workspace boundary]')
|
|
lines.push('', 'Descendants:')
|
|
if (descendants.length === 0) lines.push('- none')
|
|
else renderDescendants(lines, descendants, titles)
|
|
return lines.join('\n')
|
|
}
|
|
|
|
function renderDescendants(
|
|
lines: string[],
|
|
nodes: AuthorizedDescendants,
|
|
titles: CompleteTitleMap,
|
|
): void {
|
|
for (const { node, depth } of workspaceAccess.visitDescendants(nodes)) {
|
|
const indent = ' '.repeat(depth)
|
|
if (node === null) {
|
|
lines.push(`${indent}- [outside workspace subtree]`)
|
|
continue
|
|
}
|
|
const id = node.record.header.id
|
|
lines.push(`${indent}- ${id} — ${workspaceAccess.titleText(titles.get(id))} | ${formatTime(node.record.header.createdAt)} | ${availabilityText(node.record)}`)
|
|
}
|
|
}
|
|
|
|
function formatEventTrace(
|
|
sessionId: SessionId,
|
|
title: TitleView,
|
|
trace: SessionEventTraceObservation,
|
|
): string {
|
|
return [
|
|
`Session ${sessionId} — ${workspaceAccess.titleText(title)}`,
|
|
`Target: seq ${trace.target.seq} | ${trace.target.type} | ${trace.target.surface} | ${formatTime(trace.target.time)}`,
|
|
`Replaced by: ${trace.replacedBy ?? 'none'}`,
|
|
`Replacement chain: ${seqList(trace.replacementChain)}`,
|
|
`Events replaced by target: ${seqList(trace.replacedEventSeqs)}`,
|
|
`Direct provenance sources: ${seqList(trace.sourceEventSeqs)}`,
|
|
`Direct derived events: ${seqList(trace.derivedEventSeqs)}`,
|
|
].join('\n')
|
|
}
|
|
|
|
function formatEventRead(
|
|
sessionId: SessionId,
|
|
title: TitleView,
|
|
window: SessionEventWindow,
|
|
): string {
|
|
const before = window.events.filter(event => event.seq < window.target.seq)
|
|
const after = window.events.filter(event => event.seq > window.target.seq)
|
|
const lines = [
|
|
`Session ${sessionId} — ${workspaceAccess.titleText(title)}`,
|
|
`Target event seq ${window.target.seq}:`,
|
|
'```json',
|
|
JSON.stringify(window.target, null, 2),
|
|
'```',
|
|
]
|
|
if (before.length > 0) {
|
|
lines.push('', 'Before:')
|
|
for (const event of before) lines.push(formatNeighbor(event))
|
|
}
|
|
if (after.length > 0) {
|
|
lines.push('', 'After:')
|
|
for (const event of after) lines.push(formatNeighbor(event))
|
|
}
|
|
return lines.join('\n')
|
|
}
|
|
|
|
function formatNeighbor(event: SessionEvent): string {
|
|
const text = extractSessionEventText(event)
|
|
return `- seq ${event.seq} | ${event.type} | ${formatTime(event.time)}`
|
|
+ (text.length === 0 ? ' | (no semantic text)' : `\n ${text.replaceAll('\n', '\n ')}`)
|
|
}
|
|
|
|
function availabilityText(record: SessionRecord): string {
|
|
return [
|
|
record.live ? 'live' : undefined,
|
|
record.persisted ? 'persisted' : undefined,
|
|
].filter((value): value is string => value !== undefined).join(', ') || 'unavailable'
|
|
}
|
|
|
|
function seqList(values: readonly number[]): string {
|
|
return values.length === 0 ? 'none' : values.join(', ')
|
|
}
|
|
|
|
function formatTime(value: number): string {
|
|
return new Date(value).toISOString()
|
|
}
|
|
|
|
function presentSessionSearchCall(args: SessionSearchCallArgs): GenericCallView {
|
|
return { card: 'generic', kind: 'search', title: 'Search prior sessions', rawInput: args.query }
|
|
}
|
|
|
|
function presentEventSearchCall(args: EventSearchCallArgs): GenericCallView {
|
|
return { card: 'generic', kind: 'search', title: 'Search session events', rawInput: args.query }
|
|
}
|
|
|
|
function presentSessionTraceCall(args: SessionTargetCallArgs): GenericCallView {
|
|
return {
|
|
card: 'generic',
|
|
kind: 'read',
|
|
title: args.session_id === undefined ? 'Trace current session' : `Trace session ${args.session_id}`,
|
|
...args.session_id === undefined ? {} : { rawInput: args.session_id },
|
|
}
|
|
}
|
|
|
|
function presentEventTargetCall(
|
|
action: string,
|
|
args: EventTargetCallArgs,
|
|
): GenericCallView {
|
|
return {
|
|
card: 'generic',
|
|
kind: 'read',
|
|
title: `${action} ${args.seq}`,
|
|
rawInput: {
|
|
...args.session_id === undefined ? {} : { session_id: args.session_id },
|
|
seq: args.seq,
|
|
},
|
|
}
|
|
}
|
|
|
|
/** Text output and call-card presentation for every session-query tool. */
|
|
export const presentation = {
|
|
formatSessionSearch,
|
|
formatEmptySessionSearch,
|
|
formatEventSearch,
|
|
formatSessionTrace,
|
|
formatEventTrace,
|
|
formatEventRead,
|
|
presentSessionSearchCall,
|
|
presentEventSearchCall,
|
|
presentSessionTraceCall,
|
|
presentEventTargetCall,
|
|
}
|