Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
4.4 kB · 141 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142import { randomUUID } from 'crypto'import type { QuerySource } from '../../constants/querySource.js'import { queryModelWithoutStreaming } from '../../services/api/claude.js'import type { Message } from '../../types/message.js'import { createAbortController } from '../../utils/abortController.js'import { logError } from '../../utils/log.js'import { toError } from '../errors.js'import { extractTextContent } from '../messages.js'import { asSystemPrompt } from '../systemPromptType.js'import type { REPLHookContext } from './postSamplingHooks.js'
export type ApiQueryHookContext = REPLHookContext & { queryMessageCount?: number}
export type ApiQueryHookConfig<TResult> = { name: QuerySource shouldRun: (context: ApiQueryHookContext) => Promise<boolean>
// Build the complete message list to send to the API buildMessages: (context: ApiQueryHookContext) => Message[]
// Optional: override system prompt (defaults to context.systemPrompt) systemPrompt?: string
// Optional: whether to use tools from context (defaults to true) // Set to false to pass empty tools array useTools?: boolean
parseResponse: (content: string, context: ApiQueryHookContext) => TResult logResult: ( result: ApiQueryResult<TResult>, context: ApiQueryHookContext, ) => void // Must be a function to ensure lazy loading (config is accessed before allowed) // Receives context so callers can inherit the main loop model if desired. getModel: (context: ApiQueryHookContext) => string}
export type ApiQueryResult<TResult> = | { type: 'success' queryName: string result: TResult messageId: string model: string uuid: string } | { type: 'error' queryName: string error: Error uuid: string }
export function createApiQueryHook<TResult>( config: ApiQueryHookConfig<TResult>,) { return async (context: ApiQueryHookContext): Promise<void> => { try { const shouldRun = await config.shouldRun(context) if (!shouldRun) { return }
const uuid = randomUUID()
// Build messages using the config's buildMessages function const messages = config.buildMessages(context) context.queryMessageCount = messages.length
// Use config's system prompt if provided, otherwise use context's const systemPrompt = config.systemPrompt ? asSystemPrompt([config.systemPrompt]) : context.systemPrompt
// Use config's tools preference (defaults to true = use context tools) const useTools = config.useTools ?? true const tools = useTools ? context.toolUseContext.options.tools : []
// Get model (lazy loaded) const model = config.getModel(context)
// Make API call const response = await queryModelWithoutStreaming({ messages, systemPrompt, thinkingConfig: { type: 'disabled' as const }, tools, signal: createAbortController().signal, options: { getToolPermissionContext: async () => { const appState = context.toolUseContext.getAppState() return appState.toolPermissionContext }, model, toolChoice: undefined, isNonInteractiveSession: context.toolUseContext.options.isNonInteractiveSession, hasAppendSystemPrompt: !!context.toolUseContext.options.appendSystemPrompt, temperatureOverride: 0, agents: context.toolUseContext.options.agentDefinitions.activeAgents, querySource: config.name, mcpTools: [], agentId: context.toolUseContext.agentId, }, })
// Parse response const content = extractTextContent(response.message.content).trim()
try { const result = config.parseResponse(content, context) config.logResult( { type: 'success', queryName: config.name, result, messageId: response.message.id, model, uuid, }, context, ) } catch (error) { config.logResult( { type: 'error', queryName: config.name, error: error as Error, uuid, }, context, ) } } catch (error) { logError(toError(error)) } }}