Update server.js
Browse files
server.js
CHANGED
|
@@ -49,8 +49,9 @@ app.use(cors());
|
|
| 49 |
app.use(express.json({ limit: "10mb" }));
|
| 50 |
app.use(express.static(path.join(__dirname, "public")));
|
| 51 |
|
| 52 |
-
// ββ SINGLE MODEL:
|
| 53 |
-
const
|
|
|
|
| 54 |
|
| 55 |
// All model keys from the UI now map to DeepSeek β one API, no confusion
|
| 56 |
const MODELS = {
|
|
@@ -292,37 +293,47 @@ async function webSearch(query) {
|
|
| 292 |
return { answer: data.text || "", citations: data.citations || [], model: data.model || "gpt-5" };
|
| 293 |
}
|
| 294 |
|
| 295 |
-
// ββ callAI β
|
| 296 |
// system = role/task definition + original user request for context anchoring
|
| 297 |
// query = specific data for this call (file snippet, cmd results, etc.)
|
| 298 |
-
// _modelKey accepted but ignored β all calls route to
|
| 299 |
// history = [{role:"user"|"assistant", content:"..."}] β conversation transcript
|
| 300 |
-
// The HF space's build_messages() uses this to give DeepSeek full context.
|
| 301 |
-
// This is the sheet's "conversation history IS memory" pattern.
|
| 302 |
async function callAI(system, query, _modelKey, history = []) {
|
| 303 |
const userMessage = query ? `${system}\n\n${query}` : system;
|
| 304 |
|
| 305 |
-
// Sanitize history β
|
| 306 |
const safeHistory = (Array.isArray(history) ? history : [])
|
| 307 |
.filter(h => h && (h.role === "user" || h.role === "assistant") && h.content)
|
| 308 |
.slice(-20) // last 10 user+assistant pairs
|
| 309 |
.map(h => ({ role: h.role, content: String(h.content).slice(0, 800) })); // cap each turn
|
| 310 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 311 |
const payload = {
|
| 312 |
-
|
| 313 |
-
model: "deepseek",
|
| 314 |
-
system_message: "You are Cryo, a precise developer AI. Respond with valid JSON only β no markdown fences, no prose. The original user request is embedded in the message; never lose sight of it.",
|
| 315 |
-
history: safeHistory,
|
| 316 |
max_tokens: 2000,
|
| 317 |
-
|
| 318 |
-
|
| 319 |
};
|
| 320 |
|
| 321 |
-
const { data } = await axios.post(
|
| 322 |
timeout: 60000,
|
| 323 |
-
headers: {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 324 |
});
|
| 325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 326 |
return data.reply || data.text || data.message || "";
|
| 327 |
}
|
| 328 |
|
|
|
|
| 49 |
app.use(express.json({ limit: "10mb" }));
|
| 50 |
app.use(express.static(path.join(__dirname, "public")));
|
| 51 |
|
| 52 |
+
// ββ SINGLE MODEL: LongCat API (Anthropic format) ββββββββββββββββββββββββββββ
|
| 53 |
+
const LONGCAT_API_URL = "https://api.longcat.chat/anthropic/v1/messages";
|
| 54 |
+
const LONGCAT_API_KEY = "ak_2ep6ba2Ww0pn5cH09U2Mq3Eo0ez1M";
|
| 55 |
|
| 56 |
// All model keys from the UI now map to DeepSeek β one API, no confusion
|
| 57 |
const MODELS = {
|
|
|
|
| 293 |
return { answer: data.text || "", citations: data.citations || [], model: data.model || "gpt-5" };
|
| 294 |
}
|
| 295 |
|
| 296 |
+
// ββ callAI β LongCat API (Anthropic format) ββββββββββββββββββββββββββββββββ
|
| 297 |
// system = role/task definition + original user request for context anchoring
|
| 298 |
// query = specific data for this call (file snippet, cmd results, etc.)
|
| 299 |
+
// _modelKey accepted but ignored β all calls route to LongCat-Flash-Chat
|
| 300 |
// history = [{role:"user"|"assistant", content:"..."}] β conversation transcript
|
|
|
|
|
|
|
| 301 |
async function callAI(system, query, _modelKey, history = []) {
|
| 302 |
const userMessage = query ? `${system}\n\n${query}` : system;
|
| 303 |
|
| 304 |
+
// Sanitize history β Anthropic expects [{role, content}], trim to last 10 turns
|
| 305 |
const safeHistory = (Array.isArray(history) ? history : [])
|
| 306 |
.filter(h => h && (h.role === "user" || h.role === "assistant") && h.content)
|
| 307 |
.slice(-20) // last 10 user+assistant pairs
|
| 308 |
.map(h => ({ role: h.role, content: String(h.content).slice(0, 800) })); // cap each turn
|
| 309 |
|
| 310 |
+
// Build messages array: inject history then the new user message
|
| 311 |
+
const messages = [
|
| 312 |
+
...safeHistory,
|
| 313 |
+
{ role: "user", content: userMessage.slice(0, 5500) },
|
| 314 |
+
];
|
| 315 |
+
|
| 316 |
const payload = {
|
| 317 |
+
model: "LongCat-Flash-Chat",
|
|
|
|
|
|
|
|
|
|
| 318 |
max_tokens: 2000,
|
| 319 |
+
system: "You are Cryo, a precise developer AI. Respond with valid JSON only β no markdown fences, no prose. The original user request is embedded in the message; never lose sight of it.",
|
| 320 |
+
messages,
|
| 321 |
};
|
| 322 |
|
| 323 |
+
const { data } = await axios.post(LONGCAT_API_URL, payload, {
|
| 324 |
timeout: 60000,
|
| 325 |
+
headers: {
|
| 326 |
+
"Content-Type": "application/json",
|
| 327 |
+
"Authorization": `Bearer ${LONGCAT_API_KEY}`,
|
| 328 |
+
"anthropic-version": "2023-06-01",
|
| 329 |
+
},
|
| 330 |
});
|
| 331 |
|
| 332 |
+
// Anthropic format: data.content is an array of blocks
|
| 333 |
+
if (data.content && Array.isArray(data.content)) {
|
| 334 |
+
const textBlock = data.content.find(b => b.type === "text");
|
| 335 |
+
return textBlock ? textBlock.text : "";
|
| 336 |
+
}
|
| 337 |
return data.reply || data.text || data.message || "";
|
| 338 |
}
|
| 339 |
|