@phi-code-admin/phi-code 0.56.6 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,228 +1,48 @@
1
1
  # Phi Code Extensions
2
2
 
3
- This directory contains the official Phi Code extensions - a collection of TypeScript extensions that enhance the Pi coding agent with specialized capabilities. Each extension follows the Pi extension pattern (`export default function(pi: ExtensionAPI)`) and provides focused functionality for different aspects of AI-assisted development.
3
+ 9 TypeScript extensions automatically loaded at startup.
4
4
 
5
- ## Available Extensions
5
+ ## Extensions
6
6
 
7
- ### 1. 🧠 Memory Extension (`memory.ts`)
7
+ | Extension | File | Tools | Commands | Events |
8
+ |-----------|------|-------|----------|--------|
9
+ | **Memory** | `memory.ts` | `memory_search`, `memory_write`, `memory_read`, `memory_status` | — | `session_start` (auto-load AGENTS.md) |
10
+ | **Benchmark** | `benchmark.ts` | — | `/benchmark` | `session_start` (results count) |
11
+ | **Smart Router** | `smart-router.ts` | — | `/routing` | `input` (model suggestion), `session_start` |
12
+ | **Orchestrator** | `orchestrator.ts` | `orchestrate` | `/plan`, `/plans` | — |
13
+ | **Skill Loader** | `skill-loader.ts` | — | `/skills` | `input` (skill matching), `session_start` |
14
+ | **Web Search** | `web-search.ts` | `web_search` | `/search` | `session_start` (key detection) |
15
+ | **Agents** | `agents.ts` | — | `/agents` | `session_start` (agent count) |
16
+ | **Init** | `init.ts` | — | `/phi-init` | — |
8
17
 
9
- Persistent memory management for conversations and context.
18
+ ## Benchmark Categories
10
19
 
