Docs/AI & agentsv1.0.0-rc.1

AIPredictor

Overview

AIPredictor learns from the store's dispatch history to predict what will happen next. It offers three prediction types: next action prediction (pattern-matched from action sequences), state change prediction (based on what previous identical actions changed), and performance forecasting (statistical range from historical latencies). It also runs anomaly detection on every recorded transition, flagging performance outliers and unexpected state key changes.

All analysis is local and statistical — no external model or API key is required.

Key Concepts

  • Transition history — recordTransition adds a StateTransition to the internal log. The predictor learns as more transitions accumulate; predictions improve with more data.
  • Confidence — predictions carry a confidence value (0–1). Predictions below minConfidenceThreshold (default 0.6) are suppressed and null is returned.
  • Anomaly detection — each recorded transition is checked against statistical baselines. Performance deviations beyond anomalyThreshold standard deviations, and unexpected state key changes, produce Anomaly objects.
  • History size — historySize caps the transition log (default 100). Older transitions are discarded in FIFO order.

API Reference

PredictorConfig

interface PredictorConfig {
  enableStatePrediction?: boolean;          // default true
  enableAnomalyDetection?: boolean;         // default true
  enablePerformanceForecasting?: boolean;   // default true
  minConfidenceThreshold?: number;          // 0–1, default 0.6
  anomalyThreshold?: number;               // standard deviations, default 2.5
  historySize?: number;                    // default 100
}

StateTransition

interface StateTransition {
  fromState: any;
  toState: any;
  action: { type: string; payload?: any };
  timestamp: number;
  duration?: number;   // ms; required for performance anomaly detection
}

Prediction

interface Prediction {
  type: 'state' | 'action' | 'performance';
  confidence: number;        // 0–1
  prediction: any;           // varies by type
  reasoning: string;         // human-readable explanation
  timestamp: number;
}

For type: 'action', prediction is { type: string } (the predicted action type). For type: 'state', prediction is a partial state snapshot. For type: 'performance', prediction is { expectedDuration: number, range: [number, number], unit: 'ms' }.

Anomaly

interface Anomaly {
  severity: 'low' | 'medium' | 'high' | 'critical';
  type: string;           // 'PERFORMANCE_ANOMALY' or 'STATE_ANOMALY'
  description: string;
  detectedAt: number;
  affectedState?: string;
  expectedValue?: any;
  actualValue?: any;
  recommendation?: string;
}

AIPredictor

class AIPredictor {
  constructor(config?: PredictorConfig)

  recordTransition(transition: StateTransition): void
  predictNextAction(recentActions: any[]): Prediction | null
  predictStateChange(currentState: any, action: any): Prediction | null
  predictPerformance(actionType: string): Prediction | null
  getAnomalies(since?: number): Anomaly[]   // since: Unix timestamp ms
  clearAnomalies(): void
  getAccuracyStats(): {
    totalPredictions: number;
    actionPredictions: number;
    statePredictions: number;
    performancePredictions: number;
  }
}

function createPredictor(config?: PredictorConfig): AIPredictor

Basic Usage

import { AIPredictor } from '@tagna/udiot';

const predictor = new AIPredictor({
  minConfidenceThreshold: 0.7,
  historySize: 200,
});

// Simulate recording transitions (normally done by @AIPowered)
const transitions = [
  { fromState: { cart: [] }, toState: { cart: [{ id: 1 }] }, action: { type: 'ADD_ITEM' }, timestamp: Date.now(), duration: 5 },
  { fromState: { cart: [{ id: 1 }] }, toState: { cart: [{ id: 1 }], loading: true }, action: { type: 'CHECKOUT_START' }, timestamp: Date.now(), duration: 8 },
  { fromState: { cart: [{ id: 1 }], loading: true }, toState: { cart: [], loading: false }, action: { type: 'CHECKOUT_COMPLETE' }, timestamp: Date.now(), duration: 250 },
];

transitions.forEach(t => predictor.recordTransition(t));

