# How context-compat.ts Ensures Cross-Runtime Compatibility in the i-have-adhd Extension

> Discover how context-compat.ts guarantees cross-runtime compatibility for the i-have-adhd extension by normalizing APIs and providing runtime-agnostic utilities.

- Repository: [Ayoub Ghriss/i-have-adhd](https://github.com/ayghri/i-have-adhd)
- Tags: deep-dive
- Published: 2026-09-13

---

**The [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) module acts as an adapter layer that normalizes session-manager APIs between OMP and Pi runtimes, providing runtime-agnostic utilities to query context state without crashing on API differences.**

The ayghri/i-have-adhd repository contains a TypeScript extension that must operate consistently across different AI runtime environments. Because the OpenAI-compatible (OMP) and Pi runtimes expose session context through incompatible method signatures, the extension relies on [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) to abstract these differences and ensure reliable **cross-runtime compatibility**.

## The Runtime Compatibility Challenge

Different runtimes expose session history through distinct APIs. The OMP runtime provides session context via `buildSessionContext()`, which returns an object containing a `messages` array. In contrast, the Pi runtime uses `buildContextEntries()`, which returns the message array directly.

| Runtime | Method | Return Shape |
|---------|--------|--------------|
| **OMP** | `buildSessionContext()` | `{ messages: readonly ContextMessageMarker[] }` |
| **Pi** | `buildContextEntries()` | `readonly ContextMessageMarker[]` |

Without normalization, extension code would need runtime-specific branches, increasing complexity and fragility.

## The Adapter Implementation in context-compat.ts

The module exports two primary utilities that shield consuming code from runtime-specific implementations.

### Normalizing Session Manager APIs with contextMessages()

The `contextMessages()` function detects which API the supplied `sessionManager` implements. It checks for the existence of `buildSessionContext()` or `buildContextEntries()` and calls the appropriate method. The function always returns a plain array of `ContextMessageMarker` objects, or an empty array if the manager is missing, the call throws, or the result is not an array.

This defensive approach guarantees that calling code never crashes due to unexpected runtime API changes. If the session manager is `null`, not an object, or lacks expected methods, `contextMessages()` returns `[]`, allowing the caller to proceed with default behavior.

### Evaluating Context State with latestMarkerIsActive()

The `latestMarkerIsActive()` function walks the normalized messages array looking for custom markers (where `role === "custom"` and `type === "custom_message"`). It maintains a Boolean flag that updates when an `activeType` marker appears and clears when a `disabledType` marker appears, thus computing whether the most recent marker indicates the rule is active.

## Practical Usage in the Extension

Inside [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts), the extension consumes these utilities to determine whether ADHD-specific rules should activate:

```typescript
import { contextMessages, latestMarkerIsActive } from "./context-compat";

export function applyRule(env: RuntimeEnv) {
  // Normalise the context irrespective of OMP or Pi runtime
  const ctx = contextMessages(env.sessionManager);

  // Determine if the ADHD-friendly rule should be active
  const adhdActive = latestMarkerIsActive(ctx, "adhd_enabled", "adhd_disabled");

  if (adhdActive) {
    // …perform rule-specific logic
  }
}

```

## Validation Through Testing

The [`scripts/check_context_compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/scripts/check_context_compat.ts) test script validates this behavior by supplying mock managers implementing each API variant and asserting identical returned message arrays. This ensures that future changes to a runtime's session-manager contract are caught before breaking the extension.

```typescript
const ompMock = {
  buildSessionContext: () => ({ messages: [{ role: "custom", customType: "adhd_enabled" }] })
};

const piMock = {
  buildContextEntries: () => [{ role: "custom", customType: "adhd_enabled" }]
};

assert.deepStrictEqual(contextMessages(ompMock), contextMessages(piMock));
assert.strictEqual(
  latestMarkerIsActive(contextMessages(ompMock), "adhd_enabled", "adhd_disabled"),
  true
);

```

## Summary

- The [`context-compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/context-compat.ts) module provides an adapter pattern that normalizes incompatible session-manager APIs between OMP and Pi runtimes.
- The `contextMessages()` function returns a unified array format regardless of whether the runtime uses `buildSessionContext()` or `buildContextEntries()`.
- Defensive programming ensures the extension returns empty arrays rather than crashing when session managers are missing or malformed.
- `latestMarkerIsActive()` interprets custom message markers to determine rule activation state across all supported runtimes.
- Comprehensive testing in [`scripts/check_context_compat.ts`](https://github.com/ayghri/i-have-adhd/blob/main/scripts/check_context_compat.ts) prevents regression when runtime APIs evolve.

## Frequently Asked Questions

### What runtimes does context-compat.ts support?

The module supports the OMP (OpenAI-compatible) runtime and the Pi runtime. It detects which API is available by checking for the presence of `buildSessionContext()` for OMP or `buildContextEntries()` for Pi, allowing seamless operation across both environments.

### How does context-compat.ts handle missing or malformed session managers?

The `contextMessages()` function implements defensive checks: if the session manager is `null`, not an object, or lacks the expected methods, it returns an empty array `[]`. Similarly, if the method call throws or returns a non-array result, it returns `[]` rather than propagating the error.

### What is the difference between buildSessionContext and buildContextEntries?

`buildSessionContext()` is the OMP runtime method that returns an object with a `messages` property containing the context array. `buildContextEntries()` is the Pi runtime method that returns the context array directly without wrapping it in an object. The `contextMessages()` function normalizes both to return the unwrapped array.

### How does the extension determine if ADHD rules are active?

The extension uses `latestMarkerIsActive()` to scan the normalized message history for custom markers. It tracks the most recent occurrence of activation and deactivation markers (e.g., "adhd_enabled" vs "adhd_disabled"), returning `true` only if the latest relevant marker indicates the rule should be active.