1010 */
1111
1212import { randomUUID } from 'node:crypto' ;
13- import { autoRecordDispatchTokenUsage , getProjectRoot } from '@cleocode/core/internal' ;
13+ import { autoRecordDispatchTokenUsage , getProjectRoot , hooks } from '@cleocode/core/internal' ;
1414import { type CliOutputOptions , cliError , cliOutput } from '../../cli/renderers/index.js' ;
1515import { Dispatcher } from '../dispatcher.js' ;
1616import { createDomainHandlers } from '../domains/index.js' ;
@@ -141,6 +141,22 @@ export async function dispatchFromCli(
141141 outputOpts ?: CliOutputOptions ,
142142) : Promise < void > {
143143 const dispatcher = getCliDispatcher ( ) ;
144+ const projectRoot = getProjectRoot ( ) ;
145+ const dispatchStart = Date . now ( ) ;
146+
147+ // Dispatch onPromptSubmit hook (best-effort, fire-and-forget)
148+ hooks
149+ . dispatch ( 'onPromptSubmit' , projectRoot , {
150+ timestamp : new Date ( ) . toISOString ( ) ,
151+ gateway,
152+ domain,
153+ operation,
154+ source : 'cli' ,
155+ } )
156+ . catch ( ( ) => {
157+ /* hook errors are non-fatal */
158+ } ) ;
159+
144160 const response = await dispatcher . dispatch ( {
145161 gateway,
146162 domain,
@@ -150,6 +166,21 @@ export async function dispatchFromCli(
150166 requestId : randomUUID ( ) ,
151167 } ) ;
152168
169+ // Dispatch onResponseComplete hook (best-effort, fire-and-forget)
170+ hooks
171+ . dispatch ( 'onResponseComplete' , projectRoot , {
172+ timestamp : new Date ( ) . toISOString ( ) ,
173+ gateway,
174+ domain,
175+ operation,
176+ success : response . success ,
177+ durationMs : Date . now ( ) - dispatchStart ,
178+ errorCode : response . error ?. code ,
179+ } )
180+ . catch ( ( ) => {
181+ /* hook errors are non-fatal */
182+ } ) ;
183+
153184 if ( response . success ) {
154185 await autoRecordDispatchTokenUsage ( {
155186 requestPayload : params ,
@@ -219,12 +250,45 @@ export async function dispatchRaw(
219250 params ?: Record < string , unknown > ,
220251) : Promise < DispatchResponse > {
221252 const dispatcher = getCliDispatcher ( ) ;
222- return dispatcher . dispatch ( {
253+ const projectRoot = getProjectRoot ( ) ;
254+ const dispatchStart = Date . now ( ) ;
255+
256+ // Dispatch onPromptSubmit hook (best-effort, fire-and-forget)
257+ hooks
258+ . dispatch ( 'onPromptSubmit' , projectRoot , {
259+ timestamp : new Date ( ) . toISOString ( ) ,
260+ gateway,
261+ domain,
262+ operation,
263+ source : 'cli' ,
264+ } )
265+ . catch ( ( ) => {
266+ /* hook errors are non-fatal */
267+ } ) ;
268+
269+ const response = await dispatcher . dispatch ( {
223270 gateway,
224271 domain,
225272 operation,
226273 params,
227274 source : 'cli' ,
228275 requestId : randomUUID ( ) ,
229276 } ) ;
277+
278+ // Dispatch onResponseComplete hook (best-effort, fire-and-forget)
279+ hooks
280+ . dispatch ( 'onResponseComplete' , projectRoot , {
281+ timestamp : new Date ( ) . toISOString ( ) ,
282+ gateway,
283+ domain,
284+ operation,
285+ success : response . success ,
286+ durationMs : Date . now ( ) - dispatchStart ,
287+ errorCode : response . error ?. code ,
288+ } )
289+ . catch ( ( ) => {
290+ /* hook errors are non-fatal */
291+ } ) ;
292+
293+ return response ;
230294}
0 commit comments