feat(questions): make brand questions the primary monitoring & template axis
Deployment Config CI / Deployment Config (push) Successful in 29s
Frontend CI / Frontend (push) Successful in 4m4s
Backend CI / Backend (push) Failing after 7m12s

- add /questions/combination-fill endpoint with AI-driven, IP-region-aware matrix fill
- extract ip2region resolver from ops/app into shared/ipregion for cross-service use
- thread question_id filter through dashboard composite, citation summary, and collect-now
- switch template wizard from keyword inputs to brand-question selection (primary + supplemental)
- pass brand_question and supplemental_questions through assist/title/outline prompts
- add AiWaitingModal + 45s client timeout and request_timeout error mapping for long AI flows

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 15:59:39 +08:00
parent 37b0b32327
commit 1eae6fb6d4
36 changed files with 2119 additions and 412 deletions
+4 -1
View File
@@ -61,8 +61,11 @@ function normalizeError(error: unknown): ApiClientError {
if (axios.isAxiosError(error)) {
const payload = error.response?.data as Partial<ApiErrorEnvelope> | undefined
const isTimeout =
!error.response && (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT')
const fallbackMessage = isTimeout ? 'request_timeout' : (error.message ?? 'network_error')
return new ApiClientError({
message: payload?.message ?? error.message ?? 'network_error',
message: payload?.message ?? fallbackMessage,
code: payload?.code ?? 50000,
status: error.response?.status,
detail: payload?.detail,
+24
View File
@@ -472,6 +472,8 @@ export interface TemplateAnalyzeTaskRequest {
brand_id?: number | null
brand_name?: string
website?: string | null
brand_question?: string
supplemental_questions?: string[]
input_params?: Record<string, JsonValue>
existing_keywords?: string[]
existing_competitors?: TemplateAssistCompetitor[]
@@ -489,6 +491,8 @@ export interface TemplateTitleTaskRequest {
brand_name?: string
website?: string | null
brand_summary?: string | null
brand_question?: string
supplemental_questions?: string[]
input_params?: Record<string, JsonValue>
keywords?: string[]
competitors?: TemplateAssistCompetitor[]
@@ -506,6 +510,8 @@ export interface TemplateOutlineTaskRequest {
website?: string | null
brand_summary?: string | null
title: string
brand_question?: string
supplemental_questions?: string[]
input_params?: Record<string, JsonValue>
keywords?: string[]
competitors?: TemplateAssistCompetitor[]
@@ -1278,6 +1284,24 @@ export interface QuestionCombinationRequest {
max_items?: number
}
export interface QuestionCombinationFillRequest {
region?: string[]
prefix?: string[]
core?: string[]
industry?: string[]
suffix?: string[]
}
export interface QuestionCombinationFillResult {
region: string[]
prefix: string[]
core: string[]
industry: string[]
suffix: string[]
ai_points_charged?: number
cache_hit?: boolean
}
export interface QuestionDistillRequest {
seed_topic: string
}