add 11 new sub-agent types, fix model routing, add models.json
New agents (11): - chat-search, code-analysis, code-ingest, database - document-writer, home-automation, image-maker - iot-coder, iot-hardware, video-analyze, vscode-setup Fixes: - Remove broken :deepseek suffix from coder-basic, coder-pro, devops-basic, devops-pro (caused silent fallback to parent model) - Add models.json with openRouterRouting for DeepSeek, Qwen, MiniMax, Moonshot AI provider cache targeting Additions: - headroom-bridge extension (compress_for_agent tool) - models.json with provider routing config Cleanup: - Remove old pi-subagents extension (replaced by @tintinweb/pi-subagents)
This commit is contained in:
118
extensions/headroom-bridge/index.ts
Normal file
118
extensions/headroom-bridge/index.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||
import { compress } from "headroom-ai";
|
||||
|
||||
const HEADROOM_URL = "http://192.168.20.13:8787";
|
||||
const COMPRESS_MIN_CHARS = 20_000;
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
|
||||
pi.registerTool({
|
||||
name: "compress_for_agent",
|
||||
description:
|
||||
"Compress large logs, code files, or context before sending to a subagent. Saves tokens on expensive models. Call this when you have more than ~20K chars of text to delegate.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
content: {
|
||||
type: "string",
|
||||
description: "The text content to compress (logs, code, configs, error output, etc.)"
|
||||
}
|
||||
},
|
||||
required: ["content"]
|
||||
},
|
||||
execute: async (_toolCallId: string, params: { content: string }) => {
|
||||
const content = params?.content || "";
|
||||
if (!content || content.length < COMPRESS_MIN_CHARS) {
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify({
|
||||
compressed: content,
|
||||
originalLength: content.length,
|
||||
compressedLength: content.length,
|
||||
savingsPercent: "0%",
|
||||
note: "Content too small to compress (min 20K chars)"
|
||||
}, null, 2) }]
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const messages = [{ role: "user" as const, content }];
|
||||
const result = await compress(messages, {
|
||||
baseUrl: HEADROOM_URL,
|
||||
fallback: true,
|
||||
timeout: 15_000,
|
||||
});
|
||||
|
||||
if (result.messages && result.messages.length > 0) {
|
||||
const compressed = result.messages.map((m: any) => m.content).join("\n");
|
||||
const saved = result.tokensBefore > 0
|
||||
? ((result.tokensBefore - result.tokensAfter) / result.tokensBefore * 100).toFixed(0)
|
||||
: "0";
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify({
|
||||
compressed,
|
||||
originalLength: content.length,
|
||||
compressedLength: compressed.length,
|
||||
tokensBefore: result.tokensBefore,
|
||||
tokensAfter: result.tokensAfter,
|
||||
savingsPercent: `${saved}%`
|
||||
}, null, 2) }]
|
||||
};
|
||||
}
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify({
|
||||
compressed: content,
|
||||
originalLength: content.length,
|
||||
compressedLength: content.length,
|
||||
savingsPercent: "0%",
|
||||
note: "No compression applied"
|
||||
}, null, 2) }]
|
||||
};
|
||||
} catch (err: any) {
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify({
|
||||
compressed: content,
|
||||
originalLength: content.length,
|
||||
compressedLength: content.length,
|
||||
savingsPercent: "0%",
|
||||
error: err?.message || "Headroom compression failed"
|
||||
}, null, 2) }],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pi.registerTool({
|
||||
name: "check_headroom",
|
||||
description: "Check if the Headroom compression service at 192.168.20.13:8787 is reachable.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {}
|
||||
},
|
||||
execute: async () => {
|
||||
try {
|
||||
const res = await fetch(`${HEADROOM_URL}/health`, {
|
||||
method: "GET",
|
||||
signal: AbortSignal.timeout(5000)
|
||||
});
|
||||
const data = await res.json();
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify({
|
||||
status: res.ok ? "healthy" : "unhealthy",
|
||||
statusCode: res.status,
|
||||
version: data.version,
|
||||
uptime_seconds: data.uptime_seconds
|
||||
}, null, 2) }]
|
||||
};
|
||||
} catch (err: any) {
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify({
|
||||
status: "unreachable",
|
||||
error: err?.message || "Cannot reach Headroom at 192.168.20.13:8787"
|
||||
}, null, 2) }],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user