diff --git a/services/extraction-service/src/modules/tasks/seed.test.ts b/services/extraction-service/src/modules/tasks/seed.test.ts index 563e0626..15394ff8 100644 --- a/services/extraction-service/src/modules/tasks/seed.test.ts +++ b/services/extraction-service/src/modules/tasks/seed.test.ts @@ -15,11 +15,12 @@ const BUILTIN_TASK_IDS = [ 'memory-insight', 'reflection-enrichment', 'bug-report-extraction', + 'timer-parse', ]; describe('seed built-in tasks', () => { - it('defines exactly 5 built-in tasks', () => { - expect(BUILTIN_TASK_IDS).toHaveLength(5); + it('defines exactly 6 built-in tasks', () => { + expect(BUILTIN_TASK_IDS).toHaveLength(6); }); it('all task IDs are unique', () => { @@ -92,4 +93,17 @@ describe('seed built-in tasks', () => { }); expect(result.success).toBe(true); }); + + it('timer-parse task validates against schema', () => { + const result = ExtractionTaskSchema.safeParse({ + id: 'timer-parse', + name: 'Timer Natural Language Parse', + prompt: + 'Parse timer request and extract time, duration, urgency, label, recurrence, travel context.', + classes: ['time', 'duration', 'urgency_hint', 'label', 'recurrence', 'travel_context'], + builtIn: true, + productId: 'lysnrai', + }); + expect(result.success).toBe(true); + }); }); diff --git a/services/extraction-service/src/modules/tasks/seed.ts b/services/extraction-service/src/modules/tasks/seed.ts index 9749dd70..de024ee4 100644 --- a/services/extraction-service/src/modules/tasks/seed.ts +++ b/services/extraction-service/src/modules/tasks/seed.ts @@ -182,6 +182,74 @@ const BUILTIN_TASKS: Omit[] = [ builtIn: true, productId: DEFAULT_PRODUCT_ID, }, + { + id: 'timer-parse', + name: 'Timer Natural Language Parse', + description: + 'Extract structured timer parameters from natural language input for ChronoMind. ' + + 'Parses time references, durations, urgency hints, labels, recurrence, and travel context.', + prompt: + 'Parse the following natural language timer request and extract: absolute or relative time references, ' + + 'durations, urgency hints (critical/important/standard/gentle/passive), a concise label, ' + + 'recurrence patterns (daily/weekly/weekdays), and any travel-time context. ' + + 'Return each extraction with its class and the verbatim text that triggered it.', + classes: ['time', 'duration', 'urgency_hint', 'label', 'recurrence', 'travel_context'], + examples: [ + { + text: 'Set a critical alarm for my dentist next Tuesday at 2pm with 1 hour warning and 30 min travel time', + extractions: [ + { extraction_class: 'time', extraction_text: 'next Tuesday at 2pm' }, + { + extraction_class: 'urgency_hint', + extraction_text: 'critical', + attributes: { level: 'critical' }, + }, + { extraction_class: 'label', extraction_text: 'dentist' }, + { + extraction_class: 'duration', + extraction_text: '1 hour warning', + attributes: { minutes: '60', type: 'cascade_warning' }, + }, + { + extraction_class: 'travel_context', + extraction_text: '30 min travel time', + attributes: { minutes: '30' }, + }, + ], + }, + { + text: 'Remind me every weekday at 9am to take vitamins', + extractions: [ + { extraction_class: 'time', extraction_text: '9am' }, + { + extraction_class: 'recurrence', + extraction_text: 'every weekday', + attributes: { pattern: 'weekdays' }, + }, + { extraction_class: 'label', extraction_text: 'take vitamins' }, + ], + }, + { + text: '25 minute focus session for writing', + extractions: [ + { + extraction_class: 'duration', + extraction_text: '25 minute', + attributes: { minutes: '25', type: 'countdown' }, + }, + { extraction_class: 'label', extraction_text: 'writing' }, + { + extraction_class: 'urgency_hint', + extraction_text: 'focus session', + attributes: { level: 'standard', timer_type: 'pomodoro' }, + }, + ], + }, + ], + defaultModelId: 'gemini-2.5-flash', + builtIn: true, + productId: DEFAULT_PRODUCT_ID, + }, ]; /**