Files
oh-my-pi-telegram/docs/superpowers/plans/2026-07-15-telegram-omp-status-indicator.md
T
evandro 97f2b723bb
Validate / validate (push) Failing after 4m58s
wip: snapshot das alterações não commitadas (2026-10-20)
Origem: D:/Documents/Github/oh-my-pi-telegram
Arquivos omitidos (segredos, bancos de dados, logs, >50 MB): 0
2026-10-20 00:49:42 -03:00

14 KiB

Telegram OMP 17 Status Indicator Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Show the Telegram bridge's connection state in OMP 17's upper status bar immediately after the cost segment, while documenting the correct OMP plugin workflow.

Architecture: OMP gains one narrow public extension UI method for a sanitized status segment fixed after cost. The Telegram plugin calls that method from its existing status update path, keeping connection-state derivation local and network-free. A checkout of OMP is modified and built; the Bun-global package is never patched in place.

Tech Stack: TypeScript, Bun, OMP 17 status-line component, OMP extension API, Node test runner, Telegram bridge extension.


File structure

OMP source checkout: D:/Documents/Github/oh-my-pi

  • packages/coding-agent/src/extensibility/extensions/types.ts — public extension UI type.
  • packages/coding-agent/src/modes/controllers/extension-ui-controller.ts — forwards the public API to the status-line component.
  • packages/coding-agent/src/modes/components/status-line/component.ts — owns segment storage, sanitization, insertion after cost, and width eviction.
  • packages/coding-agent/src/modes/components/status-line/component.test.ts — verifies public-status segment rendering.

Telegram plugin: D:/Documents/Github/oh-my-pi-telegram

  • lib/pi.ts — narrow structural adapter for OMP's optional public top-status API.
  • lib/status.ts — derives the two Telegram status labels and publishes through injected ports.
  • index.ts — wires the OMP status-segment port into the existing status runtime.
  • tests/status.test.ts — verifies connection-state labels and publication calls.
  • tests/public-api.test.ts — raises the declared OMP compatibility floor to 17.0.0.
  • package.json — raises omp.compatibleWith["@oh-my-pi/pi-coding-agent"] to >=17.0.0.
  • README.md — correct OMP plugin install/link/setup instructions.

Task 1: Create a durable OMP 17 source checkout

Files:

  • Create: D:/Documents/Github/oh-my-pi

  • Step 1: Clone and install the OMP 17 source tree

git clone https://github.com/can1357/oh-my-pi.git D:/Documents/Github/oh-my-pi
cd D:/Documents/Github/oh-my-pi
git switch --create feature/telegram-status-segment
bun install
  • Step 2: Confirm the checkout matches the installed OMP major version

Run:

bun --cwd packages/coding-agent -e "console.log(require('./package.json').version)"

Expected: a 17.x.x version. If the upstream checkout is newer, switch to the v17.0.0 tag before editing so the source API matches the installed OMP.

  • Step 3: Commit no code in this task

The checkout is preparation only. The first code commit is made after the API and its test pass together.

Task 2: Add OMP's public after-cost extension segment API

Files:

  • Modify: D:/Documents/Github/oh-my-pi/packages/coding-agent/src/extensibility/extensions/types.ts

  • Modify: D:/Documents/Github/oh-my-pi/packages/coding-agent/src/modes/controllers/extension-ui-controller.ts

  • Modify: D:/Documents/Github/oh-my-pi/packages/coding-agent/src/modes/components/status-line/component.ts

  • Test: D:/Documents/Github/oh-my-pi/packages/coding-agent/src/modes/components/status-line/component.test.ts

  • Step 1: Write failing status-line component tests

Add tests that construct StatusLineComponent, register two extension segments, and inspect getTopBorder(200).content after stripping SGR codes. The assertions must prove:

expect(stripped.indexOf("$2.50")).toBeLessThan(stripped.indexOf("Telegram: conectado"));
expect(stripped.indexOf("Telegram: conectado")).toBeLessThan(stripped.indexOf("session-name"));
expect(stripped).not.toContain("\\x1b[31m");

Set the test session's usage statistics to cost: 2.5 and its session name to session-name. Register a segment with "Telegram: conectado"; register another containing "\x1b[31munsafe\x1b[0m"; then clear the first segment and assert that only the cleared value disappears.

  • Step 2: Run the component test and observe the missing API failure

Run:

bun test packages/coding-agent/src/modes/components/status-line/component.test.ts

Expected: FAIL because StatusLineComponent has no extension-status-segment method.

  • Step 3: Define the public UI type

In ExtensionUIContext, add the narrow method and option type:

