mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 18:01:22 +00:00
docs(coding-agent): improve extensions.md, add missing examples
- Add cross-links to session.md, keybindings.md, themes.md - Document truncateLine, highlightCode, getLanguageFromPath utilities - Add examples for previously undocumented APIs: - message-renderer.ts: registerMessageRenderer with Box styling - session-name.ts: setSessionName/getSessionName - event-bus.ts: pi.events for inter-extension communication - bookmark.ts: setLabel for entry bookmarking - Update examples table in extensions.md and README.md
This commit is contained in:
parent
c565fa9af8
commit
930207130b
6 changed files with 285 additions and 68 deletions
|
|
@ -88,6 +88,20 @@ cp permission-gate.ts ~/.pi/agent/extensions/
|
|||
|-----------|-------------|
|
||||
| `mac-system-theme.ts` | Syncs pi theme with macOS dark/light mode |
|
||||
|
||||
### Messages & Communication
|
||||
|
||||
| Extension | Description |
|
||||
|-----------|-------------|
|
||||
| `message-renderer.ts` | Custom message rendering with colors and expandable details via `registerMessageRenderer` |
|
||||
| `event-bus.ts` | Inter-extension communication via `pi.events` |
|
||||
|
||||
### Session Metadata
|
||||
|
||||
| Extension | Description |
|
||||
|-----------|-------------|
|
||||
| `session-name.ts` | Name sessions for the session selector via `setSessionName` |
|
||||
| `bookmark.ts` | Bookmark entries with labels for `/tree` navigation via `setLabel` |
|
||||
|
||||
### Custom Providers
|
||||
|
||||
| Extension | Description |
|
||||
|
|
|
|||
50
packages/coding-agent/examples/extensions/bookmark.ts
Normal file
50
packages/coding-agent/examples/extensions/bookmark.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Entry bookmarking example.
|
||||
*
|
||||
* Shows setLabel to mark entries with labels for easy navigation in /tree.
|
||||
* Labels appear in the tree view and help you find important points.
|
||||
*
|
||||
* Usage: /bookmark [label] - bookmark the last assistant message
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
pi.registerCommand("bookmark", {
|
||||
description: "Bookmark last message (usage: /bookmark [label])",
|
||||
handler: async (args, ctx) => {
|
||||
const label = args.trim() || `bookmark-${Date.now()}`;
|
||||
|
||||
// Find the last assistant message entry
|
||||
const entries = ctx.sessionManager.getEntries();
|
||||
for (let i = entries.length - 1; i >= 0; i--) {
|
||||
const entry = entries[i];
|
||||
if (entry.type === "message" && entry.message.role === "assistant") {
|
||||
pi.setLabel(entry.id, label);
|
||||
ctx.ui.notify(`Bookmarked as: ${label}`, "info");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.ui.notify("No assistant message to bookmark", "warning");
|
||||
},
|
||||
});
|
||||
|
||||
// Remove bookmark
|
||||
pi.registerCommand("unbookmark", {
|
||||
description: "Remove bookmark from last labeled entry",
|
||||
handler: async (_args, ctx) => {
|
||||
const entries = ctx.sessionManager.getEntries();
|
||||
for (let i = entries.length - 1; i >= 0; i--) {
|
||||
const entry = entries[i];
|
||||
const label = ctx.sessionManager.getLabel(entry.id);
|
||||
if (label) {
|
||||
pi.setLabel(entry.id, undefined);
|
||||
ctx.ui.notify(`Removed bookmark: ${label}`, "info");
|
||||
return;
|
||||
}
|
||||
}
|
||||
ctx.ui.notify("No bookmarked entry found", "warning");
|
||||
},
|
||||
});
|
||||
}
|
||||
43
packages/coding-agent/examples/extensions/event-bus.ts
Normal file
43
packages/coding-agent/examples/extensions/event-bus.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Inter-extension event bus example.
|
||||
*
|
||||
* Shows pi.events for communication between extensions. One extension
|
||||
* can emit events that other extensions listen to.
|
||||
*
|
||||
* Usage: /emit [event-name] [data] - emit an event on the bus
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
// Store ctx for use in event handler
|
||||
let currentCtx: ExtensionContext | undefined;
|
||||
|
||||
pi.on("session_start", async (_event, ctx) => {
|
||||
currentCtx = ctx;
|
||||
});
|
||||
|
||||
// Listen for events from other extensions
|
||||
pi.events.on("my:notification", (data) => {
|
||||
const { message, from } = data as { message: string; from: string };
|
||||
currentCtx?.ui.notify(`Event from ${from}: ${message}`, "info");
|
||||
});
|
||||
|
||||
// Command to emit events (emits "my:notification" which the listener above receives)
|
||||
pi.registerCommand("emit", {
|
||||
description: "Emit my:notification event (usage: /emit message)",
|
||||
handler: async (args, _ctx) => {
|
||||
const message = args.trim() || "hello";
|
||||
pi.events.emit("my:notification", { message, from: "/emit command" });
|
||||
// Listener above will show the notification
|
||||
},
|
||||
});
|
||||
|
||||
// Example: emit on session start
|
||||
pi.on("session_start", async () => {
|
||||
pi.events.emit("my:notification", {
|
||||
message: "Session started",
|
||||
from: "event-bus-example",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Custom message rendering example.
|
||||
*
|
||||
* Shows how to use registerMessageRenderer to control how custom messages
|
||||
* appear in the TUI, with colors, formatting, and expandable details.
|
||||
*
|
||||
* Usage: /status [message] - sends a status message with custom rendering
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
||||
import { Box, Text } from "@mariozechner/pi-tui";
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
// Register custom renderer for "status-update" messages
|
||||
pi.registerMessageRenderer("status-update", (message, { expanded }, theme) => {
|
||||
const details = message.details as { level: string; timestamp: number } | undefined;
|
||||
const level = details?.level ?? "info";
|
||||
|
||||
// Color based on level
|
||||
const color = level === "error" ? "error" : level === "warn" ? "warning" : "success";
|
||||
const prefix = theme.fg(color, `[${level.toUpperCase()}]`);
|
||||
|
||||
let text = `${prefix} ${message.content}`;
|
||||
|
||||
// Show timestamp when expanded
|
||||
if (expanded && details?.timestamp) {
|
||||
const time = new Date(details.timestamp).toLocaleTimeString();
|
||||
text += `\n${theme.fg("dim", ` at ${time}`)}`;
|
||||
}
|
||||
|
||||
// Use Box with customMessageBg for consistent styling
|
||||
const box = new Box(1, 1, (t) => theme.bg("customMessageBg", t));
|
||||
box.addChild(new Text(text, 0, 0));
|
||||
return box;
|
||||
});
|
||||
|
||||
// Command to send status messages
|
||||
pi.registerCommand("status", {
|
||||
description: "Send a status message (usage: /status [warn|error] message)",
|
||||
handler: async (args, _ctx) => {
|
||||
const parts = args.trim().split(/\s+/);
|
||||
let level = "info";
|
||||
let content = args.trim();
|
||||
|
||||
// Check for level prefix
|
||||
if (parts[0] === "warn" || parts[0] === "error") {
|
||||
level = parts[0];
|
||||
content = parts.slice(1).join(" ") || "Status update";
|
||||
}
|
||||
|
||||
pi.sendMessage({
|
||||
customType: "status-update",
|
||||
content,
|
||||
display: true,
|
||||
details: { level, timestamp: Date.now() },
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
27
packages/coding-agent/examples/extensions/session-name.ts
Normal file
27
packages/coding-agent/examples/extensions/session-name.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Session naming example.
|
||||
*
|
||||
* Shows setSessionName/getSessionName to give sessions friendly names
|
||||
* that appear in the session selector instead of the first message.
|
||||
*
|
||||
* Usage: /session-name [name] - set or show session name
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
pi.registerCommand("session-name", {
|
||||
description: "Set or show session name (usage: /session-name [new name])",
|
||||
handler: async (args, ctx) => {
|
||||
const name = args.trim();
|
||||
|
||||
if (name) {
|
||||
pi.setSessionName(name);
|
||||
ctx.ui.notify(`Session named: ${name}`, "info");
|
||||
} else {
|
||||
const current = pi.getSessionName();
|
||||
ctx.ui.notify(current ? `Session: ${current}` : "No session name set", "info");
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue