- Add ContextCollector class for managing and merging context entries across sessions - Add types and interfaces for context management (ContextEntry, ContextPriority, PendingContext) - Create context-injector hook for injection coordination - Refactor keyword-detector to use context-injector instead of hook-message-injector - Update src/index.ts to initialize context-injector infrastructure 🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
86 lines
2.1 KiB
TypeScript
86 lines
2.1 KiB
TypeScript
import type {
|
|
ContextEntry,
|
|
ContextPriority,
|
|
PendingContext,
|
|
RegisterContextOptions,
|
|
} from "./types"
|
|
|
|
const PRIORITY_ORDER: Record<ContextPriority, number> = {
|
|
critical: 0,
|
|
high: 1,
|
|
normal: 2,
|
|
low: 3,
|
|
}
|
|
|
|
const CONTEXT_SEPARATOR = "\n\n---\n\n"
|
|
|
|
export class ContextCollector {
|
|
private sessions: Map<string, Map<string, ContextEntry>> = new Map()
|
|
|
|
register(sessionID: string, options: RegisterContextOptions): void {
|
|
if (!this.sessions.has(sessionID)) {
|
|
this.sessions.set(sessionID, new Map())
|
|
}
|
|
|
|
const sessionMap = this.sessions.get(sessionID)!
|
|
const key = `${options.source}:${options.id}`
|
|
|
|
const entry: ContextEntry = {
|
|
id: options.id,
|
|
source: options.source,
|
|
content: options.content,
|
|
priority: options.priority ?? "normal",
|
|
timestamp: Date.now(),
|
|
metadata: options.metadata,
|
|
}
|
|
|
|
sessionMap.set(key, entry)
|
|
}
|
|
|
|
getPending(sessionID: string): PendingContext {
|
|
const sessionMap = this.sessions.get(sessionID)
|
|
|
|
if (!sessionMap || sessionMap.size === 0) {
|
|
return {
|
|
merged: "",
|
|
entries: [],
|
|
hasContent: false,
|
|
}
|
|
}
|
|
|
|
const entries = this.sortEntries([...sessionMap.values()])
|
|
const merged = entries.map((e) => e.content).join(CONTEXT_SEPARATOR)
|
|
|
|
return {
|
|
merged,
|
|
entries,
|
|
hasContent: entries.length > 0,
|
|
}
|
|
}
|
|
|
|
consume(sessionID: string): PendingContext {
|
|
const pending = this.getPending(sessionID)
|
|
this.clear(sessionID)
|
|
return pending
|
|
}
|
|
|
|
clear(sessionID: string): void {
|
|
this.sessions.delete(sessionID)
|
|
}
|
|
|
|
hasPending(sessionID: string): boolean {
|
|
const sessionMap = this.sessions.get(sessionID)
|
|
return sessionMap !== undefined && sessionMap.size > 0
|
|
}
|
|
|
|
private sortEntries(entries: ContextEntry[]): ContextEntry[] {
|
|
return entries.sort((a, b) => {
|
|
const priorityDiff = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]
|
|
if (priorityDiff !== 0) return priorityDiff
|
|
return a.timestamp - b.timestamp
|
|
})
|
|
}
|
|
}
|
|
|
|
export const contextCollector = new ContextCollector()
|