2026-06-14 16:05:04 +01:00
|
|
|
export interface QueryAgentAsk {
|
|
|
|
|
message: string
|
2026-06-16 20:16:03 +01:00
|
|
|
conversationId?: string
|
|
|
|
|
userMessageEntry?: QueryAgentConversationEntryRef
|
2026-07-01 23:50:38 +01:00
|
|
|
signal?: AbortSignal
|
2026-06-14 16:05:04 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-16 20:16:03 +01:00
|
|
|
export type QueryAgentStreamEvent =
|
|
|
|
|
| { type: "conversation"; conversationId: string }
|
2026-06-14 16:05:04 +01:00
|
|
|
| { type: "text_delta"; text: string }
|
|
|
|
|
| { type: "tool_start"; toolName: string }
|
|
|
|
|
| { type: "tool_end"; toolName: string; ok: boolean }
|
|
|
|
|
| { type: "done" }
|
|
|
|
|
| { type: "error"; message: string }
|
|
|
|
|
|
2026-06-16 20:16:03 +01:00
|
|
|
export const QueryAgentEvent = {
|
|
|
|
|
Compaction: "compaction",
|
|
|
|
|
} as const
|
|
|
|
|
|
|
|
|
|
export type QueryAgentEvent = (typeof QueryAgentEvent)[keyof typeof QueryAgentEvent]
|
|
|
|
|
|
|
|
|
|
export interface QueryAgentConversationEntryRef {
|
|
|
|
|
id: string
|
|
|
|
|
sequence: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface QueryAgentCompactedEntryRange {
|
|
|
|
|
startSequence: number
|
|
|
|
|
endSequence: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface QueryAgentCompactionEvent {
|
|
|
|
|
type: typeof QueryAgentEvent.Compaction
|
|
|
|
|
conversationId: string
|
|
|
|
|
summary: string
|
|
|
|
|
firstKeptEntryId: string
|
|
|
|
|
compactedEntryRange: QueryAgentCompactedEntryRange | null
|
|
|
|
|
tokensBefore: number
|
|
|
|
|
details?: unknown
|
|
|
|
|
fromExtension: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface QueryAgentEventMap {
|
|
|
|
|
[QueryAgentEvent.Compaction]: QueryAgentCompactionEvent
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type QueryAgentEventListener<T extends QueryAgentEvent> = (
|
|
|
|
|
event: QueryAgentEventMap[T],
|
|
|
|
|
) => void | Promise<void>
|
|
|
|
|
|
|
|
|
|
export type QueryAgentEventListeners = {
|
|
|
|
|
[T in QueryAgentEvent]: Set<QueryAgentEventListener<T>>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function createQueryAgentEventListeners(): QueryAgentEventListeners {
|
|
|
|
|
return {
|
|
|
|
|
[QueryAgentEvent.Compaction]: new Set(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-14 16:05:04 +01:00
|
|
|
export interface QueryAgent {
|
2026-06-16 20:16:03 +01:00
|
|
|
ask(input: QueryAgentAsk): AsyncIterable<QueryAgentStreamEvent>
|
|
|
|
|
addEventListener<T extends QueryAgentEvent>(
|
|
|
|
|
type: T,
|
|
|
|
|
listener: QueryAgentEventListener<T>,
|
|
|
|
|
): () => void
|
2026-06-14 16:05:04 +01:00
|
|
|
dispose(): void
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface QueryAgentResponse {
|
|
|
|
|
message: string
|
2026-06-16 20:16:03 +01:00
|
|
|
conversationId?: string
|
2026-06-14 16:05:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class QueryAgentError extends Error {
|
|
|
|
|
constructor(message: string) {
|
|
|
|
|
super(message)
|
|
|
|
|
this.name = "QueryAgentError"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function collectQueryAgentResponse(
|
|
|
|
|
agent: QueryAgent,
|
|
|
|
|
input: QueryAgentAsk,
|
|
|
|
|
): Promise<QueryAgentResponse> {
|
|
|
|
|
let message = ""
|
2026-06-16 20:16:03 +01:00
|
|
|
let conversationId: string | undefined
|
2026-06-14 16:05:04 +01:00
|
|
|
|
|
|
|
|
for await (const event of agent.ask(input)) {
|
|
|
|
|
switch (event.type) {
|
2026-06-16 20:16:03 +01:00
|
|
|
case "conversation":
|
|
|
|
|
conversationId = event.conversationId
|
|
|
|
|
break
|
2026-06-14 16:05:04 +01:00
|
|
|
case "text_delta":
|
|
|
|
|
message += event.text
|
|
|
|
|
break
|
|
|
|
|
case "error":
|
|
|
|
|
throw new QueryAgentError(event.message)
|
|
|
|
|
case "tool_start":
|
|
|
|
|
case "tool_end":
|
|
|
|
|
case "done":
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-16 20:16:03 +01:00
|
|
|
return { message, conversationId }
|
2026-06-14 16:05:04 +01:00
|
|
|
}
|