// Predict next action given recent history
const recentActions = [{ type: 'ADD_ITEM' }, { type: 'CHECKOUT_START' }];
const nextAction = predictor.predictNextAction(recentActions);
if (nextAction) {
  console.log(`Predicted next: ${nextAction.prediction.type} (${(nextAction.confidence * 100).toFixed(0)}% confidence)`);
  // Predicted next: CHECKOUT_COMPLETE (100% confidence)
}

// Check for anomalies in the last second
const anomalies = predictor.getAnomalies(Date.now() - 1000);
anomalies.forEach(a => console.log(`[${a.severity}] ${a.description}`));

Common Patterns

Enabling predictions on a store via @AIPowered

import { ReactiveStore, AIPowered, Store, getPredictor, Mutation } from '@tagna/udiot';

@ReactiveStore({ name: 'CheckoutStore' })
@AIPowered({
  predictor: {
    enableStatePrediction: true,
    enableAnomalyDetection: true,
    minConfidenceThreshold: 0.65,
    historySize: 150,
  },
  onAnomaly: (anomaly) => {
    console.error(`[Anomaly] ${anomaly.severity}: ${anomaly.description}`);
  },
})
class CheckoutStore extends Store<CheckoutState> {
  constructor(state: CheckoutState) { super(state); }

  @Mutation()
  addItem(item: CartItem): void {
    this.dispatch({ type: 'ADD_ITEM', payload: item });
  }
}

const store = new CheckoutStore({ cart: [], loading: false });

// After dispatches, access the predictor
const predictor = getPredictor(store);
const stats = predictor?.getAccuracyStats();
console.log('Stats:', stats);

Proactive data prefetching based on predictions

import { getPredictor } from '@tagna/udiot';
import { Injectable } from '@tagna/udiot';

@Injectable()
class PrefetchService {
  constructor(private store: CheckoutStore, private api: ApiService) {}

  watchAndPrefetch(): void {
    const predictor = getPredictor(this.store);
    if (!predictor) return;

    this.store.subscribe(async () => {
      const history = this.store.getActionHistory?.() ?? [];
      const prediction = predictor.predictNextAction(history);

      if (prediction && prediction.type === 'action') {
        const { type } = prediction.prediction;

        if (type === 'CHECKOUT_START' && prediction.confidence > 0.8) {
          // Pre-load checkout data before user clicks checkout
          await this.api.prefetchShippingOptions();
        }
      }
    });
  }
}

Manual anomaly monitoring

import { AIPredictor } from '@tagna/udiot';

const predictor = new AIPredictor({ anomalyThreshold: 2.0 });

// Feed 20+ transitions to establish a baseline
// ... recordTransition calls ...

// Poll for recent anomalies
setInterval(() => {
  const recent = predictor.getAnomalies(Date.now() - 5000); // last 5 seconds
  const critical = recent.filter(a => a.severity === 'critical');

  if (critical.length > 0) {
    alertingService.page('Critical state anomalies detected', critical);
  }
}, 5000);

Integration Notes

  • @AIPowered calls predictor.recordTransition(transition) on every dispatch, providing duration from the measured dispatch time. Anomaly detection on performance requires at least 10 samples for a given action type before baselines are established.
  • predictNextAction requires at least 2 recent actions and at least one matching pattern in the transition history. With a fresh store (few dispatches), it will return null.
  • getAnomalies(since) filters by detectedAt timestamp. Without the since parameter, all recorded anomalies are returned regardless of age.

Pitfalls

  • Predictions are correlational, not causal. A high-confidence prediction means the pattern occurred frequently in history; it does not mean the predicted action is appropriate in the current context.
  • Performance anomaly detection requires the duration field in StateTransition. If you record transitions manually without duration, only state anomalies (unexpected key changes) are checked.
  • The anomalyThreshold default of 2.5 standard deviations means roughly 1.2% of transitions will trigger an anomaly in a normal distribution. In applications with high natural variance, raise the threshold to reduce false positives.
  • clearAnomalies() discards all historical anomaly records but does not reset performance baselines. New anomalies will still be detected against the same baselines going forward.
From the canonical UDIOT public documentation.Try it in the playground ↗