11
- **Features:**
12
- - `memory_search(query)` - Full-text search across memory files
13
- - `memory_write(content, file?)` - Write to memory files (defaults to today's date)
14
- - `memory_read(file?)` - Read specific files or list all available
15
- - Auto-loads `AGENTS.md` on session start
16
- - Creates memory directories automatically (`~/.phi/memory/`, `.phi/memory/`)
20
+ The `/benchmark` command tests models across 6 weighted categories:
17
21
 
18
- **Usage:**
19
- ```typescript
20
- // The extension automatically provides these tools to the LLM
21
- memory_search("previous bug fixes")
22
- memory_write("Important lesson learned about React hooks", "react-notes.md")
23
- memory_read("2024-03-07.md")
24
- ```
22
+ | Category | Weight | Test |
23
+ |----------|--------|------|
24
+ | Code Generation | ×2 | Write a TypeScript function from spec |
25
+ | Debugging | ×2 | Find and fix a mutation bug |
26
+ | Planning | ×2 | Create JWT auth implementation plan |
27
+ | Tool Calling | ×1 | Parse natural language to structured JSON |
28
+ | Speed | ×1 | Response latency (simple instruction following) |
29
+ | Orchestration | ×2 | Multi-step memory leak analysis |
25
30
 
26
- ### 2. 🎯 Smart Router Extension (`smart-router.ts`)
31
+ Scoring: S (80+), A (65+), B (50+), C (35+), D (<35)
27
32
 
28
- Intelligent model routing based on task analysis.
33
+ ## Memory Auto-Recall
29
34
 
30
- **Features:**
31
- - Analyzes user input to detect task types
32
- - Suggests appropriate models via notifications
33
- - Configurable routing rules via `~/.phi/agent/routing.json`
34
- - `/routing` command for configuration management
35
+ The memory extension adds prompt guidelines that instruct the model to:
36
+ 1. Search memory before answering questions about prior work or decisions
37
+ 2. Search memory when starting work on a topic
38
+ 3. Write to memory after completing important work
35
39
 
36
- **Task Categories:**
37
- - **Code tasks** (implement, create, refactor) → Coder model
38
- - **Debug tasks** (fix, bug, error) → Reasoning model
39
- - **Exploration** (read, analyze, explain) → Fast model
40
- - **Planning** (plan, design, architect) → Reasoning model
40
+ This is not forced via code — it's a prompt guideline that well-trained models follow naturally.
41
41
 
42
- **Commands:**
43
- - `/routing` - Show current configuration
44
- - `/routing enable|disable` - Toggle smart routing
45
- - `/routing notify-on|notify-off` - Toggle notifications
46
- - `/routing test` - Test routing on sample inputs
42
+ ## Setup Wizard Modes
47
43
 
48
- ### 3. 📋 Orchestrator Extension (`orchestrator.ts`)
44
+ `/phi-init` offers 3 configuration modes:
49
45
 
50
- High-level project planning and task management.
51
-
52
- **Features:**
53
- - `/plan <description>` - Create structured project plans
54
- - `orchestrate(description)` - LLM-callable planning tool
55
- - Generates spec files and TODO lists with timestamps
56
- - Automatic task breakdown and status tracking
57
-
58
- **File Output:**
59
- - `.phi/plans/spec-TIMESTAMP.md` - Project specifications
60
- - `.phi/plans/todo-TIMESTAMP.md` - Task lists with checkboxes
61
-
62
- **Commands:**
63
- - `/plan <description>` - Create a new project plan
64
- - `/plans` - List existing project plans
65
-
66
- ### 4. 🧩 Skill Loader Extension (`skill-loader.ts`)
67
-
68
- Dynamic loading and injection of specialized skills.
69
-
70
- **Features:**
71
- - Scans `~/.phi/agent/skills/` and `.phi/skills/` for skills
72
- - Keyword-based skill detection and auto-loading
73
- - `/skills` command to browse available skills
74
- - Automatic context injection when skills are relevant
75
-
76
- **Skill Structure:**
77
- ```
78
- skill-name/
79
- ├── SKILL.md # Main skill content
80
- └── (other files) # Optional supporting files
81
- ```
82
-
83
- **Commands:**
84
- - `/skills` - List all available skills
85
- - `/skills <name>` - View specific skill details
86
-
87
- ### 5. 🌐 Web Search Extension (`web-search.ts`)
88
-
89
- Internet search capabilities with multiple providers.
90
-
91
- **Features:**
92
- - `web_search(query, count?)` - LLM-accessible web search
93
- - Brave Search API integration (with `BRAVE_API_KEY`)
94
- - DuckDuckGo HTML fallback when API unavailable
95
- - `/search` command for quick searches
96
-
97
- **Setup:**
98
- ```bash
99
- # Optional: Set Brave Search API key for better results
100
- export BRAVE_API_KEY="your-api-key"
101
- ```
102
-
103
- **Commands:**
104
- - `/search <query>` - Quick web search from chat
105
-
106
- ### 6. 🏆 Benchmark Extension (`benchmark.ts`)
107
-
108
- Integrated AI model performance testing and comparison.
109
-
110
- **Features:**
111
- - `/benchmark` command for interactive testing
112
- - Fibonacci code generation test (more categories planned)
113
- - Performance metrics: time, quality, token usage
114
- - Results persistence in `~/.phi/benchmark/results.json`
115
- - Model ranking and comparison
116
-
117
- **Test Categories (V1):**
118
- - **Fibonacci** - Iterative function implementation with test cases
119
-
120
- **Commands:**
121
- - `/benchmark` - Show available options
122
- - `/benchmark <model>` - Test specific model
123
- - `/benchmark results` - View benchmark report
124
- - `/benchmark clear` - Clear all results
125
-
126
- ## Installation
127
-
128
- 1. Copy the desired extensions to your extensions directory:
129
- ```bash
130
- # Global installation
131
- cp -r packages/coding-agent/extensions/phi ~/.pi/agent/extensions/
132
-
133
- # Project-specific installation
134
- cp -r packages/coding-agent/extensions/phi .pi/extensions/
135
- ```
136
-
137
- 2. Extensions will automatically load on next Pi session start.
138
-
139
- ## Configuration
140
-
141
- ### Memory Extension
142
- - Memory files stored in `~/.phi/memory/` (global) and `.phi/memory/` (local)
143
- - No configuration required - creates directories automatically
144
-
145
- ### Smart Router Extension
146
- - Configuration: `~/.phi/agent/routing.json`
147
- - Auto-creates default config on first run
148
- - Modify patterns and model assignments as needed
149
-
150
- ### Skill Loader Extension
151
- - Skills directory: `~/.phi/agent/skills/` (global) and `.phi/skills/` (local)
152
- - Each skill is a folder containing `SKILL.md`
153
-
154
- ### Web Search Extension
155
- - Optional: Set `BRAVE_API_KEY` environment variable
156
- - Falls back to DuckDuckGo if no API key provided
157
-
158
- ### Benchmark Extension
159
- - Results saved to `~/.phi/benchmark/results.json`
160
- - No configuration required
161
-
162
- ## Development
163
-
164
- Each extension follows these conventions:
165
-
166
- ```typescript
167
- import { Type } from "@sinclair/typebox";
168
- import type { ExtensionAPI, ExtensionContext } from "phi-code";
169
-
170
- export default function extensionName(pi: ExtensionAPI) {
171
- // Register tools
172
- pi.registerTool({
173
- name: "tool_name",
174
- description: "Tool description",
175
- parameters: Type.Object({
176
- param: Type.String({ description: "Parameter description" })
177
- }),
178
- async execute(toolCallId, params, signal, onUpdate, ctx) {
179
- // Implementation
180
- }
181
- });
182
-
183
- // Register commands
184
- pi.registerCommand("command", {
185
- description: "Command description",
186
- handler: async (args, ctx) => {
187
- // Implementation
188
- }
189
- });
190
-
191
- // Event listeners
192
- pi.on("session_start", async (event, ctx) => {
193
- // Session initialization
194
- });
195
- }
196
- ```
197
-
198
- ### Guidelines
199
- - Use `@sinclair/typebox` for parameter schemas
200
- - Prefer Node.js built-in modules over external dependencies
201
- - Include JSDoc comments for all functions
202
- - Handle errors gracefully with user-friendly messages
203
- - Use `ctx.ui.notify()` for user feedback
204
-
205
- ## Future Extensions
206
-
207
- Planned extensions for future releases:
208
-
209
- - **Git Integration** - Advanced Git operations and workflow automation
210
- - **Code Review** - Automated code review and quality checking
211
- - **Documentation** - Auto-generation of docs from code
212
- - **Testing** - Test generation and coverage analysis
213
- - **Deployment** - CI/CD pipeline integration
214
- - **Monitoring** - Real-time system monitoring and alerting
215
-
216
- ## Contributing
217
-
218
- To add new extensions:
219
-
220
- 1. Create a new `.ts` file in this directory
221
- 2. Follow the existing pattern and conventions
222
- 3. Add comprehensive JSDoc documentation
223
- 4. Update this README with the new extension details
224
- 5. Test thoroughly before submitting
225
-
226
- ## License
227
-
228
- Same license as the main Phi Code project.
46
+ - **auto**: Assigns models based on public rankings and specializations (instant)
47
+ - **benchmark**: Tests available models with `/benchmark all`, then assigns best-per-category
48
+ - **manual**: Interactive prompts to choose each model assignment
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Agents Extension - Sub-agent management and visibility
3
+ *
4
+ * Provides:
5
+ * - /agents command to list all configured sub-agents
6
+ * - /agents <name> to show detailed agent info
7
+ * - Agent definitions loaded from ~/.phi/agent/agents/ and .phi/agents/
8
+ * - Model assignment visibility
9
+ */
10
+
11
+ import type { ExtensionAPI } from "phi-code";
12
+ import { readFileSync, readdirSync, existsSync, statSync } from "node:fs";
13
+ import { join, basename } from "node:path";
14
+ import { homedir } from "node:os";
15
+
16
+ interface AgentDefinition {
17
+ name: string;
18
+ description: string;
19
+ tools: string[];
20
+ model: string;
21
+ source: string; // "global", "project", "bundled"
22
+ filePath: string;
23
+ systemPrompt: string;
24
+ }
25
+
26
+ /**
27
+ * Parse YAML frontmatter from agent .md file
28
+ */
29
+ function parseAgentFile(filePath: string): AgentDefinition | null {
30
+ try {
31
+ const content = readFileSync(filePath, "utf-8");
32
+ const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
33
+
34
+ if (!fmMatch) return null;
35
+
36
+ const frontmatter = fmMatch[1];
37
+ const body = fmMatch[2].trim();
38
+
39
+ // Simple YAML parser for our frontmatter
40
+ const fields: Record<string, string> = {};
41
+ for (const line of frontmatter.split("\n")) {
42
+ const match = line.match(/^(\w+):\s*(.*)$/);
43
+ if (match) {
44
+ fields[match[1]] = match[2].trim();
45
+ }
46
+ }
47
+
48
+ if (!fields.name) return null;
49
+
50
+ return {
51
+ name: fields.name,
52
+ description: fields.description || "No description",
53
+ tools: (fields.tools || "").split(",").map(t => t.trim()).filter(Boolean),
54
+ model: fields.model || "default",
55
+ source: "unknown",
56
+ filePath,
57
+ systemPrompt: body,
58
+ };
59
+ } catch {
60
+ return null;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Scan a directory for agent .md files
66
+ */
67
+ function scanAgentDir(dir: string, source: string): AgentDefinition[] {
68
+ const agents: AgentDefinition[] = [];
69
+
70
+ if (!existsSync(dir)) return agents;
71
+
72
+ try {
73
+ const entries = readdirSync(dir);
74
+ for (const entry of entries) {
75
+ if (!entry.endsWith(".md")) continue;
76
+ const fullPath = join(dir, entry);
77
+ if (!statSync(fullPath).isFile()) continue;
78
+
79
+ const agent = parseAgentFile(fullPath);
80
+ if (agent) {
81
+ agent.source = source;
82
+ agents.push(agent);
83
+ }
84
+ }
85
+ } catch {
86
+ // Directory not readable
87
+ }
88
+
89
+ return agents;
90
+ }
91
+
92
+ export default function agentsExtension(pi: ExtensionAPI) {
93
+ /**
94
+ * Discover all agent definitions from all sources
95
+ */
96
+ function discoverAgents(): AgentDefinition[] {
97
+ const seen = new Set<string>();
98
+ const allAgents: AgentDefinition[] = [];
99
+
100
+ const addAgents = (agents: AgentDefinition[]) => {
101
+ for (const agent of agents) {
102
+ if (!seen.has(agent.name)) {
103
+ seen.add(agent.name);
104
+ allAgents.push(agent);
105
+ }
106
+ }
107
+ };
108
+
109
+ // 1. Project-local agents
110
+ addAgents(scanAgentDir(join(process.cwd(), ".phi", "agents"), "project"));
111
+
112
+ // 2. Global agents
113
+ addAgents(scanAgentDir(join(homedir(), ".phi", "agent", "agents"), "global"));
114
+
115
+ // 3. Bundled agents (shipped with package)
116
+ const bundledDir = join(__dirname, "..", "..", "..", "agents");
117
+ if (existsSync(bundledDir)) {
118
+ addAgents(scanAgentDir(bundledDir, "bundled"));
119
+ }
120
+
121
+ return allAgents;
122
+ }
123
+
124
+ /**
125
+ * /agents command
126
+ */
127
+ pi.registerCommand("agents", {
128
+ description: "List and inspect sub-agent definitions",
129
+ handler: async (args, ctx) => {
130
+ const agents = discoverAgents();
131
+ const arg = args.trim().toLowerCase();
132
+
133
+ if (agents.length === 0) {
134
+ ctx.ui.notify("No agent definitions found.\n\nCreate agent files in:\n- `.phi/agents/` (project)\n- `~/.phi/agent/agents/` (global)\n\nFormat: Markdown with YAML frontmatter (name, description, tools, model).", "info");
135
+ return;
136
+ }
137
+
138
+ // Show specific agent details
139
+ if (arg && arg !== "list") {
140
+ const agent = agents.find(a => a.name.toLowerCase() === arg);
141
+ if (!agent) {
142
+ ctx.ui.notify(`Agent "${arg}" not found. Available: ${agents.map(a => a.name).join(", ")}`, "warning");
143
+ return;
144
+ }
145
+
146
+ const detail = `**Agent: ${agent.name}**
147
+
148
+ 📝 ${agent.description}
149
+ 🤖 Model: \`${agent.model}\`
150
+ 🔧 Tools: ${agent.tools.map(t => `\`${t}\``).join(", ")}
151
+ 📁 Source: ${agent.source} (\`${agent.filePath}\`)
152
+
153
+ **System Prompt:**
154
+ \`\`\`
155
+ ${agent.systemPrompt.substring(0, 800)}${agent.systemPrompt.length > 800 ? "\n..." : ""}
156
+ \`\`\``;
157
+
158
+ ctx.ui.notify(detail, "info");
159
+ return;
160
+ }
161
+
162
+ // List all agents
163
+ let output = `**🤖 Sub-Agents (${agents.length})**\n\n`;
164
+
165
+ // Group by source
166
+ const bySource: Record<string, AgentDefinition[]> = {};
167
+ for (const agent of agents) {
168
+ const key = agent.source;
169
+ if (!bySource[key]) bySource[key] = [];
170
+ bySource[key].push(agent);
171
+ }
172
+
173
+ const sourceLabels: Record<string, string> = {
174
+ project: "📁 Project (.phi/agents/)",
175
+ global: "🏠 Global (~/.phi/agent/agents/)",
176
+ bundled: "📦 Bundled (shipped with Phi Code)",
177
+ };
178
+
179
+ for (const [source, sourceAgents] of Object.entries(bySource)) {
180
+ output += `**${sourceLabels[source] || source}**\n`;
181
+ for (const agent of sourceAgents) {
182
+ output += ` • **${agent.name}** → \`${agent.model}\`\n`;
183
+ output += ` ${agent.description}\n`;
184
+ output += ` Tools: ${agent.tools.join(", ")}\n`;
185
+ }
186
+ output += "\n";
187
+ }
188
+
189
+ output += `Use \`/agents <name>\` for detailed info on a specific agent.`;
190
+
191
+ ctx.ui.notify(output, "info");
192
+ },
193
+ });
194
+
195
+ // Session start: show agent count
196
+ pi.on("session_start", async (_event, ctx) => {
197
+ const agents = discoverAgents();
198
+ if (agents.length > 0) {
199
+ ctx.ui.notify(`🤖 ${agents.length} sub-agents available. /agents to list.`, "info");
200
+ }
201
+ });
202
+ }