pi-agent-supervisor 1.0.0 → 1.1.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.
package/src/state.ts ADDED
@@ -0,0 +1,16 @@
1
+ export interface SessionState {
2
+ toolCalls: Array<{ tool: string; timestamp: number }>;
3
+ errorCount: number;
4
+ consecutiveErrors: number;
5
+ blockedCount: number;
6
+ lastEscalation: number;
7
+ contextBudget: { used: number; total: number } | null;
8
+ }
9
+
10
+ export let state: SessionState = {
11
+ toolCalls: [], errorCount: 0, consecutiveErrors: 0, blockedCount: 0, lastEscalation: 0, contextBudget: null,
12
+ };
13
+
14
+ export function resetState() {
15
+ state = { toolCalls: [], errorCount: 0, consecutiveErrors: 0, blockedCount: 0, lastEscalation: 0, contextBudget: null };
16
+ }
@@ -0,0 +1,65 @@
1
+ import { Type } from "typebox";
2
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
3
+ import { loadConfig } from "../config";
4
+ import { getAuditLogPath, appendToAuditLog, getCurrentRate } from "../helpers";
5
+ import { state } from "../state";
6
+ import * as fs from "node:fs";
7
+
8
+ export const statusTool = {
9
+ name: "supervisor_status" as const, label: "Supervisor Status",
10
+ description: "Show supervisor session stats.",
11
+ parameters: Type.Object({}),
12
+ async execute(_id: string, _p: any, _s: any, _u: any, ctx: ExtensionContext) {
13
+ const config = loadConfig(ctx.cwd);
14
+ const rate = getCurrentRate(config);
15
+ const lines = ["🛡 Supervisor Status", "",
16
+ `📊 Tool calls: ${state.toolCalls.length} total (${rate}/min)`,
17
+ ` Rate limit: ${config.rateLimitPerMinute}/min warn, ${config.rateLimitHardBlock}/min block`,
18
+ `❌ Errors: ${state.errorCount} total, ${state.consecutiveErrors} consecutive`,
19
+ ` Escalation at: ${config.maxConsecutiveErrors}`,
20
+ `🚫 Blocked: ${state.blockedCount}`,
21
+ `📝 Audit log: ${config.enableAuditLog ? config.auditLogPath : "disabled"}`,
22
+ `🔒 Protected: ${config.protectedFiles.length} files, ${config.protectedPatterns.length} patterns`,
23
+ ];
24
+ if (state.lastEscalation > 0) lines.push(`🚨 Last escalation: ${new Date(state.lastEscalation).toISOString()}`);
25
+ return { content: [{ type: "text", text: lines.join("\n") }], details: { rate, errors: state.errorCount, blocked: state.blockedCount } };
26
+ },
27
+ };
28
+
29
+ export const logTool = {
30
+ name: "supervisor_log" as const, label: "View Audit Log",
31
+ description: "Read the supervisor audit log (read-only).",
32
+ parameters: Type.Object({ tail: Type.Optional(Type.Number({})) }),
33
+ async execute(_id: string, params: any, _s: any, _u: any, ctx: ExtensionContext) {
34
+ const config = loadConfig(ctx.cwd);
35
+ const logPath = getAuditLogPath(ctx.cwd, config);
36
+ const tail = params.tail || 50;
37
+ if (!fs.existsSync(logPath)) return { content: [{ type: "text", text: "No audit log found." }], details: {} };
38
+ const content = fs.readFileSync(logPath, "utf-8");
39
+ const lines = content.split("\n").filter(Boolean);
40
+ const recent = lines.slice(-tail).map(line => {
41
+ if (line.includes("BLOCK")) return `🚫 ${line}`;
42
+ if (line.includes("ESCALATE")) return `🚨 ${line}`;
43
+ if (line.includes("ERROR")) return `❌ ${line}`;
44
+ return ` ${line}`;
45
+ });
46
+ return { content: [{ type: "text", text: [`📝 Audit Log (last ${recent.length} of ${lines.length})`, "", ...recent].join("\n") }], details: { totalLines: lines.length } };
47
+ },
48
+ };
49
+
50
+ export const overrideTool = {
51
+ name: "supervisor_override" as const, label: "Request Override",
52
+ description: "Request human override for a blocked operation.",
53
+ parameters: Type.Object({ reason: Type.String({}), command: Type.Optional(Type.String({})) }),
54
+ async execute(_id: string, params: any, _s: any, _u: any, ctx: ExtensionContext) {
55
+ const config = loadConfig(ctx.cwd);
56
+ const cmdInfo = params.command ? `\n\nBlocked command: ${params.command}` : "";
57
+ const allowed = await ctx.ui.confirm("Supervisor Override", `Override requested${cmdInfo}\n\nReason: ${params.reason}\n\nAllow?`);
58
+ if (allowed) {
59
+ appendToAuditLog(ctx.cwd, config, `OVERRIDE allowed: ${params.reason}`);
60
+ return { content: [{ type: "text", text: "✅ Override granted." }], details: { override: true } };
61
+ }
62
+ appendToAuditLog(ctx.cwd, config, `OVERRIDE denied: ${params.reason}`);
63
+ return { content: [{ type: "text", text: "❌ Override denied." }], isError: true, details: { override: false } };
64
+ },
65
+ };