true message
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { COOKIE_NAME } from "@shared/const";
|
||||
import { z } from "zod";
|
||||
import { getDb, getNodeMetricsHistory, getLatestNodeMetrics } from "./db";
|
||||
import { getDb } from "./db";
|
||||
import { getSessionCookieOptions } from "./_core/cookies";
|
||||
import { systemRouter } from "./_core/systemRouter";
|
||||
import { publicProcedure, router, protectedProcedure } from "./_core/trpc";
|
||||
import { retryWithBackoff, isRetryableError, logRetryAttempt, DEFAULT_RETRY_CONFIG } from "./chat-resilience";
|
||||
import { checkOllamaHealth, listModels, chatCompletion } from "./ollama";
|
||||
import {
|
||||
checkGatewayHealth,
|
||||
@@ -531,24 +532,38 @@ export const appRouter = router({
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input }) => {
|
||||
// Try Go Gateway first (preferred — full Go tool-use loop)
|
||||
const gwAvailable = await isGatewayAvailable();
|
||||
if (gwAvailable) {
|
||||
const result = await gatewayChat(
|
||||
input.messages,
|
||||
input.model,
|
||||
input.maxIterations ?? 10
|
||||
);
|
||||
return { ...result, source: "gateway" as const };
|
||||
}
|
||||
// Fallback: Node.js orchestrator
|
||||
const { orchestratorChat } = await import("./orchestrator");
|
||||
const result = await orchestratorChat(
|
||||
input.messages,
|
||||
input.model,
|
||||
input.maxIterations ?? 10
|
||||
// Wrap chat with retry logic for resilience
|
||||
return retryWithBackoff(
|
||||
async () => {
|
||||
// Try Go Gateway first (preferred — full Go tool-use loop)
|
||||
const gwAvailable = await isGatewayAvailable();
|
||||
if (gwAvailable) {
|
||||
const result = await gatewayChat(
|
||||
input.messages,
|
||||
input.model,
|
||||
input.maxIterations ?? 10
|
||||
);
|
||||
return { ...result, source: "gateway" as const };
|
||||
}
|
||||
// Fallback: Node.js orchestrator
|
||||
const { orchestratorChat } = await import("./orchestrator");
|
||||
const result = await orchestratorChat(
|
||||
input.messages,
|
||||
input.model,
|
||||
input.maxIterations ?? 10
|
||||
);
|
||||
return { ...result, source: "direct" as const };
|
||||
},
|
||||
DEFAULT_RETRY_CONFIG,
|
||||
(attempt, error) => {
|
||||
if (isRetryableError(error)) {
|
||||
logRetryAttempt(attempt, error, { messageCount: input.messages.length });
|
||||
} else {
|
||||
// Non-retryable error, throw immediately
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
);
|
||||
return { ...result, source: "direct" as const };
|
||||
}),
|
||||
|
||||
// List available tools — Go Gateway first
|
||||
@@ -706,50 +721,6 @@ export const appRouter = router({
|
||||
}
|
||||
return result;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Get historical metrics for a specific container (last 60 min, sampled every 30s)
|
||||
*/
|
||||
metricsHistory: publicProcedure
|
||||
.input(z.object({ containerId: z.string() }))
|
||||
.query(async ({ input }) => {
|
||||
const history = await getNodeMetricsHistory(input.containerId, 60);
|
||||
// Return in chronological order for sparkline rendering
|
||||
const sorted = [...history].reverse();
|
||||
return {
|
||||
containerId: input.containerId,
|
||||
points: sorted.map(m => ({
|
||||
cpu: Number(m.cpuPercent),
|
||||
mem: Number(m.memUsedMb),
|
||||
ts: m.recordedAt.getTime(),
|
||||
})),
|
||||
count: sorted.length,
|
||||
};
|
||||
}),
|
||||
|
||||
/**
|
||||
* Get latest metrics snapshot for all containers (last 30 min)
|
||||
*/
|
||||
allMetricsLatest: publicProcedure.query(async () => {
|
||||
const metrics = await getLatestNodeMetrics();
|
||||
// Group by containerId, keep last 120 points each
|
||||
const grouped: Record<string, { cpu: number; mem: number; ts: number }[]> = {};
|
||||
for (const m of metrics) {
|
||||
if (!grouped[m.containerId]) grouped[m.containerId] = [];
|
||||
if (grouped[m.containerId].length < 120) {
|
||||
grouped[m.containerId].push({
|
||||
cpu: Number(m.cpuPercent),
|
||||
mem: Number(m.memUsedMb),
|
||||
ts: m.recordedAt.getTime(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Reverse each group to chronological order
|
||||
for (const id of Object.keys(grouped)) {
|
||||
grouped[id] = grouped[id].reverse();
|
||||
}
|
||||
return { byContainer: grouped, fetchedAt: new Date().toISOString() };
|
||||
}),
|
||||
}),
|
||||
});
|
||||
export type AppRouter = typeof appRouter;
|
||||
|
||||
Reference in New Issue
Block a user