import type { Context } from 'cordis' import { CallId, LlmAdapter, ReasoningEffortId, type GenerateOptions, type LlmResolvedModelInfo, type StreamChunk, } from '@deepseek-ai/dsh-llm' const HIGH = ReasoningEffortId('high') const OFF = ReasoningEffortId('off') /** Keyless headless-agent adapter: one real bash call followed by a final answer. */ class CliMockAdapter extends LlmAdapter { override async resolveModel(provider: string, model: string): Promise { return { provider, id: model, name: model, reasoning: { efforts: [ { id: OFF, name: 'Off' }, { id: HIGH, name: 'High' }, ], defaultEffort: HIGH, }, } } async * stream(options: GenerateOptions): AsyncIterable { const toolResult = options.messages.at(-1)?.content.find(block => block.type === 'tool-result') if (toolResult === undefined) { const args = JSON.stringify({ command: 'printf CLI_TOOL_ROUND_TRIP', description: 'Prove the CLI tool round trip.' }) yield { type: 'block-start', index: 0, blockType: 'tool-call' } yield { type: 'tool-call-delta', index: 0, id: CallId('cli-smoke-call'), name: 'bash', argumentsDelta: args } yield { type: 'block-end', index: 0, block: { type: 'tool-call', id: CallId('cli-smoke-call'), name: 'bash', arguments: args } } yield { type: 'usage', usage: { inputTokens: 11, outputTokens: 3, cacheReadTokens: 2 } } yield { type: 'finish', reason: { kind: 'tool-calls' } } return } const toolText = toolResult.content .filter(block => block.type === 'text') .map(block => block.text) .join('') const reply = `CLI tool round trip complete: ${toolText.trim()}` yield { type: 'block-start', index: 0, blockType: 'text' } yield { type: 'text-delta', index: 0, text: reply } yield { type: 'block-end', index: 0, block: { type: 'text', text: reply } } yield { type: 'usage', usage: { inputTokens: 7, outputTokens: 5, reasoningTokens: 1 } } yield { type: 'finish', reason: { kind: 'stop' } } } } export const name = 'cli-mock-llm' export const inject = ['llm'] /** Register the keyless `cli-mock` adapter. */ export function apply(ctx: Context): void { ctx.llm.registerAdapter(['cli-mock'], new CliMockAdapter()) ctx.on('agent/request', async (_agent, _turn, step, _config, _signal, next) => { const config = await next() return step === 2 ? { ...config, reasoningEffort: OFF } : config }) }