Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/actions/runAudit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async function notifyWorker(auditId: string, pdfEmail?: string) {
}
}

const ALL_ENGINES: Engine[] = ["rule", "spec", "dns", "links", "vu1nz", "claude", "openai", "gemini", "qwen", "kimi", "deepseek", "perplexity"];
const ALL_ENGINES: Engine[] = ["rule", "spec", "dns", "links", "vu1nz", "claude", "openai", "gemini", "qwen", "kimi", "deepseek", "perplexity", "fugu"];

function normalizeEngines(input: unknown, signedIn: boolean): Engine[] {
if (!signedIn) return ["rule"];
Expand Down
1 change: 1 addition & 0 deletions components/charts/engine-trend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const ENGINE_COLORS: Record<Engine, string> = {
kimi: "#ec4899",
deepseek: "#ef4444",
perplexity: "#06b6d4",
fugu: "#eab308",
};

export function EngineTrend({
Expand Down
2 changes: 1 addition & 1 deletion components/engines-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { DEFAULT_PROJECT_ENGINES, ENGINES, selectionCost, type Engine } from "@/
import { runScanForProject } from "@/app/actions/runAudit";
import { updateProjectEngines } from "@/app/actions/projects";

const ENGINE_ORDER: Engine[] = ["rule", "spec", "dns", "links", "vu1nz", "claude", "openai", "gemini", "perplexity", "qwen", "kimi", "deepseek"];
const ENGINE_ORDER: Engine[] = ["rule", "spec", "dns", "links", "vu1nz", "claude", "openai", "gemini", "perplexity", "qwen", "kimi", "deepseek", "fugu"];

export function EnginesPanel({
projectId,
Expand Down
18 changes: 18 additions & 0 deletions lib/audit/fugu-engine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { env } from "../env";
import { oaCompatAudit } from "./oa-compat-engine";
import type { ClaudeAuditResult } from "./claude-engine";

// Sakana Fugu — an orchestration model that routes each request across a
// swappable pool of frontier LLMs. Speaks the OpenAI-compatible Chat
// Completions API (Sakana also offers a Responses API, but oa-compat is
// chat-completions + streaming JSON, same as every other engine here).
// Base URL + model are env-overridable; defaults match Sakana's console.
export async function fuguAudit(targetUrl: string): Promise<ClaudeAuditResult> {
return oaCompatAudit(targetUrl, {
apiKey: env.fuguApiKey,
baseURL: env.fuguBaseUrl,
model: env.fuguModel,
providerLabel: "Sakana Fugu",
maxOutputTokens: 32_000,
});
}
10 changes: 9 additions & 1 deletion lib/credits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ export type Engine =
| "kimi"
| "gemini"
| "deepseek"
| "perplexity";
| "perplexity"
| "fugu";

export const DEFAULT_PROJECT_ENGINES: Engine[] = ["rule", "dns"];

Expand Down Expand Up @@ -166,6 +167,13 @@ export const ENGINES: Record<Engine, EngineMeta> = {
blurb:
"Web-grounded with live citations. Frames your site the way Perplexity's answer engine would surface it to users.",
},
fugu: {
label: "Sakana Fugu",
cost: SCAN_CREDITS,
available: true,
blurb:
"Sakana AI's orchestration model — routes each request across a swappable pool of frontier LLMs for a frontier-level, vendor-neutral second opinion.",
},
};

export function engineCost(engine: Engine): number {
Expand Down
6 changes: 6 additions & 0 deletions lib/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ export const env = {
moonshotApiKey: process.env.MOONSHOT_API_KEY ?? "", // Kimi
deepseekApiKey: process.env.DEEPSEEK_API_KEY ?? "",
perplexityApiKey: process.env.PERPLEXITY_API_KEY ?? "", // Sonar API
// Sakana Fugu — orchestration model, OpenAI-compatible Chat Completions.
// Base URL + model are env-overridable; defaults match Sakana's console
// (https://api.sakana.ai/v1, model "fugu"; "fugu-ultra" is the higher tier).
fuguApiKey: process.env.FUGU_API_KEY ?? "",
fuguBaseUrl: process.env.FUGU_BASE_URL ?? "https://api.sakana.ai/v1",
fuguModel: process.env.FUGU_MODEL ?? "fugu",
// DataForSEO — keyword research for Autoblog. Basic-auth credentials.
dataforseoLogin: process.env.DATAFORSEO_LOGIN ?? "",
dataforseoPassword: process.env.DATAFORSEO_PASSWORD ?? "",
Expand Down
5 changes: 4 additions & 1 deletion worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { qwenAudit } from "../lib/audit/qwen-engine";
import { kimiAudit } from "../lib/audit/kimi-engine";
import { deepseekAudit } from "../lib/audit/deepseek-engine";
import { perplexityAudit } from "../lib/audit/perplexity-engine";
import { fuguAudit } from "../lib/audit/fugu-engine";
import { toMarkdown } from "../lib/audit/markdown";
import { Resend } from "resend";
import { renderPdf, renderPdfFromHtml } from "./pdf";
Expand Down Expand Up @@ -346,7 +347,8 @@ async function processJob(job: Job) {
| "qwen"
| "kimi"
| "deepseek"
| "perplexity") ?? "rule";
| "perplexity"
| "fugu") ?? "rule";
console.log(`[worker] audit ${auditId} engine=${engine}`);

let score: number;
Expand All @@ -373,6 +375,7 @@ async function processJob(job: Job) {
kimi: kimiAudit,
deepseek: deepseekAudit,
perplexity: perplexityAudit,
fugu: fuguAudit,
} as const;

if (engine === "spec") {
Expand Down
Loading