export type ExtensionStatusSegmentPlacement = "after-cost";

export interface ExtensionStatusSegmentOptions {
  placement: ExtensionStatusSegmentPlacement;
}

setStatusSegment(
  key: string,
  text: string | undefined,
  options: ExtensionStatusSegmentOptions,
): void;

Only "after-cost" is accepted. Do not expose component references, arbitrary segment IDs, callbacks, or styling controls.

  • Step 4: Forward the API through the interactive extension UI controller

Add to uiContext in ExtensionUiController.initHooksAndCustomTools():

setStatusSegment: (key, text, options) => {
  if (options.placement !== "after-cost") return;
  this.ctx.statusLine.setExtensionStatusSegment(key, text);
  this.ctx.ui.requestRender();
},

Add no-op implementations for non-interactive mock UI contexts in extensibility/utils.ts, extensibility/extensions/runner.ts, modes/acp/acp-agent.ts, and session/agent-session.ts, matching the existing setStatus convention.

  • Step 5: Store and render sanitized extension segments in the status-line component

Add a private Map<string, string> and method:

setExtensionStatusSegment(key: string, text: string | undefined): void {
  if (text === undefined) this.#extensionStatusSegments.delete(key);
  else this.#extensionStatusSegments.set(key, sanitizeStatusText(text));
}

In #buildStatusLine, retain IDs for both rendered groups. After collecting built-in segments, insert the map values sorted by key immediately after the rendered cost entry in whichever group contains it. If cost is not visible, omit extension segments; their contract is explicitly after visible cost. Include synthetic IDs in the width bookkeeping so the normal right-to-left overflow policy can evict them without breaking leftSegIds alignment.

  • Step 6: Run the focused test to verify behavior

Run:

bun test packages/coding-agent/src/modes/components/status-line/component.test.ts

Expected: PASS. It proves deterministic ordering, sanitization, and clearing.

  • Step 7: Type-check and commit the OMP API

Run:

bun --cwd packages/coding-agent run check:types
git diff --check
git add packages/coding-agent/src/extensibility/extensions/types.ts packages/coding-agent/src/extensibility/utils.ts packages/coding-agent/src/extensibility/extensions/runner.ts packages/coding-agent/src/modes/acp/acp-agent.ts packages/coding-agent/src/modes/components/status-line/component.ts packages/coding-agent/src/modes/components/status-line/component.test.ts packages/coding-agent/src/modes/controllers/extension-ui-controller.ts packages/coding-agent/src/session/agent-session.ts
git commit -m "feat: expose after-cost extension status segments"

Expected: type-check exits 0 and the commit contains only the API, wiring, component, and test.

Task 3: Publish Telegram bridge state through the new API

Files:

  • Modify: D:/Documents/Github/oh-my-pi-telegram/lib/pi.ts

  • Modify: D:/Documents/Github/oh-my-pi-telegram/lib/status.ts

  • Modify: D:/Documents/Github/oh-my-pi-telegram/index.ts

  • Test: D:/Documents/Github/oh-my-pi-telegram/tests/status.test.ts

  • Step 1: Write failing plugin status tests

Add pure tests for a new helper with these observable contracts:

assert.equal(getTelegramTopStatusSegment({ pollingActive: true }), "Telegram: conectado");
assert.equal(getTelegramTopStatusSegment({ pollingActive: false }), "Telegram: desconectado");

Add an injected setStatusSegment spy and call runtime.updateStatus(ctx) with a context whose ui.setStatus is a no-op. Assert that the captured publication is:

["telegram", "Telegram: conectado", { placement: "after-cost" }]

when polling becomes active, and the disconnected text when it becomes inactive.

  • Step 2: Run the focused status test and observe the missing helper failure

Run:

node --experimental-strip-types --test tests/status.test.ts

Expected: FAIL because getTelegramTopStatusSegment is not exported.

  • Step 3: Add a narrow OMP context capability adapter

In lib/pi.ts, define structural ports without importing OMP internal modules:

export interface PiTopStatusSegmentPorts {
  setStatusSegment?: (
    key: string,
    text: string | undefined,
    options: { placement: "after-cost" },
  ) => void;
}

export function setExtensionContextTopStatusSegment(
  ctx: ExtensionContext,
  key: string,
  text: string,
): void {
  const ui = ctx.ui as ExtensionContext["ui"] & PiTopStatusSegmentPorts;
  ui.setStatusSegment?.(key, text, { placement: "after-cost" });
}

