agent-relay-server 0.4.7 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/codex/plugin/.codex-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/src/index.ts +49 -52
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A lightweight HTTP message bus that lets AI coding agents talk to each other acr
|
|
|
8
8
|
|
|
9
9
|
Built for [Claude Code](https://docs.anthropic.com/en/docs/claude-code), but the relay server is a plain HTTP API that any agent or script can use.
|
|
10
10
|
|
|
11
|
-

|
|
11
|
+

|
|
12
12
|
|
|
13
13
|
## Why
|
|
14
14
|
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
REAP_INTERVAL_MS,
|
|
8
8
|
STALE_TTL_MS,
|
|
9
9
|
OFFLINE_PRUNE_MS,
|
|
10
|
-
MAX_BODY_BYTES,
|
|
11
10
|
DAY_MS,
|
|
12
11
|
VERSION,
|
|
13
12
|
} from "./config";
|
|
@@ -57,68 +56,66 @@ function startServer(): void {
|
|
|
57
56
|
if (pruned > 0) console.log(`pruned ${pruned} old message(s)`);
|
|
58
57
|
}, DAY_MS);
|
|
59
58
|
|
|
60
|
-
const publicDir = resolve(import.meta.dir, "../public");
|
|
61
|
-
const publicDirPrefix = publicDir + sep;
|
|
62
|
-
|
|
63
59
|
Bun.serve({
|
|
64
60
|
port: PORT,
|
|
65
61
|
hostname: HOST,
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
fetch: createFetchHandler({ logRequests: LOG_REQUESTS }),
|
|
63
|
+
});
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
if (!isOriginAllowed(req)) {
|
|
73
|
-
return Response.json({ error: "origin not allowed" }, { status: 403 });
|
|
74
|
-
}
|
|
65
|
+
console.log(`agent-relay ${VERSION} running on http://${HOST}:${PORT}`);
|
|
66
|
+
}
|
|
75
67
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
{ status: 413 },
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
68
|
+
export function createFetchHandler(
|
|
69
|
+
opts: { publicDir?: string; logRequests?: boolean } = {},
|
|
70
|
+
): (req: Request) => Promise<Response> {
|
|
71
|
+
const publicDir = opts.publicDir ?? resolve(import.meta.dir, "../public");
|
|
72
|
+
const publicDirPrefix = publicDir + sep;
|
|
73
|
+
const logRequests = opts.logRequests ?? false;
|
|
86
74
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
75
|
+
return async function fetch(req: Request): Promise<Response> {
|
|
76
|
+
const url = new URL(req.url);
|
|
77
|
+
|
|
78
|
+
if (req.method === "OPTIONS") {
|
|
79
|
+
return corsPreflight(req);
|
|
80
|
+
}
|
|
81
|
+
if (!isOriginAllowed(req)) {
|
|
82
|
+
return Response.json({ error: "origin not allowed" }, { status: 403 });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// API routes
|
|
86
|
+
const matched = matchRoute(req.method, url.pathname);
|
|
87
|
+
if (matched) {
|
|
88
|
+
const integrationAuth = getIntegrationAuth(req);
|
|
89
|
+
if (!isAuthorized(req)) {
|
|
90
|
+
if (!integrationAuth || !url.pathname.startsWith("/api/integrations/")) {
|
|
91
|
+
return unauthorized(req);
|
|
100
92
|
}
|
|
101
|
-
return response;
|
|
102
93
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const resolved = resolve(publicDir, `.${requested}`);
|
|
108
|
-
if (!resolved.startsWith(publicDirPrefix)) {
|
|
109
|
-
return Response.json({ error: "not found" }, { status: 404 });
|
|
94
|
+
const response = await matched.handler(req, matched.params);
|
|
95
|
+
applyCors(req, response);
|
|
96
|
+
if (logRequests && url.pathname.startsWith("/api/")) {
|
|
97
|
+
console.log(`${req.method} ${url.pathname} → ${response.status}`);
|
|
110
98
|
}
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
return response;
|
|
100
|
+
}
|
|
113
101
|
|
|
102
|
+
// Dashboard — serve static files, rejecting path traversal and directory requests
|
|
103
|
+
let requested = url.pathname === "/" ? "/index.html" : url.pathname;
|
|
104
|
+
if (requested.endsWith("/")) requested += "index.html";
|
|
105
|
+
const resolved = resolve(publicDir, `.${requested}`);
|
|
106
|
+
if (!resolved.startsWith(publicDirPrefix)) {
|
|
114
107
|
return Response.json({ error: "not found" }, { status: 404 });
|
|
115
|
-
}
|
|
116
|
-
|
|
108
|
+
}
|
|
109
|
+
const file = Bun.file(resolved);
|
|
110
|
+
if (await file.exists()) return new Response(file);
|
|
117
111
|
|
|
118
|
-
|
|
112
|
+
return Response.json({ error: "not found" }, { status: 404 });
|
|
113
|
+
};
|
|
119
114
|
}
|
|
120
115
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
116
|
+
if (import.meta.main) {
|
|
117
|
+
main().catch((error) => {
|
|
118
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
});
|
|
121
|
+
}
|