Skip to content

Commit d1ffc31

Browse files
committed
sync
1 parent 622348a commit d1ffc31

File tree

6 files changed

+118
-40
lines changed

6 files changed

+118
-40
lines changed

app/schemas.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { z } from "zod";
2+
3+
// Define schema for provider.toml
4+
export const ProviderSchema = z
5+
.object({
6+
name: z.string().min(1, "Provider name cannot be empty"),
7+
})
8+
.strict();
9+
10+
// Define schema for model files
11+
export const ModelSchema = z
12+
.object({
13+
name: z.string().min(1, "Model name cannot be empty"),
14+
attachment: z.boolean().default(false).optional(),
15+
reasoning: z.boolean().default(false).optional(),
16+
cost: z.object({
17+
input: z.number().min(0, "Input price cannot be negative"),
18+
output: z.number().min(0, "Output price cannot be negative"),
19+
inputCached: z.number().min(0, "Input cached price cannot be negative"),
20+
outputCached: z.number().min(0, "Output cached price cannot be negative"),
21+
}),
22+
limit: z.object({
23+
context: z.number().min(0, "Context window must be positive"),
24+
output: z.number().min(0, "Output tokens must be positive"),
25+
}),
26+
})
27+
.strict();
28+
29+
// Define types based on schemas
30+
export type Provider = z.infer<typeof ProviderSchema>;
31+
export type Model = z.infer<typeof ModelSchema>;

app/worker.tsx

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,81 @@
11
import { Hono } from "hono";
2+
import type { Fetcher } from "@cloudflare/workers-types";
3+
import type { Model } from "./schemas";
24

3-
const app = new Hono();
5+
interface Env {
6+
ASSETS: Fetcher;
7+
}
8+
9+
// Define the API data structure
10+
interface ApiData {
11+
[providerId: string]: {
12+
name: string;
13+
models: {
14+
[modelId: string]: Model;
15+
};
16+
};
17+
}
18+
19+
// Create a typed Hono app
20+
const app = new Hono<{ Bindings: Env }>();
421

522
// Root route
6-
app.get("/", (c) => {
7-
return c.html(
8-
<html>
9-
<body>
10-
<h1>Hello World</h1>
11-
</body>
12-
</html>
13-
);
23+
app.get("/", async (c) => {
24+
try {
25+
// Get the api.json file using env.ASSETS binding
26+
const apiJsonResponse = await c.env.ASSETS.fetch(
27+
new URL("api.json", c.req.url)
28+
);
29+
if (!apiJsonResponse) {
30+
throw new Error("api.json not found");
31+
}
32+
33+
// Decode the JSON file
34+
const apiData = (await apiJsonResponse.json()) as ApiData;
35+
36+
return c.html(
37+
<html>
38+
<head>
39+
<title>API Data</title>
40+
</head>
41+
<body>
42+
<h1>API Data</h1>
43+
<table>
44+
<thead>
45+
<tr>
46+
<th>Provider</th>
47+
<th>Model</th>
48+
<th>Details</th>
49+
</tr>
50+
</thead>
51+
<tbody>
52+
{Object.entries(apiData).map(([providerId, provider]) =>
53+
Object.entries(provider.models).map(([modelId, model]) => (
54+
<tr key={`${providerId}-${modelId}`}>
55+
<td>{provider.name}</td>
56+
<td>{model.name}</td>
57+
<td>
58+
<pre>{JSON.stringify(model, null, 2)}</pre>
59+
</td>
60+
</tr>
61+
))
62+
)}
63+
</tbody>
64+
</table>
65+
</body>
66+
</html>
67+
);
68+
} catch (err) {
69+
const error = err instanceof Error ? err : new Error(String(err));
70+
return c.html(
71+
<html>
72+
<body>
73+
<h1>Error</h1>
74+
<p>{error.message}</p>
75+
</body>
76+
</html>
77+
);
78+
}
1479
});
1580

1681
// Default route - return 404 for any other path

bun.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"zod": "^3.25.51",
1111
},
1212
"devDependencies": {
13+
"@cloudflare/workers-types": "^4.20250605.0",
1314
"@types/bun": "latest",
1415
},
1516
"peerDependencies": {
@@ -18,6 +19,8 @@
1819
},
1920
},
2021
"packages": {
22+
"@cloudflare/workers-types": ["@cloudflare/[email protected]", "", {}, "sha512-e3/ZCXcpmk3jUNfq/2gyVYqeOqUhuQ0hsSdohSGscCgTkUI37QraVeCAOQtciKPDFXKOkaGGkmxg+RLYunbKuw=="],
23+
2124
"@iarna/toml": ["@iarna/[email protected]", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="],
2225

2326
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/[email protected]", "", { "dependencies": { "content-type": "^1.0.5", "cors": "^2.8.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^4.1.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-oxzMzYCkZHMntzuyerehK3fV6A2Kwh5BD6CGEJSVDU2QNEhfLOptf2X7esQgaHZXHZY0oHmMsOtIDLP71UJXgA=="],

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"type": "module",
55
"private": true,
66
"devDependencies": {
7+
"@cloudflare/workers-types": "^4.20250605.0",
78
"@types/bun": "latest"
89
},
910
"peerDependencies": {

scripts/validate

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,9 @@ import { join } from "path";
44
import { readdir, stat } from "fs/promises";
55
import { parse } from "@iarna/toml";
66
import { file } from "bun";
7+
import { ModelSchema, ProviderSchema } from "../app/schemas";
78
import { z } from "zod";
89

9-
// Define schema for provider.toml
10-
const ProviderSchema = z
11-
.object({
12-
name: z.string().min(1, "Provider name cannot be empty"),
13-
})
14-
.strict();
15-
16-
// Define schema for model files
17-
const ModelSchema = z
18-
.object({
19-
name: z.string().min(1, "Model name cannot be empty"),
20-
attachment: z.boolean().default(false).optional(),
21-
reasoning: z.boolean().default(false).optional(),
22-
cost: z.object({
23-
input: z.number().min(0, "Input price cannot be negative"),
24-
output: z.number().min(0, "Output price cannot be negative"),
25-
inputCached: z.number().min(0, "Input cached price cannot be negative"),
26-
outputCached: z.number().min(0, "Output cached price cannot be negative"),
27-
}),
28-
limit: z.object({
29-
context: z.number().min(0, "Context window must be positive"),
30-
output: z.number().min(0, "Output tokens must be positive"),
31-
}),
32-
})
33-
.strict();
34-
3510
async function validate() {
3611
const providersDir = join(import.meta.dir, "..", "providers");
3712

sst-env.d.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@
33
/* eslint-disable */
44
/* deno-fmt-ignore-file */
55

6+
import "sst"
7+
declare module "sst" {
8+
export interface Resource {
9+
}
10+
}
11+
// cloudflare
12+
import * as cloudflare from "@cloudflare/workers-types";
613
declare module "sst" {
714
export interface Resource {
8-
"MyWorker": {
9-
"type": "sst.cloudflare.Worker"
10-
"url": string
11-
}
15+
"MyWorker": cloudflare.Service
1216
}
1317
}
14-
/// <reference path="sst-env.d.ts" />
1518

1619
import "sst"
1720
export {}

0 commit comments

Comments
 (0)