The optional capability keeps passive modes and stale local SDK declarations from throwing. The package compatibility floor still makes OMP 17 the supported runtime.

  • Step 4: Publish the two-state bridge label in lib/status.ts

Add:

export function getTelegramTopStatusSegment(state: Pick<TelegramStatusBarState, "pollingActive">): string {
  return state.pollingActive ? "Telegram: conectado" : "Telegram: desconectado";
}

Extend TelegramStatusRuntimeDeps with optional:

setStatusSegment?: (ctx: TContext, key: string, text: string) => void;

In updateStatus, compute the bridge state once, retain the existing footer setStatus call, and then call:

deps.setStatusSegment?.(ctx, "telegram", getTelegramTopStatusSegment(state));

The status runtime is already called from connect, disconnect, polling, lock, and session updates, so no additional event listeners are added.

  • Step 5: Wire the context adapter from index.ts

Pass Pi.setExtensionContextTopStatusSegment as setStatusSegment into createTelegramBridgeStatusRuntime. Do not call the OMP API directly outside the lib/pi.ts adapter boundary.

  • Step 6: Run focused tests and type-check

Run:

node --experimental-strip-types --test tests/status.test.ts
npm run typecheck

Expected: all focused status tests pass and TypeScript exits 0.

  • Step 7: Commit the plugin integration
git diff --check
git add lib/pi.ts lib/status.ts index.ts tests/status.test.ts
git commit -m "feat: publish Telegram bridge status in OMP"

Task 4: Correct OMP installation and secure setup documentation

Files:

  • Modify: D:/Documents/Github/oh-my-pi-telegram/README.md

  • Modify: D:/Documents/Github/oh-my-pi-telegram/package.json

  • Modify: D:/Documents/Github/oh-my-pi-telegram/tests/public-api.test.ts

  • Step 1: Write a failing manifest test for the OMP 17 floor

Change the existing test expectation to:

assert.equal(
  packageJson.omp?.compatibleWith?.["@oh-my-pi/pi-coding-agent"],
  ">=17.0.0",
);
  • Step 2: Run the manifest test and observe the floor mismatch

Run:

node --experimental-strip-types --test tests/public-api.test.ts

Expected: FAIL because the manifest still declares >=16.5.2.

  • Step 3: Update the manifest and README

Set the OMP compatibility floor in package.json to >=17.0.0.

Replace the incorrect OMP install block with:

omp plugin install npm:@evandrodevbr/oh-my-pi-telegram
omp plugin install git:github.com/evandrodevbr/oh-my-pi-telegram
omp plugin link /path/to/oh-my-pi-telegram

Document restarting OMP after installation/linking. Keep bot-token setup limited to the interactive commands:

/telegram-setup
/telegram-connect
/telegram-disconnect
/telegram-status

Explicitly state that bot tokens must not be committed or pasted into chat.

  • Step 4: Run documentation-adjacent verification

Run:

node --experimental-strip-types --test tests/public-api.test.ts
npm run typecheck
npm run audit
npm run pack:check

Expected: all commands exit 0.

  • Step 5: Commit documentation and compatibility metadata
git diff --check
git add README.md package.json tests/public-api.test.ts
git commit -m "docs: document OMP 17 Telegram setup"

Task 5: Build, install, configure, and smoke-test the integrated runtime

Files:

  • Modify: no source files expected.

  • Step 1: Build and link the versioned OMP checkout

From D:/Documents/Github/oh-my-pi:

bun --cwd packages/coding-agent run check:types
bun --cwd packages/coding-agent run build
bun --cwd packages/coding-agent link
omp --version

Expected: the linked omp reports the built 17.x version. Do not edit or link files under the Bun global package directory directly.

  • Step 2: Link the updated Telegram plugin

From D:/Documents/Github/oh-my-pi-telegram:

omp plugin link .
omp plugin doctor

Expected: the doctor lists @evandrodevbr/oh-my-pi-telegram with zero errors.

  • Step 3: Configure the replacement token locally

Start omp in the user's own terminal and run:

/telegram-setup

Paste the new bot token only into OMP's local prompt. Then run:

/telegram-connect

Expected: polling starts and the upper status bar contains Telegram: conectado after $… (sub).

  • Step 4: Exercise disconnect and command behavior

In the same OMP session, run:

/telegram-status
/telegram-disconnect

Expected: /telegram-status returns bridge diagnostics and the upper status bar changes to Telegram: desconectado after cost.

  • Step 5: Commit and push both repositories

From each repository after its focused tests pass:

git status --short
git push origin HEAD

Expected: both commits are on their respective remote branches. Do not push a bot token, generated build output, Bun-global installation files, or .env files.