feat(pi): @cotal-ai/pi native-embed coding-agent mesh peer#126
feat(pi): @cotal-ai/pi native-embed coding-agent mesh peer#126Lanzelot1 wants to merge 3 commits into
Conversation
85b3f02 to
6d39239
Compare
Rebased onto current
|
6d39239 to
79c9c43
Compare
79c9c43 to
89a57ed
Compare
Sibling native-embed adapters to @cotal-ai/pi, reusing connector-core's
InboxTurn: @cotal-ai/openai-agents (OpenAI Agents SDK) and @cotal-ai/vercel-ai
(Vercel AI SDK). Each embeds MeshAgent + the framework session and answers
DMs/anycasts/@-mentions off the inbox. Adds examples/03-{openai-agents,vercel-ai}.
Stacked on feat/land-connector-pi (pi PR #126) for the shared InboxTurn; becomes
a standalone PR once pi lands.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Scope / containmentThis change is contained in the integrations tier — the protocol core is not touched:
|
|
I've been building a Pi integration from a different angle and wanted to share two things that might be complementary rather than overlapping. 1. Interactive-session vs. headless peer.
2. A |
|
@Lanzelot1 I've got my PR stacked on top at #182 - very clean; thanks very much for the Pi foundation! @deshbirc I had the same thought and put together this PR for exactly the same reason. I want to be able to manually watch/interact with agent terminals so that I can babysit edit permissions and code since "just throw it at the wall and see what sticks" vibing never produces anything near what proper engineering does. I've managed to add a ctx.hasUI friendly flag that should keep all of this intact and allow BOTH headless and TUI based agents. Feel free to hop on that one and let me know if it solves your original concerns or if you had a different shape. I don't think I looked to in-depth into the "working/idle" approach like you have so that would be cool to hear about. |
dd59322 to
30b8774
Compare
MeshAgent.ackInbox acks specific buffered messages by id, wherever they sit — immune to the MAX_INBOX front-eviction that shifts positions out from under drainInbox — so a consumer can ack exactly the messages a turn surfaced. Plus shared-layer fixes that apply to every connector: senders rendered as "name" (role) so models stop replying to the literal name/role text, own channel echoes excluded from the wake policy, display-form "#chan" channel args normalized fail-loud instead of silently token-rewritten, historical items flagged as catch-up context in injections, and the provider-key allow-list extended (Gemini/Groq/xAI/DeepSeek/Mistral).
The mesh as a pi extension, plugged into the user's OWN pi — no bundled runtime. One file covers three surfaces: `pi --extension` puts the interactive TUI session on the mesh; the Connector spawns the operator's installed `pi` with the extension loaded (the worker IS the real TUI, watchable via cotal attach); and pi's default resource loader discovers ~/.pi/agent/extensions, so agents built on pi's SDK join with no per-app work. Without a COTAL_* identity in the env the extension stays inert. Inbound DMs/anycasts/@mentions land as user turns in the live session (steered mid-turn while streaming); the loop owns reply routing on the correct delivery scope, with ack-on-surface via InboxTurn — a crash redelivers, nothing is lost. The model gets cotal_roster / cotal_status; sending stays in the loop.
Spawned peers ignored the agent file's persona body and pinned model — the pi connector was the lone holdout among the harness connectors. buildLaunch parses the file at launch (a malformed persona fails loud at cotal spawn), passes the frontmatter-stripped persona body to pi via --append-system-prompt with a file path (no ARG_MAX ceiling), and forwards the resolved model via --model, with the spawn flag taking precedence over the file's model: pin.
30b8774 to
f5699de
Compare
Adds
@cotal-ai/pi: the Cotal mesh as a pi extension — a thin client into the user's own pi installation. No pi runtime is bundled; the user's pi version, settings, auth, and other extensions all apply.One extension file covers three surfaces:
pi --extension <file>(plusCOTAL_*env): the TUI session a human is sitting in becomes a mesh peer.Connector(agent typepi) launches the operator's installedpibinary with the extension loaded, like the Claude Code connector spawnsclaude. Under the manager's pty runtime the worker is the real pi TUI —cotal attachshows it.~/.pi/agent/extensions/, so default SDK embedders join with no per-app work. (Forks and custom-loader apps, e.g. openclaw, need their own thin plugin — a follow-up.)Without a mesh identity in the env the extension stays inert, so an installed copy never affects normal pi sessions.
Inbound DMs, role anycasts, and @mentions land as user turns in the live session (steered mid-turn while streaming), with ack-on-surface via the package's
InboxTurn— a crash redelivers, nothing is lost. (InboxTurnlives in this package as its sole consumer; it gets promoted to connector-core if/when another native-embed adapter needs it.) The model gets the full sharedcotal_*toolset (rendered from connector-core'scotalToolSpecs, the same source the Claude Code and OpenCode adapters render) and owns its replies: it answers by callingcotal_dm/cotal_send/cotal_anycast, can stay silent when no reply is warranted, and nothing leaves the peer that it didn't deliberately send.cotal_inboxis read-only (peek) since the loop drives delivery and acking. Persona body andmodel:from the agent file ride pi's own CLI flags (--append-system-promptwith a frontmatter-stripped file,--model) — contributed by @TheReaperJay, whose commit is included with authorship.Contents
extensions/pi/*— the extension + tool renderer + connector, plusInboxTurn(the ack-on-surface turn helper) and itssmoke:inboxextensions/connector-core— additive only:MeshAgent.ackInbox(ack-by-id) and small shared-surface fixes (sender framing, own-echo wake exclusion,#channormalization, provider keys)bin/cotal.ts— one import line: the binary registers thepiconnector like every sibling, socotal spawn --agent piworks out of the box (no dedicated example needed — none of the other connectors has one)agent-frameworks.md, READMEs)Scope
pi only.
packages/coreuntouched — no new message kinds, subjects, or endpoint methods.buildLaunchfollows the siblinglaunchEnv/aclEnvcontract. One accepted residual, documented in code: pi's extension API can't drain the steering queue at turn end, so a message steered after the loop's final poll can carry into the next turn; SDK embedders needing it fully closed can wiresession.clearQueue()+InboxTurn.commitExceptdirectly (documented pattern).Vetting
pnpm typecheck,pnpm build,pnpm smoke:cigreen;smoke:inboxcovers the InboxTurn invariants.piwith the extension loaded (real model turns): peer joins; a DM is answered via acotal_dmtool call and a channel @mention viacotal_sendback on that channel; ambient chatter is ack-dropped in silence;cotal_roster/ read-onlycotal_inboxwork from a prompt; killing the pi process mid-turn and restarting redelivers the un-acked message and it gets answered — no message loss; withoutCOTAL_*env a normal pi session is completely unaffected.