a81a450e7e
Merged into tinqs/studio: - cmd/tinqs-cli/ — tinqs-cli (Go binary, from bot/cli) - cmd/tea/ — Gitea CLI tool (from tinqs/cli-tea) - services/bot/ — Bot service (from tinqs-ltd/bot on git.arikigame.com) - services/admin/ — Admin panel (from tinqs/admin) - services/team-tool/ — Team Tool (from tinqs/team-tool) - services/proxy/ — tinqs-proxy (from bot/proxy) - web/landing/ — tinqs.com website (from tinqs/website) - web/docs/ — Platform docs (from tinqs/docs) - web/blog/ — Blog (placeholder) - runner/ — Ephemeral CI runner (from tinqs/runner) All source repos will be deleted after verification.
88 lines
2.2 KiB
TypeScript
88 lines
2.2 KiB
TypeScript
/**
|
|
* Langfuse client — LLM observability.
|
|
*
|
|
* Pushes traces, spans, and generations to self-hosted Langfuse.
|
|
* Wraps every LLM call (Nova Lite, Claude, Ollama) with tracing.
|
|
*
|
|
* Usage:
|
|
* import { langfuse, traceAgent } from "@/lib/langfuse";
|
|
* const trace = traceAgent("singularity", "process-message", { space, user });
|
|
* const gen = trace.generation({ model, input, output, tokens });
|
|
* trace.update({ output: result });
|
|
*/
|
|
|
|
import { Langfuse } from "langfuse";
|
|
|
|
// Self-hosted Langfuse on Lightsail :3100
|
|
// Falls back gracefully if Langfuse is not running
|
|
const langfuse = new Langfuse({
|
|
publicKey: process.env.LANGFUSE_PUBLIC_KEY || "pk-tinqs-agents",
|
|
secretKey: process.env.LANGFUSE_SECRET_KEY || "sk-tinqs-agents-secret",
|
|
baseUrl: process.env.LANGFUSE_BASE_URL || "http://localhost:3100",
|
|
enabled: process.env.LANGFUSE_ENABLED !== "false",
|
|
});
|
|
|
|
// Flush on process exit
|
|
if (typeof process !== "undefined") {
|
|
process.on("beforeExit", async () => {
|
|
await langfuse.shutdownAsync();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Create a trace for an agent action.
|
|
*/
|
|
function traceAgent(
|
|
agentName: string,
|
|
action: string,
|
|
metadata?: Record<string, unknown>
|
|
) {
|
|
return langfuse.trace({
|
|
name: `${agentName}/${action}`,
|
|
userId: agentName,
|
|
metadata: {
|
|
...metadata,
|
|
machine: metadata?.machine || "unknown",
|
|
timestamp: new Date().toISOString(),
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log a generation (LLM call) to Langfuse.
|
|
* Call this instead of just logInference — it feeds both Langfuse + Postgres.
|
|
*/
|
|
function logGeneration(
|
|
trace: ReturnType<typeof langfuse.trace>,
|
|
opts: {
|
|
name: string;
|
|
model: string;
|
|
input: string;
|
|
output: string;
|
|
tokensIn: number;
|
|
tokensOut: number;
|
|
latencyMs: number;
|
|
costUsd?: number;
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
) {
|
|
return trace.generation({
|
|
name: opts.name,
|
|
model: opts.model,
|
|
input: opts.input,
|
|
output: opts.output,
|
|
usage: {
|
|
input: opts.tokensIn,
|
|
output: opts.tokensOut,
|
|
total: opts.tokensIn + opts.tokensOut,
|
|
},
|
|
metadata: {
|
|
latency_ms: opts.latencyMs,
|
|
cost_usd: opts.costUsd,
|
|
...opts.metadata,
|
|
},
|
|
});
|
|
}
|
|
|
|
export { langfuse, traceAgent, logGeneration };
|