style(deps): migrated from Prettier to Biome and updated formatting rules
- Removed Prettier configuration files (.prettierignore and .prettierrc) and migrated formatting to Biome. - Updated Biome configuration from version 2.3.11 to 2.3.12 and changed arrowParentheses rule from 'always' to 'asNeeded'. - Pinned @biomejs/biome dependency to exact version 2.3.12 in package.json and bun.lock. - Applied consistent arrow function formatting across 489 files by removing unnecessary parentheses around single parameters. - Removed blank lines after comment blocks and reorganized imports for consistency across the codebase.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { CustomToolFactory } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
const factory: CustomToolFactory = (pi) => ({
|
||||
const factory: CustomToolFactory = pi => ({
|
||||
name: "hello",
|
||||
label: "Hello",
|
||||
description: "A simple greeting tool",
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*
|
||||
* The onSession callback reconstructs state by scanning past tool results.
|
||||
*/
|
||||
|
||||
import type {
|
||||
CustomTool,
|
||||
CustomToolContext,
|
||||
@@ -29,7 +28,7 @@ interface TodoDetails {
|
||||
error?: string;
|
||||
}
|
||||
|
||||
const factory: CustomToolFactory = (pi) => {
|
||||
const factory: CustomToolFactory = pi => {
|
||||
const { Type } = pi.typebox;
|
||||
const { StringEnum, Text } = pi.pi;
|
||||
|
||||
@@ -85,7 +84,7 @@ const factory: CustomToolFactory = (pi) => {
|
||||
{
|
||||
type: "text",
|
||||
text: todos.length
|
||||
? todos.map((t) => `[${t.done ? "x" : " "}] #${t.id}: ${t.text}`).join("\n")
|
||||
? todos.map(t => `[${t.done ? "x" : " "}] #${t.id}: ${t.text}`).join("\n")
|
||||
: "No todos",
|
||||
},
|
||||
],
|
||||
@@ -114,7 +113,7 @@ const factory: CustomToolFactory = (pi) => {
|
||||
details: { action: "toggle", todos: [...todos], nextId, error: "id required" },
|
||||
};
|
||||
}
|
||||
const todo = todos.find((t) => t.id === params.id);
|
||||
const todo = todos.find(t => t.id === params.id);
|
||||
if (!todo) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Todo #${params.id} not found` }],
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* These features are now exposed directly on the ExtensionAPI, matching
|
||||
* the CustomToolAPI interface.
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Example extension that uses a 3rd party dependency (chalk).
|
||||
* Tests that jiti can resolve npm modules correctly.
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
import chalk from "chalk";
|
||||
|
||||
@@ -14,12 +13,12 @@ export default function (pi: ExtensionAPI) {
|
||||
console.log(`${chalk.blue("[chalk-logger]")} Agent starting`);
|
||||
});
|
||||
|
||||
pi.on("tool_call", async (event) => {
|
||||
pi.on("tool_call", async event => {
|
||||
console.log(`${chalk.yellow("[chalk-logger]")} Tool: ${chalk.cyan(event.toolName)}`);
|
||||
return undefined;
|
||||
});
|
||||
|
||||
pi.on("agent_end", async (event) => {
|
||||
pi.on("agent_end", async event => {
|
||||
const count = event.messages.length;
|
||||
console.log(`${chalk.green("[chalk-logger]")} Done with ${chalk.bold(String(count))} messages`);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Demonstrates using ExtensionAPI's logger, typebox, and pi module access.
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
* 2. Use /pirate to toggle pirate mode
|
||||
* 3. When enabled, the agent will respond like a pirate
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function pirateExtension(pi: ExtensionAPI) {
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
* 2. Use /plan to toggle plan mode on/off
|
||||
* 3. Or start in plan mode with --plan flag
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI, ExtensionContext } from "@oh-my-pi/pi-coding-agent";
|
||||
import { Key } from "@oh-my-pi/pi-tui";
|
||||
|
||||
@@ -120,12 +119,12 @@ const SAFE_COMMANDS = [
|
||||
];
|
||||
|
||||
function isSafeCommand(command: string): boolean {
|
||||
if (SAFE_COMMANDS.some((pattern) => pattern.test(command))) {
|
||||
if (!DESTRUCTIVE_PATTERNS.some((pattern) => pattern.test(command))) {
|
||||
if (SAFE_COMMANDS.some(pattern => pattern.test(command))) {
|
||||
if (!DESTRUCTIVE_PATTERNS.some(pattern => pattern.test(command))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (DESTRUCTIVE_PATTERNS.some((pattern) => pattern.test(command))) {
|
||||
if (DESTRUCTIVE_PATTERNS.some(pattern => pattern.test(command))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -223,7 +222,7 @@ export default function planModeExtension(pi: ExtensionAPI) {
|
||||
// Helper to update status displays
|
||||
function updateStatus(ctx: ExtensionContext) {
|
||||
if (executionMode && todoItems.length > 0) {
|
||||
const completed = todoItems.filter((t) => t.completed).length;
|
||||
const completed = todoItems.filter(t => t.completed).length;
|
||||
ctx.ui.setStatus("plan-mode", ctx.ui.theme.fg("accent", `📋 ${completed}/${todoItems.length}`));
|
||||
} else if (planModeEnabled) {
|
||||
ctx.ui.setStatus("plan-mode", ctx.ui.theme.fg("warning", "⏸ plan"));
|
||||
@@ -293,13 +292,13 @@ export default function planModeExtension(pi: ExtensionAPI) {
|
||||
// Register Shift+P shortcut
|
||||
pi.registerShortcut(Key.shift("p"), {
|
||||
description: "Toggle plan mode",
|
||||
handler: async (ctx) => {
|
||||
handler: async ctx => {
|
||||
await togglePlanMode(ctx);
|
||||
},
|
||||
});
|
||||
|
||||
// Block destructive bash in plan mode
|
||||
pi.on("tool_call", async (event) => {
|
||||
pi.on("tool_call", async event => {
|
||||
if (!planModeEnabled) return;
|
||||
if (event.toolName !== "bash") return;
|
||||
|
||||
@@ -319,7 +318,7 @@ export default function planModeExtension(pi: ExtensionAPI) {
|
||||
if (!executionMode || todoItems.length === 0) return;
|
||||
|
||||
// Mark the first uncompleted step as done when any tool succeeds
|
||||
const nextStep = todoItems.find((t) => !t.completed);
|
||||
const nextStep = todoItems.find(t => !t.completed);
|
||||
if (nextStep) {
|
||||
nextStep.completed = true;
|
||||
updateStatus(ctx);
|
||||
@@ -328,7 +327,7 @@ export default function planModeExtension(pi: ExtensionAPI) {
|
||||
|
||||
// Filter out stale plan mode context messages from LLM context
|
||||
// This ensures the agent only sees the CURRENT state (plan mode on/off)
|
||||
pi.on("context", async (event) => {
|
||||
pi.on("context", async event => {
|
||||
// Only filter when NOT in plan mode (i.e., when executing)
|
||||
if (planModeEnabled) {
|
||||
return;
|
||||
@@ -336,7 +335,7 @@ export default function planModeExtension(pi: ExtensionAPI) {
|
||||
|
||||
// Remove any previous plan-mode-context messages
|
||||
const _beforeCount = event.messages.length;
|
||||
const filtered = event.messages.filter((m) => {
|
||||
const filtered = event.messages.filter(m => {
|
||||
if (m.role === "user" && Array.isArray(m.content)) {
|
||||
const hasOldContext = m.content.some(
|
||||
(c: { type: string; text?: string }) => c.type === "text" && c.text?.includes("[PLAN MODE ACTIVE]"),
|
||||
@@ -381,8 +380,8 @@ Do NOT attempt to make changes - just describe what you would do.`,
|
||||
}
|
||||
|
||||
if (executionMode && todoItems.length > 0) {
|
||||
const remaining = todoItems.filter((t) => !t.completed);
|
||||
const todoList = remaining.map((t) => `${t.step}. ${t.text}`).join("\n");
|
||||
const remaining = todoItems.filter(t => !t.completed);
|
||||
const todoList = remaining.map(t => `${t.step}. ${t.text}`).join("\n");
|
||||
return {
|
||||
message: {
|
||||
customType: "plan-execution-context",
|
||||
@@ -402,10 +401,10 @@ Execute each step in order.`,
|
||||
pi.on("agent_end", async (event, ctx) => {
|
||||
// In execution mode, check if all steps complete
|
||||
if (executionMode && todoItems.length > 0) {
|
||||
const allComplete = todoItems.every((t) => t.completed);
|
||||
const allComplete = todoItems.every(t => t.completed);
|
||||
if (allComplete) {
|
||||
// Show final completed list in chat
|
||||
const completedList = todoItems.map((t) => `~~${t.text}~~`).join("\n");
|
||||
const completedList = todoItems.map(t => `~~${t.text}~~`).join("\n");
|
||||
pi.sendMessage(
|
||||
{
|
||||
customType: "plan-complete",
|
||||
@@ -428,7 +427,7 @@ Execute each step in order.`,
|
||||
|
||||
// Extract todos from last message
|
||||
const messages = event.messages;
|
||||
const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant");
|
||||
const lastAssistant = [...messages].reverse().find(m => m.role === "assistant");
|
||||
if (lastAssistant && Array.isArray(lastAssistant.content)) {
|
||||
const textContent = lastAssistant.content
|
||||
.filter(
|
||||
@@ -541,7 +540,7 @@ Execute each step in order.`,
|
||||
// If no tools were called this turn, the agent was doing analysis/explanation
|
||||
// Mark the next uncompleted step as done
|
||||
if (!toolsCalledThisTurn) {
|
||||
const nextStep = todoItems.find((t) => !t.completed);
|
||||
const nextStep = todoItems.find(t => !t.completed);
|
||||
if (nextStep) {
|
||||
nextStep.completed = true;
|
||||
updateStatus(ctx);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
* proper branching - when you branch, the todo state is automatically
|
||||
* correct for that point in history.
|
||||
*/
|
||||
|
||||
import { StringEnum } from "@oh-my-pi/pi-ai";
|
||||
import type { ExtensionAPI, ExtensionContext, Theme } from "@oh-my-pi/pi-coding-agent";
|
||||
import { matchesKey, Text, truncateToWidth } from "@oh-my-pi/pi-tui";
|
||||
@@ -74,7 +73,7 @@ class TodoListComponent {
|
||||
if (this.todos.length === 0) {
|
||||
lines.push(truncateToWidth(` ${th.fg("dim", "No todos yet. Ask the agent to add some!")}`, width));
|
||||
} else {
|
||||
const done = this.todos.filter((t) => t.done).length;
|
||||
const done = this.todos.filter(t => t.done).length;
|
||||
const total = this.todos.length;
|
||||
lines.push(truncateToWidth(` ${th.fg("muted", `${done}/${total} completed`)}`, width));
|
||||
lines.push("");
|
||||
@@ -149,7 +148,7 @@ export default function (pi: ExtensionAPI) {
|
||||
{
|
||||
type: "text",
|
||||
text: todos.length
|
||||
? todos.map((t) => `[${t.done ? "x" : " "}] #${t.id}: ${t.text}`).join("\n")
|
||||
? todos.map(t => `[${t.done ? "x" : " "}] #${t.id}: ${t.text}`).join("\n")
|
||||
: "No todos",
|
||||
},
|
||||
],
|
||||
@@ -178,7 +177,7 @@ export default function (pi: ExtensionAPI) {
|
||||
details: { action: "toggle", todos: [...todos], nextId, error: "id required" } as TodoDetails,
|
||||
};
|
||||
}
|
||||
const todo = todos.find((t) => t.id === params.id);
|
||||
const todo = todos.find(t => t.id === params.id);
|
||||
if (!todo) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Todo #${params.id} not found` }],
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
* 1. Copy this file to ~/.omp/agent/extensions/ (legacy: ~/.pi/agent/extensions/) or your project's .omp/extensions/
|
||||
* 2. Use /tools to open the tool selector
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI, ExtensionContext } from "@oh-my-pi/pi-coding-agent";
|
||||
import { getSettingsListTheme } from "@oh-my-pi/pi-coding-agent";
|
||||
import { Container, type SettingItem, SettingsList } from "@oh-my-pi/pi-tui";
|
||||
@@ -71,7 +70,7 @@ export default function toolsExtension(pi: ExtensionAPI) {
|
||||
|
||||
await ctx.ui.custom((tui, theme, done) => {
|
||||
// Build settings items for each tool
|
||||
const items: SettingItem[] = allTools.map((tool) => ({
|
||||
const items: SettingItem[] = allTools.map(tool => ({
|
||||
id: tool,
|
||||
label: tool,
|
||||
currentValue: enabledTools.has(tool) ? "enabled" : "disabled",
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*
|
||||
* Requires: npm install in this directory
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import ms from "ms";
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Automatically commits changes when the agent exits.
|
||||
* Uses the last assistant message to generate a commit message.
|
||||
*/
|
||||
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function (pi: HookAPI) {
|
||||
@@ -27,7 +26,7 @@ export default function (pi: HookAPI) {
|
||||
if (Array.isArray(content)) {
|
||||
lastAssistantText = content
|
||||
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
||||
.map((c) => c.text)
|
||||
.map(c => c.text)
|
||||
.join("\n");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Prompts for confirmation before destructive session actions (clear, switch, branch).
|
||||
* Demonstrates how to cancel session events using the before_* events.
|
||||
*/
|
||||
|
||||
import type { HookAPI, SessionBeforeSwitchEvent, SessionMessageEntry } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function (pi: HookAPI) {
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
* Usage:
|
||||
* omp --hook examples/hooks/custom-compaction.ts
|
||||
*/
|
||||
|
||||
import { complete, getModel } from "@oh-my-pi/pi-ai";
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
import { convertToLlm, serializeConversation } from "@oh-my-pi/pi-coding-agent";
|
||||
@@ -89,7 +88,7 @@ ${conversationText}
|
||||
|
||||
const summary = response.content
|
||||
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
||||
.map((c) => c.text)
|
||||
.map(c => c.text)
|
||||
.join("\n");
|
||||
|
||||
if (!summary.trim()) {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Prevents session changes when there are uncommitted git changes.
|
||||
* Useful to ensure work is committed before switching context.
|
||||
*/
|
||||
|
||||
import type { HookAPI, HookContext } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
async function checkDirtyRepo(pi: HookAPI, ctx: HookContext, action: string): Promise<{ cancel: boolean } | undefined> {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
* Usage:
|
||||
* echo "Run the tests" > /tmp/agent-trigger.txt
|
||||
*/
|
||||
|
||||
import * as fs from "node:fs";
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Creates git stash checkpoints at each turn so /branch can restore code state.
|
||||
* When branching, offers to restore code to that point in history.
|
||||
*/
|
||||
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function (pi: HookAPI) {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
*
|
||||
* The generated prompt appears as a draft in the editor for review/editing.
|
||||
*/
|
||||
|
||||
import { complete, type Message } from "@oh-my-pi/pi-ai";
|
||||
import type { HookAPI, SessionEntry } from "@oh-my-pi/pi-coding-agent";
|
||||
import { BorderedLoader, convertToLlm, serializeConversation } from "@oh-my-pi/pi-coding-agent";
|
||||
@@ -62,7 +61,7 @@ export default function (pi: HookAPI) {
|
||||
const branch = ctx.sessionManager.getBranch();
|
||||
const messages = branch
|
||||
.filter((entry): entry is SessionEntry & { type: "message" } => entry.type === "message")
|
||||
.map((entry) => entry.message);
|
||||
.map(entry => entry.message);
|
||||
|
||||
if (messages.length === 0) {
|
||||
ctx.ui.notify("No conversation to hand off", "error");
|
||||
@@ -105,13 +104,13 @@ export default function (pi: HookAPI) {
|
||||
|
||||
return response.content
|
||||
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
||||
.map((c) => c.text)
|
||||
.map(c => c.text)
|
||||
.join("\n");
|
||||
};
|
||||
|
||||
doGenerate()
|
||||
.then(done)
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
console.error("Handoff generation failed:", err);
|
||||
done(null);
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Prompts for confirmation before running potentially dangerous bash commands.
|
||||
* Patterns checked: rm -rf, sudo, chmod/chown 777
|
||||
*/
|
||||
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function (pi: HookAPI) {
|
||||
@@ -14,7 +13,7 @@ export default function (pi: HookAPI) {
|
||||
if (event.toolName !== "bash") return undefined;
|
||||
|
||||
const command = event.input.command as string;
|
||||
const isDangerous = dangerousPatterns.some((p) => p.test(command));
|
||||
const isDangerous = dangerousPatterns.some(p => p.test(command));
|
||||
|
||||
if (isDangerous) {
|
||||
if (!ctx.hasUI) {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Blocks write and edit operations to protected paths.
|
||||
* Useful for preventing accidental modifications to sensitive files.
|
||||
*/
|
||||
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function (pi: HookAPI) {
|
||||
@@ -16,7 +15,7 @@ export default function (pi: HookAPI) {
|
||||
}
|
||||
|
||||
const path = event.input.path as string;
|
||||
const isProtected = protectedPaths.some((p) => path.includes(p));
|
||||
const isProtected = protectedPaths.some(p => path.includes(p));
|
||||
|
||||
if (isProtected) {
|
||||
if (ctx.hasUI) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* 2. Shows a spinner while extracting (hides editor)
|
||||
* 3. Loads the result into the editor for user to fill in answers
|
||||
*/
|
||||
|
||||
import { complete, type UserMessage } from "@oh-my-pi/pi-ai";
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
import { BorderedLoader } from "@oh-my-pi/pi-coding-agent";
|
||||
@@ -56,7 +55,7 @@ export default function (pi: HookAPI) {
|
||||
}
|
||||
const textParts = msg.content
|
||||
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
||||
.map((c) => c.text);
|
||||
.map(c => c.text);
|
||||
if (textParts.length > 0) {
|
||||
lastAssistantText = textParts.join("\n");
|
||||
break;
|
||||
@@ -96,7 +95,7 @@ export default function (pi: HookAPI) {
|
||||
|
||||
return response.content
|
||||
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
||||
.map((c) => c.text)
|
||||
.map(c => c.text)
|
||||
.join("\n");
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* Snake game hook - play snake with /snake command
|
||||
*/
|
||||
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
import { matchesKey, visibleWidth } from "@oh-my-pi/pi-tui";
|
||||
|
||||
@@ -47,7 +46,7 @@ function spawnFood(snake: Point[]): Point {
|
||||
x: Math.floor(Math.random() * GAME_WIDTH),
|
||||
y: Math.floor(Math.random() * GAME_HEIGHT),
|
||||
};
|
||||
} while (snake.some((s) => s.x === food.x && s.y === food.y));
|
||||
} while (snake.some(s => s.x === food.x && s.y === food.y));
|
||||
return food;
|
||||
}
|
||||
|
||||
@@ -127,7 +126,7 @@ class SnakeComponent {
|
||||
}
|
||||
|
||||
// Check self collision
|
||||
if (this.state.snake.some((s) => s.x === newHead.x && s.y === newHead.y)) {
|
||||
if (this.state.snake.some(s => s.x === newHead.x && s.y === newHead.y)) {
|
||||
this.state.gameOver = true;
|
||||
return;
|
||||
}
|
||||
@@ -249,7 +248,7 @@ class SnakeComponent {
|
||||
let row = "";
|
||||
for (let x = 0; x < effectiveWidth; x++) {
|
||||
const isHead = this.state.snake[0].x === x && this.state.snake[0].y === y;
|
||||
const isBody = this.state.snake.slice(1).some((s) => s.x === x && s.y === y);
|
||||
const isBody = this.state.snake.slice(1).some(s => s.x === x && s.y === y);
|
||||
const isFood = this.state.food.x === x && this.state.food.y === y;
|
||||
|
||||
if (isHead) {
|
||||
@@ -331,7 +330,7 @@ export default function (pi: HookAPI) {
|
||||
return new SnakeComponent(
|
||||
tui,
|
||||
() => done(undefined),
|
||||
(state) => {
|
||||
state => {
|
||||
// Save or clear state
|
||||
pi.appendEntry(SNAKE_SAVE_TYPE, state);
|
||||
},
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Demonstrates ctx.ui.setStatus() for displaying persistent status text in the footer.
|
||||
* Shows turn progress with themed colors.
|
||||
*/
|
||||
|
||||
import type { HookAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
export default function (pi: HookAPI) {
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
* Uses all defaults: discovers skills, hooks, tools, context files
|
||||
* from cwd and ~/.omp/agent. Model chosen from settings or first available.
|
||||
*/
|
||||
|
||||
import { createAgentSession } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
const { session } = await createAgentSession();
|
||||
|
||||
session.subscribe((event) => {
|
||||
session.subscribe(event => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
});
|
||||
|
||||
await session.prompt("What files are in the current directory?");
|
||||
session.state.messages.forEach((msg) => {
|
||||
session.state.messages.forEach(msg => {
|
||||
console.log(msg);
|
||||
});
|
||||
console.log();
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Shows how to select a specific model and thinking level.
|
||||
*/
|
||||
|
||||
import { getModel } from "@oh-my-pi/pi-ai";
|
||||
import { createAgentSession, discoverAuthStorage, discoverModels } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
@@ -27,7 +26,7 @@ if (customModel) {
|
||||
const available = modelRegistry.getAvailable();
|
||||
console.log(
|
||||
"Available models:",
|
||||
available.map((m) => `${m.provider}/${m.id}`),
|
||||
available.map(m => `${m.provider}/${m.id}`),
|
||||
);
|
||||
|
||||
if (available.length > 0) {
|
||||
@@ -38,7 +37,7 @@ if (available.length > 0) {
|
||||
modelRegistry,
|
||||
});
|
||||
|
||||
session.subscribe((event) => {
|
||||
session.subscribe(event => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Shows how to replace or modify the default system prompt.
|
||||
*/
|
||||
|
||||
import { createAgentSession, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
// Option 1: Replace prompt entirely
|
||||
@@ -13,7 +12,7 @@ Always end responses with "Arrr!"`,
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
session1.subscribe((event) => {
|
||||
session1.subscribe(event => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
@@ -25,7 +24,7 @@ console.log("\n");
|
||||
|
||||
// Option 2: Modify default prompt (receives default, returns modified)
|
||||
const { session: session2 } = await createAgentSession({
|
||||
systemPrompt: (defaultPrompt) => `${defaultPrompt}
|
||||
systemPrompt: defaultPrompt => `${defaultPrompt}
|
||||
|
||||
## Additional Instructions
|
||||
- Always be concise
|
||||
@@ -33,7 +32,7 @@ const { session: session2 } = await createAgentSession({
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
session2.subscribe((event) => {
|
||||
session2.subscribe(event => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
|
||||
@@ -4,18 +4,17 @@
|
||||
* Skills provide specialized instructions loaded into the system prompt.
|
||||
* Discover, filter, merge, or replace them.
|
||||
*/
|
||||
|
||||
import { createAgentSession, discoverSkills, SessionManager, type Skill } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
// Discover all skills from cwd/.omp/skills, ~/.omp/agent/skills, etc.
|
||||
const { skills: allSkills } = await discoverSkills();
|
||||
console.log(
|
||||
"Discovered skills:",
|
||||
allSkills.map((s) => s.name),
|
||||
allSkills.map(s => s.name),
|
||||
);
|
||||
|
||||
// Filter to specific skills
|
||||
const filteredSkills = allSkills.filter((s) => s.name.includes("browser") || s.name.includes("search"));
|
||||
const filteredSkills = allSkills.filter(s => s.name.includes("browser") || s.name.includes("search"));
|
||||
|
||||
// Or define custom skills inline
|
||||
const customSkill: Skill = {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* An extension is a TypeScript file that exports a default function:
|
||||
* export default function (pi: ExtensionAPI) { ... }
|
||||
*/
|
||||
|
||||
import { createAgentSession, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
// Extensions are loaded from disk, not passed inline to createAgentSession.
|
||||
@@ -28,7 +27,7 @@ const { session } = await createAgentSession({
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
session.subscribe((event) => {
|
||||
session.subscribe(event => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
|
||||
@@ -4,28 +4,27 @@
|
||||
* Hooks intercept agent events for logging, blocking, or modification.
|
||||
* Note: "hooks" is now called "extensions" in the API.
|
||||
*/
|
||||
|
||||
import { createAgentSession, type ExtensionFactory, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
// Logging hook (now called extension)
|
||||
const loggingHook: ExtensionFactory = (api) => {
|
||||
const loggingHook: ExtensionFactory = api => {
|
||||
api.on("agent_start", async () => {
|
||||
console.log("[Hook] Agent starting");
|
||||
});
|
||||
|
||||
api.on("tool_call", async (event) => {
|
||||
api.on("tool_call", async event => {
|
||||
console.log(`[Hook] Tool: ${event.toolName}`);
|
||||
return undefined; // Don't block
|
||||
});
|
||||
|
||||
api.on("agent_end", async (event) => {
|
||||
api.on("agent_end", async event => {
|
||||
console.log(`[Hook] Done, ${event.messages.length} messages`);
|
||||
});
|
||||
};
|
||||
|
||||
// Blocking extension (returns { block: true, reason: "..." })
|
||||
const safetyHook: ExtensionFactory = (api) => {
|
||||
api.on("tool_call", async (event) => {
|
||||
const safetyHook: ExtensionFactory = api => {
|
||||
api.on("tool_call", async event => {
|
||||
if (event.toolName === "bash") {
|
||||
const cmd = (event.input as { command?: string }).command ?? "";
|
||||
if (cmd.includes("rm -rf")) {
|
||||
@@ -42,7 +41,7 @@ const { session } = await createAgentSession({
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
});
|
||||
|
||||
session.subscribe((event) => {
|
||||
session.subscribe(event => {
|
||||
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
||||
process.stdout.write(event.assistantMessageEvent.delta);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Context files provide project-specific instructions loaded into the system prompt.
|
||||
*/
|
||||
|
||||
import { createAgentSession, discoverContextFiles, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
// Discover AGENTS.md files walking up from cwd
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* File-based templates that inject content when invoked with /templatename.
|
||||
*/
|
||||
|
||||
import {
|
||||
createAgentSession,
|
||||
discoverPromptTemplates,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* File-based commands that inject content when invoked with /commandname.
|
||||
* Note: File-based slash commands are now called "prompt templates".
|
||||
*/
|
||||
|
||||
import {
|
||||
createAgentSession,
|
||||
discoverPromptTemplates,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Configure API key resolution via AuthStorage and ModelRegistry.
|
||||
*/
|
||||
|
||||
import {
|
||||
AuthStorage,
|
||||
createAgentSession,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Override settings using SettingsManager.
|
||||
*/
|
||||
|
||||
import { createAgentSession, loadSettings, SessionManager, SettingsManager } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
// Load current settings (merged global + project)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Control session persistence: in-memory, new file, continue, or open specific.
|
||||
*/
|
||||
|
||||
import { createAgentSession, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
||||
|
||||
// In-memory (no persistence)
|
||||
|
||||
Reference in New Issue
Block a user