Skip to content

feat(connector-oh-my-pi): render cotal_* tool calls natively (no spinner fallback) - #11

Closed
sealedsecurity-bot wants to merge 2 commits into
cotal-connector-esc-composerfrom
cotal-connector-renderer-tools
Closed

feat(connector-oh-my-pi): render cotal_* tool calls natively (no spinner fallback)#11
sealedsecurity-bot wants to merge 2 commits into
cotal-connector-esc-composerfrom
cotal-connector-renderer-tools

Conversation

@sealedsecurity-bot

Copy link
Copy Markdown

What

Workstream A of the native OMP renderer design (docs/designs/platform/cotal-connector-renderer.md): give the cotal_* tools a renderCall so their tool cards render natively instead of falling back to OMP's generic animated-spinner glyph (the artifact Matt flagged).

  • Attach renderCall to both registration branches in registerSpec — the cotal_inbox read-only branch and the generic branch. Returning a Component is what takes OMP's custom-renderer path instead of the spinner fallback.
  • The renderer is a titled single line: the tool label plus a per-surface summary from args — recipient for cotal_dm, channel + mentions for cotal_send, role for cotal_anycast, status/attention/activity for cotal_status, a static label for cotal_inbox. cotalCallSummary is pure and exported for the smoke.
  • Extends the extension smoke: every registered tool must expose a renderCall (the spinner-fallback regression guard), and the summary is arg-enriched. Red-green verified (removing the generic renderCall fails the new assertion).

Scope

  • Confined to extensions/connector-oh-my-pi (+ a type-only devDependency). No core/protocol change.
  • Display-only: content (the LLM-visible text / non-TUI fallback) is untouched.
  • Workstream B (inbound cotal:incoming/cotal:nudge message renderer) is intentionally not here — it ships separately per the design's split-delivery decision.

Verification

  • pnpm --filter @cotal-ai/oh-my-pi build — tsc + esbuild bundle clean.
  • pnpm --filter @cotal-ai/oh-my-pi test — all three connector smokes green (peer, extension, interactive-loop).
  • Red-green: the new renderCall-present assertion fails when the hook is removed, passes with it.

Open Questions (parked for Matt — overnight)

  1. [LOAD-BEARING — landing target] This PR is stacked on fix(connector): deliver peer messages as nextTurn, not steer #8 (cotal-connector-esc-composer), not main. The connector code (registerSpec in extension.ts) exists only on fix(connector): deliver peer messages as nextTurn, not steer #8, which is fork-base held (stacked on feat(oh-my-pi): Cotal connector — headless peer + interactive extension #5). Implemented against the design's own recommendation (OQ#2 option (a): stack + park, execute-ready the moment the fork-base clears) rather than waiting for fix(connector): deliver peer messages as nextTurn, not steer #8main. If you'd rather it wait for fix(connector): deliver peer messages as nextTurn, not steer #8 to land and re-base off main, say so and I'll retarget. Verified: extension.ts is absent on origin/main, so basing on main today is not possible without fix(connector): deliver peer messages as nextTurn, not steer #8.

  2. [implementation refinement, non-load-bearing] Component is imported type-only; the renderer returns a minimal hand-rolled Component rather than pi-tui's Text. The design named @oh-my-pi/pi-tui primitives, but a runtime pi-tui import drags @oh-my-pi/pi-utils' barrel, which does import { YAML } from "bun" — unloadable under the connector's Node/tsx smoke harness (the real OMP runtime is Bun, so Text would work there, but CI smokes run on Node). The Component interface requires only render(width): readonly string[], so a hand-rolled one is a valid Component, keeps the connector's existing type-only-OMP discipline, and avoids the Bun coupling. @oh-my-pi/pi-tui is therefore a type-only devDependency. If you'd prefer real Text + a Bun-run smoke, that's the alternative.

Co-Authored-By: seal noreply@sealedsecurity.com

…ner fallback)

The cotal_* tools registered via `pi.registerTool` carried no `renderCall`, so
OMP fell back to its generic animated-spinner glyph on every tool card. Attach a
`renderCall` to both registration branches (the `cotal_inbox` read-only branch
and the generic branch) in `registerSpec`: returning a Component takes OMP's
custom-renderer branch instead of the spinner fallback.

The renderer is a titled single line — the tool label plus a per-surface summary
drawn from args (recipient for cotal_dm, channel + mentions for cotal_send, role
for cotal_anycast, status/attention/activity for cotal_status, a static label for
cotal_inbox). `cotalCallSummary` is pure and exported for the smoke.

Component is imported type-only from `@oh-my-pi/pi-tui` and the renderer returns a
minimal hand-rolled Component (only `render(width)` is required by the interface)
rather than pi-tui's `Text`: a runtime pi-tui import drags `@oh-my-pi/pi-utils`'
Bun-coupled barrel (`import { YAML } from "bun"`), which the Node/tsx smoke can't
load. pi-tui is therefore a type-only devDependency.

Workstream A of the native-renderer design (docs/designs/platform/cotal-connector-renderer.md);
the inbound message renderer (Workstream B) follows separately. Extends the
extension smoke to assert every registered tool exposes a renderCall (the
spinner-fallback regression guard) and that the summary is arg-enriched.

Co-Authored-By: seal <noreply@sealedsecurity.com>
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a545e562-b83b-42c5-81d2-877334d53423

📥 Commits

Reviewing files that changed from the base of the PR and between 6501bb5 and ff91562.

