@civic/hub-bridge
Version:
Stdio <-> HTTP/SSE MCP bridge with Civic auth handling
127 lines • 5.67 kB
JavaScript
export {};
// import { AbstractHook } from "@civic/hook-common";
// import type { HookResponse, ToolCall, HookContext } from "@civic/hook-common";
// import { logger } from "../utils/logger.js";
//
// /**
// * SessionRecoveryHook detects when the server has dropped the session
// * and automatically recreates the client connection.
// *
// * This hook monitors responses for the specific error message:
// * "Bad Request: No valid session ID provided or not an initialize request"
// * which indicates the server has lost the session.
// */
// export class SessionRecoveryHook extends AbstractHook {
// private isRecovering = false;
//
// get name(): string {
// return "SessionRecoveryHook";
// }
//
// /**
// * Check if the error indicates a dropped session
// */
// private isSessionDroppedError(error: unknown): boolean {
// // Check for Error object with session drop message
// if (error instanceof Error) {
// const isSessionError = error.message.includes("No valid session ID provided or not an initialize request");
// if (isSessionError) {
// logger.info(`SessionRecoveryHook: Detected session drop: ${error.message}`);
// return true;
// }
// }
//
// return false;
// }
//
// async processToolException(toolError: unknown, originalToolCall: ToolCall, context: HookContext): Promise<HookResponse> {
// try {
// // Skip if we're already in recovery process to avoid recursion
// if (this.isRecovering) {
// return { response: "continue" };
// }
//
// if (!context || !isPassthroughServerContext(context)) {
// logger.error(`Hook ${this.name} is not running in PassthroughServerContext, skipping session recovery. Context: ${JSON.stringify(context)}`);
// return { response: "continue" };
// }
//
// // Check if this error indicates a session drop
// const isSessionDropped = this.isSessionDroppedError(toolError);
//
// if (isSessionDropped) {
// logger.info(`SessionRecoveryHook: Starting session recovery for tool: ${originalToolCall.name}`);
//
// // Set recovery flag to prevent recursion
// this.isRecovering = true;
//
// try {
// const passthroughServerHookContext = getPassthroughServerContext(context)!;
//
// // Recreate the client
// const newClient = await passthroughServerHookContext.recreateClient();
//
// // Now retry the original tool call with the new client
// try {
// // Call the target client's tool with arguments (potentially modified by hook)
// const toolCallWithArgs = {
// ...originalToolCall,
// arguments:
// typeof originalToolCall.arguments === "object" &&
// originalToolCall.arguments !== null
// ? (originalToolCall.arguments as Record<string, unknown>)
// : undefined,
// };
// const result = await newClient.callTool(toolCallWithArgs);
//
// logger.info(`SessionRecoveryHook: Tool call succeeded after recovery`);
//
// return {
// response: "abort" as const,
// body: result,
// reason: "Session was invalid an needed to be recovered" as const,
// };
//
// } catch (retryError) {
// logger.error(`SessionRecoveryHook: Tool call failed after recovery:`, retryError);
//
// // Return the retry error instead of the original session error
// return {
// response: "abort" as const,
// body: {
// jsonrpc: "2.0",
// error: {
// code: -32603,
// message: "Tool call failed after session recovery.",
// data: {
// recoveryPerformed: true,
// originalError: toolError,
// retryError: retryError
// }
// },
// id: null
// }
// };
// }
//
// } finally {
// // Always reset the recovery flag
// this.isRecovering = false;
// }
// }
//
// // Continue with the original error if no session drop detected
// return { response: "continue" };
//
// } catch (processingError) {
// logger.error("SessionRecoveryHook: Error in processToolException:", processingError);
//
// // Reset recovery flag on error
// this.isRecovering = false;
//
// // Continue with original error on processing failure to avoid breaking the flow
// return { response: "continue" };
// }
// }
// }
//# sourceMappingURL=session-recovery-hook.js.map