Files
Evandro Fonseca Junior d1d04001d0
Release / release (push) Failing after 5s
Validate / validate (push) Failing after 5m21s
chore: fork @llblab/[email protected] as @evandrodevbr/oh-my-pi-telegram
Fork of upstream llblab/[email protected].0 (SHA afe09c5) repackaged as a
drop-in extension for can1357/oh-my-pi (omp >= 16.5.2).

Changes vs upstream:
- Rename package: @llblab/pi-telegram -> @evandrodevbr/oh-my-pi-telegram
- Bump version: 0.22.0 -> 0.22.0-evandro.1
- Update repository/homepage/bugs URLs to evandrodevbr
- Add omp field in package.json (displayName + compatibleWith)
- README: prepend 'Oh My Pi (omp) Compatibility' section with install
  commands, verified-components table, upstream lineage, and rationale
- CHANGELOG: add '0.22.0-evandro.1' entry under Unreleased
- docs/: rename @llblab/pi-telegram imports to @evandrodevbr/oh-my-pi-telegram
- tests/public-api.test.ts: rename package import paths

Gates re-run on the fork:
- npm run typecheck  -> tsc --noEmit (success)
- npm test           -> 1229 pass / 0 fail / 1 platform-only skip
- npm run audit      -> found 0 vulnerabilities
- npm run pack:check -> evandrodevbr-oh-my-pi-telegram-0.22.0-evandro.1.tgz

Verified:
- omp install --link ./pi-telegram -> Linked OK
- omp plugin list -> @evandrodevbr/[email protected].0-evandro.1

Upstream lineage: badlogic/pi-telegram -> llblab/pi-telegram (0.22.0) -> evandrodevbr/oh-my-pi-telegram (this fork)
2026-07-15 14:18:16 -03:00

196 lines
5.3 KiB
TypeScript

/**
* pi SDK adapter boundary
* Zones: pi agent sdk boundary, shared adapters
* Owns direct pi SDK imports and exposes narrow bridge-facing helpers/types for the extension composition layer
*/
import type { AssistantMessageEvent } from "@earendil-works/pi-ai";
import {
type AgentEndEvent,
type AgentSettledEvent,
type AgentStartEvent,
type BeforeAgentStartEvent,
type ExtensionAPI,
type ExtensionCommandContext,
type ExtensionContext,
type InputEvent,
type SessionBeforeCompactEvent,
type SessionCompactEvent,
type SessionShutdownEvent,
type SessionStartEvent,
type SlashCommandInfo,
SettingsManager,
} from "@earendil-works/pi-coding-agent";
export type {
AgentEndEvent,
AgentSettledEvent,
AgentStartEvent,
AssistantMessageEvent,
BeforeAgentStartEvent,
ExtensionAPI,
ExtensionCommandContext,
ExtensionContext,
InputEvent,
SessionBeforeCompactEvent,
SessionCompactEvent,
SessionShutdownEvent,
SessionStartEvent,
SlashCommandInfo,
};
export interface ToolExecutionStartEvent {
type: "tool_execution_start";
toolCallId: string;
toolName: string;
args: unknown;
}
export interface ToolExecutionUpdateEvent {
type: "tool_execution_update";
toolCallId: string;
toolName: string;
args: unknown;
partialResult: unknown;
}
export interface ToolExecutionEndEvent {
type: "tool_execution_end";
toolCallId: string;
toolName: string;
result: unknown;
isError: boolean;
}
export interface PiSettingsManager {
reload: () => Promise<void>;
flush: () => Promise<void>;
getEnabledModels: () => string[] | undefined;
setEnabledModels: (patterns: string[] | undefined) => void;
}
export type PiSlashCommandInfo = SlashCommandInfo;
export type PiRunMode = "tui" | "rpc" | "json" | "print";
function isPiRunMode(value: unknown): value is PiRunMode {
return (
value === "tui" || value === "rpc" || value === "json" || value === "print"
);
}
export function getExtensionContextMode(ctx: unknown): PiRunMode | undefined {
const mode =
typeof ctx === "object" && ctx !== null
? (ctx as { mode?: unknown }).mode
: undefined;
return isPiRunMode(mode) ? mode : undefined;
}
export function isExtensionContextPassiveRunMode(ctx: unknown): boolean {
const mode = getExtensionContextMode(ctx);
return mode === "print" || mode === "json";
}
export function canStartPollingInExtensionContext(ctx: unknown): boolean {
return !isExtensionContextPassiveRunMode(ctx);
}
export function formatPollingStartBlockedByRunMode(ctx: unknown): string {
const mode = getExtensionContextMode(ctx);
return mode
? `Telegram polling is unavailable in Pi ${mode} mode. Use /telegram-connect from a long-lived Pi session.`
: "Telegram polling is unavailable in this Pi run mode.";
}
export function getSessionCompactionReason(
event: unknown,
): "manual" | "threshold" | "overflow" | "unknown" {
const reason =
event && typeof event === "object" && "reason" in event
? (event as { reason?: unknown }).reason
: undefined;
return reason === "manual" || reason === "threshold" || reason === "overflow"
? reason
: "unknown";
}
export type PiSendUserMessageOptions = NonNullable<
Parameters<ExtensionAPI["sendUserMessage"]>[1]
>;
export interface PiExtensionApiRuntimePorts {
sendUserMessage: ExtensionAPI["sendUserMessage"];
exec: ExtensionAPI["exec"];
getCommands: ExtensionAPI["getCommands"];
getThinkingLevel: ExtensionAPI["getThinkingLevel"];
setThinkingLevel: ExtensionAPI["setThinkingLevel"];
setModel: ExtensionAPI["setModel"];
}
export function createExtensionApiRuntimePorts(
api: Pick<
ExtensionAPI,
| "sendUserMessage"
| "exec"
| "getCommands"
| "getThinkingLevel"
| "setThinkingLevel"
| "setModel"
>,
): PiExtensionApiRuntimePorts {
return {
sendUserMessage: (content, options) =>
api.sendUserMessage(content, options),
exec: (command, args, options) => api.exec(command, args, options),
getCommands: () => api.getCommands(),
getThinkingLevel: () => api.getThinkingLevel(),
setThinkingLevel: (level) => api.setThinkingLevel(level),
setModel: (model) => api.setModel(model),
};
}
export function createSettingsManager(cwd: string): PiSettingsManager {
return SettingsManager.create(cwd);
}
export function createScopedModelPatternPersister(deps: {
createSettingsManager: (cwd: string) => PiSettingsManager;
clearCachedModelMenuInputs: () => void;
}): (patterns: string[], ctx: ExtensionContext) => Promise<void> {
return async (patterns, ctx) => {
const settingsManager = deps.createSettingsManager(ctx.cwd);
settingsManager.setEnabledModels(
patterns.length > 0 ? patterns : undefined,
);
await settingsManager.flush();
deps.clearCachedModelMenuInputs();
};
}
export function getExtensionContextModel(
ctx: ExtensionContext,
): ExtensionContext["model"] {
return ctx.model;
}
export function getExtensionContextCwd(ctx: ExtensionContext): string {
return ctx.cwd;
}
export function isExtensionContextIdle(ctx: ExtensionContext): boolean {
return ctx.isIdle();
}
export function hasExtensionContextPendingMessages(
ctx: ExtensionContext,
): boolean {
return ctx.hasPendingMessages();
}
export function compactExtensionContext(
ctx: ExtensionContext,
callbacks: Parameters<ExtensionContext["compact"]>[0],
): ReturnType<ExtensionContext["compact"]> {
return ctx.compact(callbacks);
}