📒 Files selected for processing (2)
  • extensions/connector-oh-my-pi/oh-my-pi-extension.smoke.ts
  • extensions/connector-oh-my-pi/src/extension.ts

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added concise visual previews for Cotal tool calls in the interface.
    • Inbox actions now display a clear “peek inbox” summary.
  • Bug Fixes
    • Previews now correctly reflect recipient/channel details for direct and channel sends.
    • Improved width-fitting behavior, including proper handling of zero-width rendering and consistent truncation.
  • Tests
    • Expanded smoke test coverage to validate rendering output for all registered Cotal tools.

Walkthrough

The extension adds compact, width-aware renderers and argument-based summaries for all registered cotal_* tools. Default channel resolution now uses concrete subscriptions, and smoke tests cover rendering, destination details, explicit-channel precedence, and zero-width output.

Changes

Cotal tool-call rendering

Layer / File(s) Summary
Renderer summaries and registration
extensions/connector-oh-my-pi/src/extension.ts, extensions/connector-oh-my-pi/package.json
Cotal tools expose width-aware renderers with defensive argument summaries, resolved default channels, and the required UI component dependency.
Renderer smoke coverage
extensions/connector-oh-my-pi/oh-my-pi-extension.smoke.ts
Smoke tests validate every registered renderer, recipient/channel details, explicit-channel precedence, and zero-width output clamping.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RegisteredCotalTool
  participant cotalCallSummary
  participant renderCotalCall
  participant OMPUI
  RegisteredCotalTool->>cotalCallSummary: provide tool name, args, and default channel
  cotalCallSummary-->>renderCotalCall: return call summary
  renderCotalCall-->>OMPUI: return Component
  OMPUI->>renderCotalCall: request render(width)
  renderCotalCall-->>OMPUI: return truncated line
Loading

Poem

I’m a rabbit with previews to show,
Compact calls now neatly flow.
Channels resolve, widths obey,
Tests hop through each UI display—
A tidy burrow for every day!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: native rendering for cotal_* tool calls instead of the spinner fallback.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the renderer, smoke tests, and scope.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cotal-connector-renderer-tools

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds native Oh My Pi rendering for the cotal_* tool cards. The main changes are:

  • Adds argument-aware one-line summaries for tool calls.
  • Wires renderCall into both tool registration paths.
  • Uses the resolved default send channel when no channel is provided.
  • Adds smoke coverage for renderer presence, enriched summaries, and tight-width rendering.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
extensions/connector-oh-my-pi/src/extension.ts Adds the native call renderer, summary helper, default-channel-aware send display, and width-bounded output.
extensions/connector-oh-my-pi/oh-my-pi-extension.smoke.ts Adds smoke coverage for renderCall, argument-enriched summaries, omitted send channels, explicit send channels, and zero-width rendering.
extensions/connector-oh-my-pi/package.json Adds the Pi TUI package for the erased Component type import.
pnpm-lock.yaml Locks the new connector dev dependency.

Reviews (2): Last reviewed commit: "fix(connector-oh-my-pi): cotal_send card..." | Re-trigger Greptile

Comment thread extensions/connector-oh-my-pi/src/extension.ts Outdated
Comment thread extensions/connector-oh-my-pi/src/extension.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
extensions/connector-oh-my-pi/src/extension.ts (1)

145-198: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

LGTM! The defensive arg parsing in cotalCallSummary and the minimal hand-rolled Component in renderCotalCall are clean and well-documented.

One optional nit: the truncation-with-ellipsis pattern (slice(0, n - 1) + "…") appears in both preview (line 154) and renderCotalCall (line 194). A shared truncate(s, max) helper would eliminate the duplication and keep the edge-case handling consistent. Feel free to defer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@extensions/connector-oh-my-pi/src/extension.ts` around lines 145 - 198,
Optionally extract the duplicated truncation-with-ellipsis logic from
cotalCallSummary’s preview and renderCotalCall into a shared truncate(s, max)
helper, preserving current handling for zero or narrow widths and updating both
call sites to use it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@extensions/connector-oh-my-pi/src/extension.ts`:
- Around line 145-198: Optionally extract the duplicated
truncation-with-ellipsis logic from cotalCallSummary’s preview and
renderCotalCall into a shared truncate(s, max) helper, preserving current
handling for zero or narrow widths and updating both call sites to use it.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 45b079a0-2a69-476e-b8c0-27ba6c3f59c2

📥 Commits

Reviewing files that changed from the base of the PR and between 8b98869 and 6501bb5.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • extensions/connector-oh-my-pi/oh-my-pi-extension.smoke.ts
  • extensions/connector-oh-my-pi/package.json
  • extensions/connector-oh-my-pi/src/extension.ts

…mp zero-width render

Two display-correctness fixes on the cotal_* tool-call renderer, from PR review:

- Send cards named the wrong channel: the renderer hardcoded `#general` for an
  omitted `channel`, but the tool resolves the omitted case to the agent's
  configured default (`config.subscribe.find(isConcreteChannel) ?? "general"`,
  per CotalEndpoint.multicast). An agent whose default was not `general` saw a
  card claiming `#general` while the message went elsewhere. Thread the same
  resolved default into `cotalCallSummary` so the card names the true target.
- Zero-width render slot bypassed truncation: a `width <= 0` (or non-finite)
  slot fell through to `line.length` and returned the untruncated title,
  violating the width-bounded render contract. Clamp to a single empty line.
- Extract the shared `truncate(s, max)` helper used by both the summary preview
  and the render clamp, so the narrow/zero-width edges are handled identically.

Extends the extension smoke (3c): omitted send channel shows the resolved
default (not a fabricated `#general`), explicit channel still wins, and a
zero-width render returns `[""]`. Red-green verified.

Co-Authored-By: seal <noreply@sealedsecurity.com>
@mattwilkinsonn
mattwilkinsonn deleted the branch cotal-connector-esc-composer July 25, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants