-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathserver.ts
More file actions
138 lines (123 loc) · 3.5 KB
/
server.ts
File metadata and controls
138 lines (123 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import express from "express";
import { promises as fs } from "node:fs";
import path from "node:path";
import { type ApiConfig } from "../commands/dev";
import { BITTE_HISTORY_API_URL } from "../config/constants";
export async function startUIServer(
apiConfig: ApiConfig,
agentSpec: unknown,
): Promise<ReturnType<typeof express.application.listen>> {
const app = express();
app.use(
express.json({
limit: "2mb",
}),
);
// Try multiple possible paths for the static files
const possiblePaths = [
// When running in development mode
path.resolve(process.cwd(), "dist", "playground"),
// When installed as a node module
path.resolve(
process.cwd(),
"node_modules",
"make-agent",
"dist",
"playground",
),
// When running from the node_modules/.bin directory
path.resolve(process.cwd(), "..", "make-agent", "dist", "playground"),
];
let staticPath: string | undefined;
// Try each path until we find one that exists
for (const testPath of possiblePaths) {
try {
await fs.access(testPath);
const indexExists = await fs
.access(path.join(testPath, "index.html"))
.then(() => true)
.catch(() => false);
if (indexExists) {
staticPath = testPath;
break;
}
} catch {
continue;
}
}
if (!staticPath) {
throw new Error("Could not find static files directory with index.html");
}
// Serve static files with correct MIME types
app.use(
express.static(staticPath, {
setHeaders: (res, path) => {
if (path.endsWith(".css")) {
res.setHeader("Content-Type", "text/css");
}
},
}),
);
// Serve config endpoint
app.get("/api/config", async (req, res) => {
try {
const serverConfig = {
serverStartTime: new Date().toISOString(),
environment: "make-agent",
localAgent: {
pluginId: req.hostname,
accountId: "anon",
spec: agentSpec,
},
bitteApiKey: apiConfig.key,
bitteApiUrl: `${apiConfig.url}/chat`,
};
res.json(serverConfig);
} catch (error) {
res.status(500).json({ error: "Failed to fetch AI plugin spec" });
}
});
app.get("/api/history", async (req, res) => {
try {
const id = req.query.id;
if (!id) {
throw new Error("No history id on request.");
}
const url = `${BITTE_HISTORY_API_URL}?id=${id}`;
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${apiConfig.key}`,
},
});
const result = await response.json();
res.json(result);
} catch (err) {
res.status(500).json({ error: `Failed to fetch chat history: ${err}` });
}
});
// Serve index.html for all routes
app.get("*", async (req, res) => {
console.log(req.path);
const indexPath = path.join(staticPath, "index.html");
try {
const html = await fs.readFile(indexPath, "utf8");
res.setHeader("Content-Type", "text/html");
res.send(html);
} catch (err) {
res.status(404).send("Not found");
}
});
return new Promise<ReturnType<typeof app.listen>>((resolve, reject) => {
try {
const server = app.listen(apiConfig.serverPort, () => {
console.log(
`[Server] UI server listening http://localhost:${apiConfig.serverPort}`,
);
console.log("[Server] Ready to handle requests");
resolve(server);
});
} catch (error) {
reject(error);
}
});
}