mirror of
https://github.com/whekin/household-bot.git
synced 2026-04-01 07:14:02 +00:00
feat(bot): unified topic processor replacing router+interpreter stack
Replace 3-layer architecture (gpt-5-nano router + gpt-4o-mini interpreter) with single unified topic processor (gpt-4o-mini) for simplified message handling. New components: - HouseholdContextCache: TTL-based caching (5 min) for household config data - TopicProcessor: Unified classification + parsing with structured JSON output Key changes: - Renamed ASSISTANT_ROUTER_MODEL → TOPIC_PROCESSOR_MODEL - Added TOPIC_PROCESSOR_TIMEOUT_MS (default 10s) - Refactored save() → saveWithInterpretation() for pre-parsed interpretations - Removed deprecated createOpenAiTopicMessageRouter and ~300 lines legacy code - Fixed typing indicator to only start when needed (purchase routes) - Fixed amount formatting: convert minor units to major for rawText Routes: silent, chat_reply, purchase, purchase_clarification, payment, payment_clarification, topic_helper, dismiss_workflow All 212 bot tests pass. Typecheck, lint, format, build clean.
This commit is contained in:
@@ -512,6 +512,9 @@ describe('registerPurchaseTopicIngestion', () => {
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -605,6 +608,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -670,6 +676,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -757,6 +766,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -866,6 +878,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -942,6 +957,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1037,6 +1055,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1125,6 +1146,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1182,6 +1206,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1224,6 +1251,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1271,6 +1301,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1325,6 +1358,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1391,6 +1427,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1457,6 +1496,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1516,6 +1558,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1581,6 +1626,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1655,6 +1703,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1712,6 +1763,9 @@ Confirm or cancel below.`
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1814,6 +1868,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1865,6 +1922,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1942,6 +2002,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -1992,6 +2055,9 @@ Confirm or cancel below.`,
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -2051,17 +2117,9 @@ Confirm or cancel below.`,
|
||||
repository,
|
||||
{
|
||||
historyRepository,
|
||||
router: async (input) => {
|
||||
topicProcessor: async (input) => {
|
||||
if (input.messageText.includes('картошки')) {
|
||||
return {
|
||||
route: 'silent',
|
||||
replyText: null,
|
||||
helperKind: null,
|
||||
shouldStartTyping: false,
|
||||
shouldClearWorkflow: false,
|
||||
confidence: 90,
|
||||
reason: 'planning'
|
||||
}
|
||||
return { route: 'silent', reason: 'planning' }
|
||||
}
|
||||
|
||||
recentTurnTexts = input.recentThreadMessages?.map((turn) => turn.text) ?? []
|
||||
@@ -2069,10 +2127,6 @@ Confirm or cancel below.`,
|
||||
return {
|
||||
route: 'chat_reply',
|
||||
replyText: 'No leaked context here.',
|
||||
helperKind: 'assistant',
|
||||
shouldStartTyping: false,
|
||||
shouldClearWorkflow: false,
|
||||
confidence: 91,
|
||||
reason: 'thread_scoped'
|
||||
}
|
||||
}
|
||||
@@ -2136,6 +2190,9 @@ Confirm or cancel below.`,
|
||||
participants: participants()
|
||||
}
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -2195,6 +2252,9 @@ Participants:
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -2258,6 +2318,9 @@ Participants:
|
||||
participants: participants()
|
||||
}
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
@@ -2311,6 +2374,9 @@ Participants:
|
||||
async confirm() {
|
||||
throw new Error('not used')
|
||||
},
|
||||
async saveWithInterpretation() {
|
||||
throw new Error('not implemented')
|
||||
},
|
||||
async cancel() {
|
||||
return {
|
||||
status: 'cancelled' as const,
|
||||
|
||||
Reference in New Issue
Block a user