56db06811e
* Add native Codex hooks integration * Address Codex review feedback * Use durable Codex marketplace root * Address Codex file context review feedback * Harden Codex installer review paths * Report Codex legacy cleanup failures * fix: keep MCP manifests in marketplace sync * fix: bundle zod in MCP server * fix: warn on Codex legacy cleanup failure * Fix hook observation readiness timeouts * Address Codex hook review notes * Tighten Codex MCP file context matching * Resolve final Codex review nits * Add Codex marketplace version guidance * Reset worker failure counter on API fallback * Fix Codex cat flag file extraction
90 lines
3.5 KiB
TypeScript
90 lines
3.5 KiB
TypeScript
|
|
import type { EventHandler, NormalizedHookInput, HookResult } from '../types.js';
|
|
import { executeWithWorkerFallback, isWorkerFallback } from '../../shared/worker-utils.js';
|
|
import { logger } from '../../utils/logger.js';
|
|
import { extractLastMessage } from '../../shared/transcript-parser.js';
|
|
import { stripMemoryTagsFromPrompt } from '../../utils/tag-stripping.js';
|
|
import { HOOK_EXIT_CODES } from '../../shared/hook-constants.js';
|
|
import { normalizePlatformSource } from '../../shared/platform-source.js';
|
|
import { shouldTrackProject } from '../../shared/should-track-project.js';
|
|
|
|
export const summarizeHandler: EventHandler = {
|
|
async execute(input: NormalizedHookInput): Promise<HookResult> {
|
|
if (input.cwd && !shouldTrackProject(input.cwd)) {
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
}
|
|
|
|
if (input.stopHookActive === true) {
|
|
logger.debug('HOOK', 'Skipping summary: Codex Stop hook re-entry detected', {
|
|
sessionId: input.sessionId,
|
|
});
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
}
|
|
|
|
if (input.agentId) {
|
|
logger.debug('HOOK', 'Skipping summary: subagent context detected', {
|
|
sessionId: input.sessionId,
|
|
agentId: input.agentId,
|
|
agentType: input.agentType
|
|
});
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
}
|
|
|
|
const { sessionId, transcriptPath } = input;
|
|
|
|
if (!sessionId) {
|
|
logger.warn('HOOK', 'summarize: No sessionId provided, skipping');
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
}
|
|
|
|
let lastAssistantMessage = '';
|
|
|
|
if (input.lastAssistantMessage !== undefined) {
|
|
lastAssistantMessage = stripMemoryTagsFromPrompt(input.lastAssistantMessage);
|
|
} else {
|
|
if (!transcriptPath) {
|
|
logger.debug('HOOK', `No transcriptPath in Stop hook input for session ${sessionId} - skipping summary`);
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
}
|
|
|
|
try {
|
|
lastAssistantMessage = extractLastMessage(transcriptPath, 'assistant', true);
|
|
lastAssistantMessage = stripMemoryTagsFromPrompt(lastAssistantMessage);
|
|
} catch (err) {
|
|
logger.warn('HOOK', `Stop hook: failed to extract last assistant message for session ${sessionId}: ${err instanceof Error ? err.message : err}`);
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
}
|
|
}
|
|
|
|
if (!lastAssistantMessage || !lastAssistantMessage.trim()) {
|
|
logger.debug('HOOK', 'No assistant message available - skipping summary', {
|
|
sessionId,
|
|
transcriptPath
|
|
});
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
}
|
|
|
|
logger.dataIn('HOOK', 'Stop: Requesting summary', {
|
|
hasLastAssistantMessage: !!lastAssistantMessage
|
|
});
|
|
|
|
const platformSource = normalizePlatformSource(input.platform);
|
|
|
|
const queueResult = await executeWithWorkerFallback<{ status?: string }>(
|
|
'/api/sessions/summarize',
|
|
'POST',
|
|
{
|
|
contentSessionId: sessionId,
|
|
last_assistant_message: lastAssistantMessage,
|
|
platformSource,
|
|
},
|
|
);
|
|
if (isWorkerFallback(queueResult)) {
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
}
|
|
|
|
logger.debug('HOOK', 'Summary request queued, exiting hook');
|
|
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
|
|
},
|
|
};
|