How context-compat.ts Enables OMP Compatibility: A Deep Dive into the Open-Code Marketplace Plugin Adapter
TLDR: context-compat.ts is a compatibility bridge that normalizes the Open-Code Marketplace Plugin (OMP) runtime's session-context APIs into a single, stable ContextMessageMarker shape, gracefully degrades on failure, and evaluates marker state — ensuring the i-have-adhd plugin works across all OMP versions.
The ayghri/i-have-adhd repository contains a plugin that injects ADHD-focused productivity rules and UI tweaks into an AI coding assistant. Its core challenge is that the Open-Code Marketplace Plugin (OMP) runtime exposes session context through two different, version-dependent APIs. The file extensions/context-compat.ts solves this by abstracting those differences. In this article, I explain exactly how this adapter works, the functions it exports, and where it plugs into the larger architecture — based directly on the source code in the repository.
What context-compat.ts Does: The OMP Compatibility Bridge
The OMP runtime provides a sessionManager object to plugins at initialization time. That object may implement one of two methods depending on the OMP release:
buildSessionContext()— the newer API signature.buildContextEntries()— the older, legacy API.
If the plugin code tried to call one method directly, it would break on the other version. context-compat.ts eliminates this fragility by defining the CompatibleSessionManager type, which captures both signatures:
type CompatibleSessionManager = {
buildSessionContext?: () => ContextMessageMarker[];
buildContextEntries?: () => ContextMessageMarker[];
// ... additional optional fields
};
Because both methods return the same underlying ContextMessageMarker shape, the type acts as a structural union. The rest of the plugin can then treat every supported OMP version identically, regardless of which API the runtime actually provides.
How contextMessages() Normalizes OMP Context Data
The exported contextMessages() function performs the actual dispatch. It checks which method exists on the session manager, invokes it, and returns a normalized ContextMessageMarker[] array:
export function contextMessages(sessionManager: unknown): ContextMessageMarker[] {
if (!sessionManager) return [];
const sm = sessionManager as CompatibleSessionManager;
try {
if (typeof sm.buildSessionContext === "function") {
return sm.buildSessionContext() ?? [];
}
if (typeof sm.buildContextEntries === "function") {
return sm.buildContextEntries() ?? [];
}
} catch {
// OMP API changed or transient failure — fail open, not closed.
}
return [];
}
Notice three defensive details in this implementation:
- Null safety — If
sessionManagerisundefined, the function short-circuits to an empty array. - Double validation — Each method is checked with
typeofbefore invocation, so a missing method never throws aTypeError. - Exception swallowing — Any runtime error inside the method call is caught, and the function returns
[]instead of crashing the plugin startup.
This fails-open behavior is essential for OMP compatibility: the plugin must start safely even when the runtime's API is temporarily broken or mid-migration.
Graceful Degradation and the OMP Fallback Policy
According to the i-have-adhd source, OMP enforces a policy where its custom rules are applied only as a fallback when an alternative provider (called "Pi") is unavailable. context-compat.ts supports this policy through its fail-open default.
When the plugin initializes, it never knows ahead of time whether the OMP session manager will be present, functional, or using the expected API. If contextMessages() returned null or threw, the plugin would crash — and no rules would load, breaking the fallback entirely. By silently returning an empty array, the adapter enables the plugin to:
- Start up cleanly every time.
- Wait for the session manager to become available later.
- Re-inject OMP rules when a later call succeeds.
This separation of "retrieve what you can, fail without side effects" is critical for long-running editor sessions where OMP updates may hot-reload the API mid-session.
Marker State Evaluation with latestMarkerIsActive()
A marker in the OMP context is a typed message object: { type: string, ... }. OMP uses custom types such as "omp_active" and "omp_disabled" to signal whether the OMP-specific ruleset should be applied.
The helper latestMarkerIsActive() walks through the normalized markers in order and determines if the most recent marker of a given active type activeType is still in effect — accounting for a later disabling marker:
export function latestMarkerIsActive(
markers: ContextMessageMarker[],
activeType: string,
disabledType: string
): boolean {
let active = false;
for (const m of markers) {
if (m.type === activeType) active = true;
else if (m.type === disabledType) active = false;
}
return active;
}
The function is order-aware: it scans the chronological list, so a later "omp_disabled" overrides an earlier "omp_active". This gives the plugin a single, deterministic Boolean that drives feature toggles without the caller needing to understand OMP's internal message ordering.
Integration Points: Where the Adapter Plugs Into the Plugin
The OMP Extension Entry Point
The main integration lives in extensions/i-have-adhd.ts, which is invoked by OMP at plugin load. It calls contextMessages(sessionManager) and then latestMarkerIsActive() to decide whether to apply OMP-specific rules:
import { contextMessages, latestMarkerIsActive } from "./extensions/context-compat";
// The OMP runtime passes its session manager to the plugin entry point.
function onPluginInit(sessionManager: unknown) {
// Retrieve a normalized list of context markers.
const markers = contextMessages(sessionManager);
// Determine whether the "omp_active" marker is still in effect.
const isOmpActive = latestMarkerIsActive(
markers,
"omp_active", // active marker type
"omp_disabled" // disabling marker type
);
if (isOmpActive) {
// Enable OMP-specific behavior (e.g., custom rules, UI tweaks)
enableOmpFeatures();
} else {
// Fallback to default behavior or Pi compatibility path
disableOmpFeatures();
}
}
This is the only place in the plugin that touches OMP internals. Everything downstream operates on the simple Boolean isOmpActive.
The Verification Script
The repository also contains scripts/check_context_compat.ts, a test script that validates OMP compatibility. It checks two essential properties:
- Message presence — that
contextMessages()returns the expected markers for a given mock session manager. - Marker ordering — that chronological order is preserved, ensuring
latestMarkerIsActive()behaves deterministically.
This test is crucial because OMP regularly evolves its API. If a future OMP release changes the session manager shape, the test fails immediately, alerting the maintainers that the adapter needs an update — rather than silently breaking plugin behavior in production.
Key Files and Their Roles
| File | Purpose |
|---|---|
extensions/context-compat.ts |
Normalizes OMP session-context messages and evaluates marker state. |
extensions/i-have-adhd.ts |
OMP entry point that uses the helpers above to apply runtime-specific rules. |
scripts/check_context_compat.ts |
Test script that verifies OMP compatibility (message presence, ordering). |
Why This Design Matters for Plugin Maintainability
By encapsulating the differences between OMP's session-manager APIs, context-compat.ts delivers three concrete benefits to the i‑have‑adhd plugin:
- Version independence — The rest of the codebase is completely decoupled from OMP's API changes.
- Fail-safe startup — The plugin can never crash due to a missing or broken session manager.
- Deterministic behavior — Marker logic is centralized, auditable, and unit-tested.
Any new OMP feature that introduces additional context types only requires extending the adapter functions — never the consumer code in i-have-adhd.ts.
Summary
context-compat.tsdefines theCompatibleSessionManagertype that unifies OMP's two APIs:buildSessionContext()andbuildContextEntries().- The
contextMessages()function normalizes output toContextMessageMarker[]and returns an empty array on any error, satisfying OMP's fallback policy. latestMarkerIsActive()evaluates marker sequencing deterministically, returning a Boolean used by OMP feature toggles.- The adapter is integrated through
extensions/i-have-adhd.tsand guarded by thescripts/check_context_compat.tstest script. - This design ensures the plugin remains fully compatible across OMP releases with zero change to its core logic.
Frequently Asked Questions
What problem does context-compat.ts solve?
context-compat.ts solves the problem of OMP runtime API divergence. The OMP may provide a session manager implementing either buildSessionContext() or buildContextEntries(), and this file normalizes both into a single ContextMessageMarker[] array that the rest of the plugin consumes without knowing which API version is in use.
How does context-compat.ts handle missing or broken session managers?
It fails open. If the session manager is missing, the contextMessages() function returns an empty array. If the manager exists but throws an error during mark the call, the error is swallowed and the function still returns []. This prevents plugin startup crashes and allows OMP's fallback-only policy to work safely.
What lesson does latestMarkerActive() teach about OMP marker evaluation?
It scans markers chronologically, so the last marker always wins: if a "omp_disabled" marker appears after an "omp_active" marker, the function returns false. Order preservation is checked by the test script in check_context_compat.ts.
Where in the repository is the OMP compatibility adapter used?
The adapter is used in extensions/i-have-adhd.ts, the OMP entry point. That file calls contextMessages(sessionManager) at full initialization and latestMarkerIsActive() to decide whether to enable OMP-specific features. The adapter and its integration are governed by the test in scripts/check_context_compat.ts.
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 →