How the `context‑compat.ts` Layer Ensures Cross‑Platform Compatibility in i‑have‑ADHD
The context‑compat.ts module acts as an abstraction shim that normalizes platform‑specific session managers into a unified message format, enabling the i‑have‑ADHD runtime to work identically across Claude, Codex, Pi, OMP, and other adapters.
The i‑have‑ADHD open‑source project provides ADHD‑friendly response rules for AI assistants, but different platforms expose incompatible session APIs. The extensions/context‑compat.ts file solves this by isolating platform quirks behind a stable compatibility layer. This article breaks down exactly how context‑compat.ts achieves cross‑platform compatibility, with reference to the actual implementation in the ayghri/i‑have‑adhd repository.
Unified Message Shape via ContextMessageMarker
The foundation of compatibility is a minimal, platform‑agnostic type that captures only essential fields.
In extensions/context‑compat.ts, lines 1–5 define ContextMessageMarker containing type, role, and customType. Platform‑specific session managers may expose richer message objects, but the shim reduces every message to this common structure. This prevents type mismatches when the same code runs under different adapters.
Graceful Session‑Manager Detection
The exported contextMessages function accepts an unknown session manager and validates it before use.
Lines 18–20 verify that the input is an object. This protects the runtime from crashes when a platform omits the session manager or changes its API signature. Without this guard, an undefined or malformed manager would throw at runtime.
Dual‑API Support for Platform Variations
Different platforms expose context building through incompatible method names. The compatibility layer handles both conventions:
buildSessionContext— returns{ messages: … }(object wrapper)buildContextEntries— returns an array directly
Lines 24–33 check for both methods, invoking whichever is present. The result is normalized to an array of ContextMessageMarker regardless of which API was used. This dual‑path logic means the same code works whether the underlying platform follows Claude's conventions or Codex's.
Error‑Resilient Fallback Behavior
All platform detection and method invocation is wrapped in try … catch (lines 34–36). Any thrown error results in an empty array rather than a crash. This defensive design allows the rule engine to continue operating; markers can be re‑injected later if the session manager recovers or the platform environment stabilizes.
Active‑Marker Detection with latestMarkerIsActive
The latestMarkerIsActive helper (lines 41–60) scans normalized messages to determine if a custom marker is currently active. Because it operates exclusively on the standardized ContextMessageMarker fields, this logic stays identical across all platforms.
The function accepts an active customType and a disabled customType, returning true only if the most recent relevant marker indicates activation. This powers features like the "ADHD‑mode" toggle without platform‑specific branches.
Practical Usage Examples
Import and use the compatibility layer in any extension:
import { contextMessages, latestMarkerIsActive } from
"extensions/context-compat.ts";
// Assume `sessionMgr` is supplied by the current platform runtime.
const markers = contextMessages(sessionMgr);
// Determine if the "adhd_mode" marker is active, ignoring any "adhd_off" marker.
const adhdActive = latestMarkerIsActive(
markers,
"adhd_mode", // active customType
"adhd_off" // disabled customType
);
if (adhdActive) {
// Enable ADHD-friendly response rules
}
For generic marker detection, wrap the compatibility layer:
// Direct use of the compatibility layer in a generic utility
export function hasCustomMarker(
sessionMgr: unknown,
type: string
): boolean {
const msgs = contextMessages(sessionMgr);
return msgs.some(m => m.customType === type);
}
The context-compat.ts layer ensures these patterns execute identically whether the host is Claude, Codex, Pi, OMP, or any future adapter.
Key Files in the Compatibility System
| File | Purpose |
|---|---|
[extensions/context-compat.ts](https://github.com/ayghri/i-have-adhd/blob/main/extensions/context-compat.ts) |
Core compatibility shim that normalises session‑manager messages and provides marker‑checking helpers. |
[extensions/i-have-adhd.ts](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) |
Platform‑specific entry point that consumes normalized messages from context-compat.ts. |
[skills/i-have-adhd/SKILL.md](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) |
Defines the ADHD‑friendly response rules that rely on markers supplied by context-compat.ts. |
[hooks/hooks.json](https://github.com/ayghri/i-have-adhd/blob/main/hooks/hooks.json) |
Declares the hook that wires the compatibility layer into the runtime's execution flow. |
Summary
ContextMessageMarkerprovides a minimal, stable message format that all platforms can map to.- Unknown input handling with object validation prevents runtime crashes from missing or malformed session managers.
- Dual‑API detection (
buildSessionContextvs.buildContextEntries) accommodates platform variations without conditional compilation. - Try‑catch wrapping returns empty arrays on failure, preserving system stability.
latestMarkerIsActiveoperates on normalized data, ensuring consistent behavior across adapters.
Frequently Asked Questions
What platforms does context‑compat.ts support?
The layer supports Claude, Codex, Pi, OMP, and any platform exposing either buildSessionContext or buildContextEntries. The unknown‑input design allows graceful degradation on unsupported platforms.
Why does contextMessages return an empty array on error?
Empty arrays prevent the rule engine from crashing when session managers fail or platforms change APIs. The system can re‑inject markers later. This is implemented in lines 34–36 of context-compat.ts.
How does latestMarkerIsActive handle conflicting markers?
It scans messages chronologically and respects the most recent marker matching either the active or disabled customType. Only the latest state determines the return value, preventing stale activation.
Can I extend context‑compat.ts for new platforms?
Yes. Add detection logic in the dual‑API block (lines 24–33) to handle additional method signatures, ensuring the result normalizes to ContextMessageMarker[]. The rest of the system remains unchanged.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →