Summary
pi-messenger fails to load as an extension under Oh My Pi (omp, a pi-compatible coding agent). The extension factory throws during module evaluation, so the pi_messenger tool is never registered and Crew is unavailable. It works fine under upstream pi.
Error
Failed to load extension: /…/node_modules/pi-messenger/index.ts
error: Type.Unsafe is not a function.
(In 'Type.Unsafe({ type: "string", enum: [...values], … })', 'Type.Unsafe' is undefined)
Root cause
index.ts defines a StringEnum helper that calls Type.Unsafe(...) unconditionally:
import { Type, type TUnsafe } from "typebox";
function StringEnum<T extends readonly string[]>(values: T, options?): TUnsafe<T[number]> {
return Type.Unsafe<T[number]>({ type: "string", enum: [...values], … });
}
Hosts rewrite the typebox / @sinclair/typebox import onto their own bundled copy. omp maps it onto a minimal, ArkType-backed typebox compatibility shim (so tool validation works in eval-restricted runtimes — see @oh-my-pi/pi-coding-agent v0.69.0). That shim implements the common Type.* builders (String, Number, Boolean, Array, Object, Optional, Union, Literal, Enum, …) but not Type.Unsafe. The call to Type.Unsafe therefore throws at load time, the factory aborts, and the whole extension (tool + command + overlay) fails to register.
StringEnum is the only place Type.Unsafe is used; every other Type.* member the extension uses is present in the shim.
Impact
- Under
omp: pi_messenger tool and Crew are entirely unavailable; only a "Failed to load extension" error in the logs.
- Affects any host that provides a partial/minimal typebox surface without
Type.Unsafe.
Repro
- Install
pi-messenger as an extension in @oh-my-pi/pi-coding-agent.
- Start a session.
- The
pi_messenger tool is absent; logs show Type.Unsafe is not a function.
Proposed fix
Make StringEnum portable: use Type.Unsafe when the runtime provides it (real typebox — behavior unchanged), and otherwise fall back to an equivalent union of literals (Type.Union(values.map((v) => Type.Literal(v)), options)), which both real typebox and the shim support and which yields an equivalent string-enum parameter schema.
PR to follow.
Summary
pi-messengerfails to load as an extension under Oh My Pi (omp, api-compatible coding agent). The extension factory throws during module evaluation, so thepi_messengertool is never registered and Crew is unavailable. It works fine under upstreampi.Error
Root cause
index.tsdefines aStringEnumhelper that callsType.Unsafe(...)unconditionally:Hosts rewrite the
typebox/@sinclair/typeboximport onto their own bundled copy.ompmaps it onto a minimal, ArkType-backed typebox compatibility shim (so tool validation works in eval-restricted runtimes — see@oh-my-pi/pi-coding-agentv0.69.0). That shim implements the commonType.*builders (String,Number,Boolean,Array,Object,Optional,Union,Literal,Enum, …) but notType.Unsafe. The call toType.Unsafetherefore throws at load time, the factory aborts, and the whole extension (tool + command + overlay) fails to register.StringEnumis the only placeType.Unsafeis used; every otherType.*member the extension uses is present in the shim.Impact
omp:pi_messengertool and Crew are entirely unavailable; only a "Failed to load extension" error in the logs.Type.Unsafe.Repro
pi-messengeras an extension in@oh-my-pi/pi-coding-agent.pi_messengertool is absent; logs showType.Unsafe is not a function.Proposed fix
Make
StringEnumportable: useType.Unsafewhen the runtime provides it (real typebox — behavior unchanged), and otherwise fall back to an equivalent union of literals (Type.Union(values.map((v) => Type.Literal(v)), options)), which both real typebox and the shim support and which yields an equivalent string-enum parameter schema.PR to follow.