Spaces:
Sleeping
Sleeping
| import { checkUrlRequestSchema } from '@/schema/gradio-proxy/check-url'; | |
| import { excelRequestSchema } from '@/schema/gradio-proxy/excel'; | |
| import { poxRequestSchema } from '@/schema/gradio-proxy/pox'; | |
| import { proposalCnRequestSchema } from '@/schema/gradio-proxy/proposal-cn'; | |
| import { proposalFvRequestSchema } from '@/schema/gradio-proxy/proposal-fv'; | |
| import { proposalIntentRequestSchema } from '@/schema/gradio-proxy/proposal-intent'; | |
| import { proposalPredictionRequestSchema } from '@/schema/gradio-proxy/proposal-prediction'; | |
| import { refreshMomentRequestSchema } from '@/schema/gradio-proxy/refresh-moment'; | |
| import { scoreStep3RequestSchema } from '@/schema/gradio-proxy/score-step3'; | |
| import { summaryRequestSchema } from '@/schema/gradio-proxy/summary'; | |
| import { themeByMomentRequestSchema } from '@/schema/gradio-proxy/theme-by-moment'; | |
| import { visScoreRequestSchema } from '@/schema/gradio-proxy/vis-score'; | |
| import { AppError } from '@/lib/errors'; | |
| import { getDummyData } from '@/server/utils/dummy-data'; | |
| import { | |
| getCheckUrl, | |
| getExcel, | |
| getPox, | |
| getProposalCn, | |
| getProposalFv, | |
| getProposalIntent, | |
| getProposalPrediction, | |
| getRefreshMoment, | |
| getScoreStep3, | |
| getSummary, | |
| getThemeByMoment, | |
| getVisScore, | |
| } from '@/services/gradio'; | |
| import { zValidator } from '@hono/zod-validator'; | |
| import { Hono } from 'hono'; | |
| /** | |
| * Gradio APIエラーを統一的に処理するヘルパー関数 | |
| */ | |
| function handleGradioError(error: unknown): { statusCode: number; message: string } { | |
| let errorMessage = '不明なエラーが発生しました。'; | |
| let statusCode = 500; | |
| if (error instanceof AppError) { | |
| errorMessage = error.message; | |
| statusCode = error.statusCode || 500; | |
| } else if (error instanceof Error) { | |
| errorMessage = error.message; | |
| // タイムアウトエラー | |
| if (error.message.includes('タイムアウト') || error.message.includes('timeout')) { | |
| errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。'; | |
| statusCode = 408; | |
| } | |
| if ('statusCode' in error && typeof error.statusCode === 'number') { | |
| statusCode = error.statusCode; | |
| } | |
| } | |
| return { statusCode, message: errorMessage }; | |
| } | |
| export const gradioProxyRoute = new Hono() | |
| // check_url API (POST /check-url) | |
| .post('/check-url', zValidator('json', checkUrlRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_check_url.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[CHECK_URL API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getCheckUrl( | |
| { | |
| ownUrl: request.ownUrl, | |
| urlText: request.urlText, | |
| ownImage: request.ownImage, | |
| ownImageName: request.ownImageName, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| // エラーレスポンスチェック | |
| if (result && typeof result === 'object' && 'status' in result && result.status === 'error') { | |
| return c.json(result, 400); | |
| } | |
| return c.json(result); | |
| } catch (error) { | |
| console.error('[CHECK_URL API] Error:', error); | |
| const { statusCode, message } = handleGradioError(error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // score_step3 API (POST /score-step3) | |
| .post( | |
| '/score-step3', | |
| zValidator('json', scoreStep3RequestSchema, (result, c) => { | |
| if (!result.success) { | |
| console.error('[SCORE_STEP3 API] Validation error:', JSON.stringify(result.error.issues, null, 2)); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: `リクエストのバリデーションに失敗しました: ${result.error.issues.map((i) => i.message).join(', ')}`, | |
| }, | |
| 400, | |
| ); | |
| } | |
| }), | |
| async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_score.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getScoreStep3( | |
| { | |
| tempImages: request.tempImages, | |
| fvInfos: request.fvInfos, | |
| cnInfo: request.cnInfo, | |
| commonDict: request.commonDict, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| console.error('[SCORE_STEP3 API] Error:', error); | |
| const { statusCode, message } = handleGradioError(error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }, | |
| ) | |
| // vis_score API (POST /vis-score) | |
| .post('/vis-score', zValidator('json', visScoreRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_vis_score.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[VIS_SCORE API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getVisScore( | |
| { | |
| commonDict: request.commonDict, | |
| scoreDict: request.scoreDict, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| console.error('[VIS_SCORE API] Error:', error); | |
| const { statusCode, message } = handleGradioError(error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // summary API (POST /summary) | |
| .post('/summary', zValidator('json', summaryRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_summary.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[SUMMARY API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getSummary( | |
| { | |
| commonDict: request.commonDict, | |
| scoreDict: request.scoreDict, | |
| score_total: request.score_total, | |
| url_category_scores: request.url_category_scores, | |
| own_category_score: request.own_category_score, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| console.error('[SUMMARY API] Error:', error); | |
| const { statusCode, message } = handleGradioError(error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // pox API (POST /pox) | |
| .post('/pox', zValidator('json', poxRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_pox.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[POX API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getPox( | |
| { | |
| commonDict: request.commonDict, | |
| scoreDict: request.scoreDict, | |
| score_total: request.score_total, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| console.error('[POX API] Error:', error); | |
| const { statusCode, message } = handleGradioError(error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // excel API (POST /excel) | |
| .post('/excel', zValidator('json', excelRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_excel.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[EXCEL API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getExcel( | |
| { | |
| ownUrl: request.ownUrl, | |
| urlText: request.urlText, | |
| commonDict: request.commonDict, | |
| scoreDict: request.scoreDict, | |
| summary: request.summary, | |
| swot: request.swot, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| console.error('[EXCEL API] Error:', error); | |
| const { statusCode, message } = handleGradioError(error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // theme_by_moment API (POST /theme-by-moment) | |
| .post( | |
| '/theme-by-moment', | |
| zValidator('json', themeByMomentRequestSchema, (result, c) => { | |
| if (!result.success) { | |
| console.error('[THEME_BY_MOMENT API] Validation failed:', result.error.issues); | |
| return c.json({ success: false, error: result.error.issues }, 400); | |
| } | |
| }), | |
| async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_theme_by_moment.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[THEME_BY_MOMENT API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getThemeByMoment( | |
| { | |
| commonDict: request.commonDict || {}, | |
| scoreDict: request.scoreDict || {}, | |
| swot: request.swot || {}, | |
| strategies: request.strategies || {}, | |
| moments: request.moments || [], | |
| fv_infos: request.fv_infos ?? undefined, | |
| own_theme: request.own_theme || '', | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| let errorMessage = '不明なエラーが発生しました。'; | |
| let statusCode = 500; | |
| if (error instanceof Error) { | |
| errorMessage = error.message; | |
| if (error.message.includes('タイムアウト') || error.message.includes('timeout')) { | |
| errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。'; | |
| statusCode = 408; | |
| } | |
| } | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: errorMessage, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }, | |
| ) | |
| // proposal_fv API (POST /proposal-fv) | |
| .post('/proposal-fv', zValidator('json', proposalFvRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_proposal_fv.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[PROPOSAL_FV API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getProposalFv( | |
| { | |
| strategy_x_moment: request.strategy_x_moment, | |
| commonDict: request.commonDict, | |
| fv_infos: request.fv_infos, | |
| strategies: request.strategies, | |
| cnall_json: request.cnall_json, | |
| url_category_scores: request.url_category_scores, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| let errorMessage = '不明なエラーが発生しました。'; | |
| let statusCode = 500; | |
| if (error instanceof Error) { | |
| errorMessage = error.message; | |
| if (error.message.includes('タイムアウト') || error.message.includes('timeout')) { | |
| errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。'; | |
| statusCode = 408; | |
| } | |
| } | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: errorMessage, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // proposal_cn API (POST /proposal-cn) | |
| .post('/proposal-cn', zValidator('json', proposalCnRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_proposal_cn.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[PROPOSAL_CN API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getProposalCn( | |
| { | |
| strategy_x_moment: request.strategy_x_moment, | |
| commonDict: request.commonDict, | |
| cnall_json: request.cnall_json, | |
| strategies: request.strategies, | |
| fv_infos: request.fv_infos, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| let errorMessage = '不明なエラーが発生しました。'; | |
| let statusCode = 500; | |
| if (error instanceof Error) { | |
| errorMessage = error.message; | |
| if (error.message.includes('タイムアウト') || error.message.includes('timeout')) { | |
| errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。'; | |
| statusCode = 408; | |
| } | |
| } | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: errorMessage, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // proposal_prediction API (POST /proposal-prediction) | |
| .post('/proposal-prediction', zValidator('json', proposalPredictionRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_proposal_prediction.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[PROPOSAL_PREDICTION API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getProposalPrediction( | |
| { | |
| proposal_fv: request.proposal_fv, | |
| proposal_cn: request.proposal_cn, | |
| commonDict: request.commonDict, | |
| fv_infos: request.fv_infos, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| let errorMessage = '不明なエラーが発生しました。'; | |
| let statusCode = 500; | |
| if (error instanceof Error) { | |
| errorMessage = error.message; | |
| if (error.message.includes('タイムアウト') || error.message.includes('timeout')) { | |
| errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。'; | |
| statusCode = 408; | |
| } | |
| } | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: errorMessage, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // proposal_intent API (POST /proposal-intent) | |
| .post('/proposal-intent', zValidator('json', proposalIntentRequestSchema), async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_proposal_intent.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[PROPOSAL_INTENT API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getProposalIntent( | |
| { | |
| proposal_fv: request.proposal_fv, | |
| proposal_cn: request.proposal_cn, | |
| commonDict: request.commonDict, | |
| swot: request.swot, | |
| q_summary: request.q_summary, | |
| strategy_x_moment: request.strategy_x_moment, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| let errorMessage = '不明なエラーが発生しました。'; | |
| let statusCode = 500; | |
| if (error instanceof Error) { | |
| errorMessage = error.message; | |
| if (error.message.includes('タイムアウト') || error.message.includes('timeout')) { | |
| errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。'; | |
| statusCode = 408; | |
| } | |
| } | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: errorMessage, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }) | |
| // refresh_moment API (POST /refresh-moment) | |
| .post( | |
| '/refresh-moment', | |
| zValidator('json', refreshMomentRequestSchema, (result, c) => { | |
| if (!result.success) { | |
| console.error('[REFRESH_MOMENT API] Validation failed:', result.error.issues); | |
| return c.json({ success: false, error: result.error.issues }, 400); | |
| } | |
| }), | |
| async (c) => { | |
| try { | |
| const request = c.req.valid('json'); | |
| // ダミーモード時はJSONファイルを返す | |
| if (request.dummyMode) { | |
| try { | |
| const dummyData = getDummyData('get_refresh_moment.json'); | |
| return c.json(dummyData); | |
| } catch (error) { | |
| console.error('[REFRESH_MOMENT API] Dummy data loading failed:', error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message: error instanceof Error ? error.message : 'ダミーデータの読み込みに失敗しました。', | |
| }, | |
| 404, | |
| ); | |
| } | |
| } | |
| // 通常モード時はGradio APIを呼び出し | |
| const result = await getRefreshMoment( | |
| { | |
| commonDict: request.commonDict || {}, | |
| scoreDict: request.scoreDict || {}, | |
| swot: request.swot || {}, | |
| }, | |
| request.userEmail || null, | |
| request.userIdentifier, | |
| ); | |
| return c.json(result); | |
| } catch (error) { | |
| console.error('[REFRESH_MOMENT API] Error:', error); | |
| const { statusCode, message } = handleGradioError(error); | |
| return c.json( | |
| { | |
| status: 'error', | |
| message, | |
| }, | |
| statusCode as 400 | 408 | 500, | |
| ); | |
| } | |
| }, | |
| ); | |