Skip to content

recurrenceAI — Recurrence Rules & Schedule Translation

recurrenceAI() provides multi-directional translation between natural language repeating schedule descriptions ("Every 2nd Tuesday of the month at 3pm") and RFC 5545 RRULE strings, generating paged Tempo instance batches on demand.

Basic Usage

typescript
import { recurrenceAI, initAI } from '@magmacomputing/tempo-plugin-ai';

// 1. Initialize provider configuration
await initAI({
  providers: [{ id: 'groq', key: process.env.GROQ_API_KEY }]
});

// 2. Natural Language Input (human-in -> RRule & Tempo batches out)
const result = await recurrenceAI("Every 2 weeks on Friday at 9am", {
  locale: 'fr-FR',  // Output localized human summary
  count: 5          // Default batch size
});

console.log(result.rrule);     // "FREQ=WEEKLY;INTERVAL=2;BYDAY=FR;BYHOUR=9"
console.log(result.summary);   // "Chaque 2 semaines le vendredi à 09:00"
console.log(result.isFinite);  // false (recurs indefinitely)
console.log(result.size);      // Infinity

Stateful Paged Batching (.take(n))

recurrenceAI maintains an internal date cursor. Calling .take(n) repeatedly returns consecutive batches of Tempo instances:

typescript
// Fetch initial batch of 5 items
const batch1 = result.take(5);
console.log(batch1.length); // 5

// Fetch NEXT batch of 5 items starting right where batch 1 left off
const batch2 = result.take(5);
console.log(batch2.length); // 5

When a finite schedule (e.g. COUNT=10) completes, .take(n) returns an empty array [] to signal exhaustion:

typescript
const finiteResult = await recurrenceAI("FREQ=MONTHLY;BYDAY=1MO;COUNT=2");

const b1 = finiteResult.take(2); // [ Tempo(Month 1), Tempo(Month 2) ]
const b2 = finiteResult.take(2); // [] (Exhausted)

Native RRULE Parsing (Zero Network Overhead)

Passing a raw RFC 5545 RRULE string directly to recurrenceAI bypasses network LLM calls entirely (provider: 'rrule-parser'), functioning as an instant native parser:

typescript
const native = await recurrenceAI("FREQ=MONTHLY;BYDAY=1MO;COUNT=12");

console.log(native.provider); // "rrule-parser" (Instant native resolution)
console.log(native.isFinite); // true
console.log(native.size);     // 12

Lazy Iteration (for...of)

TempoRecurrenceResult implements [Symbol.iterator], allowing lazy iteration over occurrences up to the batch limit (count: 5 by default).

When iterating over open-ended schedules (isFinite === false), build a break termination clause into the loop:

typescript
const schedule = await recurrenceAI("Every Friday");

for (const occurrence of schedule) {
  // Always include a termination condition for open-ended schedules
  if (occurrence.yy > 2028) break;

  console.log(occurrence.format('{yyyy}-{mm}-{dd}'));
}

Result Interface

typescript
export interface TempoRecurrenceResult {
  /** Standard RFC 5545 RRULE string (e.g. 'FREQ=WEEKLY;BYDAY=TU') */
  rrule: string;
  
  /** Localized human-friendly schedule summary */
  summary: string;
  
  /** Reasoning / explanation of how the recurrence pattern was parsed */
  reasoning?: string;
  
  /** True if schedule has an explicit end date or count limit; false if infinite */
  isFinite: boolean;
  
  /** Total count of occurrences if finite, or Infinity (Number.POSITIVE_INFINITY) */
  size: number;
  
  /** Advances cursor and returns the next batch of N Tempo instances */
  take(count?: number): Tempo[];
  
  /** Lazy generator yielding Tempo instances */
  [Symbol.iterator](): Generator<Tempo, void, unknown>;
  
  /** Confidence score (0.0 to 1.0) */
  confidence: number;
  
  /** Provider ID responsible for processing or 'rrule-parser' */
  provider: string;
}

Released under the MIT License.