@lantos1618/better-ui 0.5.0 → 0.6.0
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 +25 -2
- package/dist/agui/index.d.mts +116 -0
- package/dist/agui/index.d.ts +116 -0
- package/dist/agui/index.js +328 -0
- package/dist/agui/index.mjs +156 -0
- package/dist/auth/index.mjs +1 -1
- package/dist/chunk-CIESM3BP.mjs +33 -0
- package/dist/chunk-XDWHMRBN.mjs +159 -0
- package/dist/components/index.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/mcp/index.d.mts +13 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.js +78 -0
- package/dist/mcp/index.mjs +87 -141
- package/dist/persistence/index.mjs +1 -1
- package/dist/react/index.mjs +1 -1
- package/package.json +12 -3
- package/dist/chunk-Y6FXYEAI.mjs +0 -10
package/dist/mcp/index.mjs
CHANGED
|
@@ -1,146 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
function convert(schema) {
|
|
8
|
-
const def = schema._def;
|
|
9
|
-
const typeName = def?.typeName;
|
|
10
|
-
switch (typeName) {
|
|
11
|
-
case "ZodString":
|
|
12
|
-
return convertString(def);
|
|
13
|
-
case "ZodNumber":
|
|
14
|
-
return convertNumber(def);
|
|
15
|
-
case "ZodBoolean":
|
|
16
|
-
return { type: "boolean" };
|
|
17
|
-
case "ZodNull":
|
|
18
|
-
return { type: "null" };
|
|
19
|
-
case "ZodLiteral":
|
|
20
|
-
return { enum: [def.value] };
|
|
21
|
-
case "ZodEnum":
|
|
22
|
-
return { type: "string", enum: def.values };
|
|
23
|
-
case "ZodNativeEnum":
|
|
24
|
-
return { enum: Object.values(def.values) };
|
|
25
|
-
case "ZodObject":
|
|
26
|
-
return convertObject(def);
|
|
27
|
-
case "ZodArray":
|
|
28
|
-
return convertArray(def);
|
|
29
|
-
case "ZodOptional":
|
|
30
|
-
return convert(def.innerType);
|
|
31
|
-
case "ZodNullable": {
|
|
32
|
-
const inner = convert(def.innerType);
|
|
33
|
-
return { anyOf: [inner, { type: "null" }] };
|
|
34
|
-
}
|
|
35
|
-
case "ZodDefault":
|
|
36
|
-
return { ...convert(def.innerType), default: def.defaultValue() };
|
|
37
|
-
case "ZodUnion":
|
|
38
|
-
return { anyOf: def.options.map((o) => convert(o)) };
|
|
39
|
-
case "ZodDiscriminatedUnion":
|
|
40
|
-
return { oneOf: [...def.options.values()].map((o) => convert(o)) };
|
|
41
|
-
case "ZodRecord":
|
|
42
|
-
return {
|
|
43
|
-
type: "object",
|
|
44
|
-
additionalProperties: convert(def.valueType)
|
|
45
|
-
};
|
|
46
|
-
case "ZodTuple": {
|
|
47
|
-
const items = def.items.map((item) => convert(item));
|
|
48
|
-
return { type: "array", items: items.length === 1 ? items[0] : void 0, prefixItems: items };
|
|
49
|
-
}
|
|
50
|
-
case "ZodEffects":
|
|
51
|
-
return convert(def.schema);
|
|
52
|
-
case "ZodPipeline":
|
|
53
|
-
return convert(def.in);
|
|
54
|
-
case "ZodLazy":
|
|
55
|
-
return convert(def.getter());
|
|
56
|
-
case "ZodAny":
|
|
57
|
-
return {};
|
|
58
|
-
case "ZodUnknown":
|
|
59
|
-
return {};
|
|
60
|
-
default:
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function convertString(def) {
|
|
65
|
-
const schema = { type: "string" };
|
|
66
|
-
if (def.checks) {
|
|
67
|
-
for (const check of def.checks) {
|
|
68
|
-
switch (check.kind) {
|
|
69
|
-
case "min":
|
|
70
|
-
schema.minLength = check.value;
|
|
71
|
-
break;
|
|
72
|
-
case "max":
|
|
73
|
-
schema.maxLength = check.value;
|
|
74
|
-
break;
|
|
75
|
-
case "email":
|
|
76
|
-
schema.format = "email";
|
|
77
|
-
break;
|
|
78
|
-
case "url":
|
|
79
|
-
schema.format = "uri";
|
|
80
|
-
break;
|
|
81
|
-
case "uuid":
|
|
82
|
-
schema.format = "uuid";
|
|
83
|
-
break;
|
|
84
|
-
case "regex":
|
|
85
|
-
schema.pattern = check.regex.source;
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
if (def.description) schema.description = def.description;
|
|
91
|
-
return schema;
|
|
92
|
-
}
|
|
93
|
-
function convertNumber(def) {
|
|
94
|
-
const schema = { type: "number" };
|
|
95
|
-
if (def.checks) {
|
|
96
|
-
for (const check of def.checks) {
|
|
97
|
-
switch (check.kind) {
|
|
98
|
-
case "min":
|
|
99
|
-
schema.minimum = check.value;
|
|
100
|
-
if (check.inclusive === false) schema.exclusiveMinimum = check.value;
|
|
101
|
-
break;
|
|
102
|
-
case "max":
|
|
103
|
-
schema.maximum = check.value;
|
|
104
|
-
if (check.inclusive === false) schema.exclusiveMaximum = check.value;
|
|
105
|
-
break;
|
|
106
|
-
case "int":
|
|
107
|
-
schema.type = "integer";
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (def.description) schema.description = def.description;
|
|
113
|
-
return schema;
|
|
114
|
-
}
|
|
115
|
-
function convertObject(def) {
|
|
116
|
-
const shape = def.shape();
|
|
117
|
-
const properties = {};
|
|
118
|
-
const required = [];
|
|
119
|
-
for (const [key, value] of Object.entries(shape)) {
|
|
120
|
-
properties[key] = convert(value);
|
|
121
|
-
const fieldDef = value._def;
|
|
122
|
-
const isOptional = fieldDef?.typeName === "ZodOptional" || fieldDef?.typeName === "ZodDefault";
|
|
123
|
-
if (!isOptional) {
|
|
124
|
-
required.push(key);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
const schema = { type: "object", properties };
|
|
128
|
-
if (required.length > 0) schema.required = required;
|
|
129
|
-
if (def.description) schema.description = def.description;
|
|
130
|
-
return schema;
|
|
131
|
-
}
|
|
132
|
-
function convertArray(def) {
|
|
133
|
-
const schema = {
|
|
134
|
-
type: "array",
|
|
135
|
-
items: convert(def.type)
|
|
136
|
-
};
|
|
137
|
-
if (def.minLength) schema.minItems = def.minLength.value;
|
|
138
|
-
if (def.maxLength) schema.maxItems = def.maxLength.value;
|
|
139
|
-
if (def.description) schema.description = def.description;
|
|
140
|
-
return schema;
|
|
141
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
init_schema,
|
|
3
|
+
zodToJsonSchema
|
|
4
|
+
} from "../chunk-XDWHMRBN.mjs";
|
|
5
|
+
import "../chunk-CIESM3BP.mjs";
|
|
142
6
|
|
|
143
7
|
// src/mcp/server.ts
|
|
8
|
+
init_schema();
|
|
144
9
|
var PARSE_ERROR = -32700;
|
|
145
10
|
var INVALID_REQUEST = -32600;
|
|
146
11
|
var METHOD_NOT_FOUND = -32601;
|
|
@@ -368,6 +233,84 @@ var MCPServer = class {
|
|
|
368
233
|
return Response.json(response);
|
|
369
234
|
};
|
|
370
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Create a Streamable HTTP handler (MCP spec 2025-03-26).
|
|
238
|
+
* Supports both single JSON-RPC requests and SSE streaming for long-running operations.
|
|
239
|
+
* Compatible with Next.js route handlers, Deno, Bun, Cloudflare Workers.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```typescript
|
|
243
|
+
* // Next.js route: app/api/mcp/route.ts
|
|
244
|
+
* import { server } from '@/lib/mcp';
|
|
245
|
+
* export const POST = server.streamableHttpHandler();
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
streamableHttpHandler() {
|
|
249
|
+
return async (req) => {
|
|
250
|
+
const accept = req.headers.get("accept") || "";
|
|
251
|
+
const contentType = req.headers.get("content-type") || "";
|
|
252
|
+
if (!contentType.includes("application/json")) {
|
|
253
|
+
return Response.json(
|
|
254
|
+
{ jsonrpc: "2.0", id: null, error: { code: PARSE_ERROR, message: "Content-Type must be application/json" } },
|
|
255
|
+
{ status: 400 }
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
let message;
|
|
259
|
+
try {
|
|
260
|
+
message = await req.json();
|
|
261
|
+
} catch {
|
|
262
|
+
return Response.json(
|
|
263
|
+
{ jsonrpc: "2.0", id: null, error: { code: PARSE_ERROR, message: "Parse error" } },
|
|
264
|
+
{ status: 400 }
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
if (!message.jsonrpc || message.jsonrpc !== "2.0") {
|
|
268
|
+
return Response.json(
|
|
269
|
+
{ jsonrpc: "2.0", id: message.id ?? null, error: { code: INVALID_REQUEST, message: "Invalid JSON-RPC version" } },
|
|
270
|
+
{ status: 400 }
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
if (accept.includes("text/event-stream")) {
|
|
274
|
+
const encoder = new TextEncoder();
|
|
275
|
+
const self = this;
|
|
276
|
+
const sseStream = new ReadableStream({
|
|
277
|
+
async start(controller) {
|
|
278
|
+
try {
|
|
279
|
+
const response2 = await self.handleMessage(message);
|
|
280
|
+
if (response2) {
|
|
281
|
+
controller.enqueue(encoder.encode(`event: message
|
|
282
|
+
data: ${JSON.stringify(response2)}
|
|
283
|
+
|
|
284
|
+
`));
|
|
285
|
+
}
|
|
286
|
+
} catch (err) {
|
|
287
|
+
const errorResponse = {
|
|
288
|
+
jsonrpc: "2.0",
|
|
289
|
+
id: message.id ?? null,
|
|
290
|
+
error: { code: INTERNAL_ERROR, message: err instanceof Error ? err.message : "Internal error" }
|
|
291
|
+
};
|
|
292
|
+
controller.enqueue(encoder.encode(`event: message
|
|
293
|
+
data: ${JSON.stringify(errorResponse)}
|
|
294
|
+
|
|
295
|
+
`));
|
|
296
|
+
}
|
|
297
|
+
controller.close();
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
return new Response(sseStream, {
|
|
301
|
+
headers: {
|
|
302
|
+
"Content-Type": "text/event-stream",
|
|
303
|
+
"Cache-Control": "no-cache"
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
const response = await this.handleMessage(message);
|
|
308
|
+
if (!response) {
|
|
309
|
+
return new Response(null, { status: 204 });
|
|
310
|
+
}
|
|
311
|
+
return Response.json(response);
|
|
312
|
+
};
|
|
313
|
+
}
|
|
371
314
|
};
|
|
372
315
|
var McpError = class extends Error {
|
|
373
316
|
constructor(code, message) {
|
|
@@ -379,6 +322,9 @@ var McpError = class extends Error {
|
|
|
379
322
|
function createMCPServer(config) {
|
|
380
323
|
return new MCPServer(config);
|
|
381
324
|
}
|
|
325
|
+
|
|
326
|
+
// src/mcp/index.ts
|
|
327
|
+
init_schema();
|
|
382
328
|
export {
|
|
383
329
|
MCPServer,
|
|
384
330
|
createMCPServer,
|
package/dist/react/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lantos1618/better-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "A minimal, type-safe AI-first UI framework for building tools",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -36,6 +36,11 @@
|
|
|
36
36
|
"import": "./dist/mcp/index.mjs",
|
|
37
37
|
"require": "./dist/mcp/index.js"
|
|
38
38
|
},
|
|
39
|
+
"./agui": {
|
|
40
|
+
"types": "./dist/agui/index.d.ts",
|
|
41
|
+
"import": "./dist/agui/index.mjs",
|
|
42
|
+
"require": "./dist/agui/index.js"
|
|
43
|
+
},
|
|
39
44
|
"./theme.css": "./src/theme.css"
|
|
40
45
|
},
|
|
41
46
|
"files": [
|
|
@@ -50,7 +55,11 @@
|
|
|
50
55
|
"ai",
|
|
51
56
|
"react",
|
|
52
57
|
"tools",
|
|
53
|
-
"typescript"
|
|
58
|
+
"typescript",
|
|
59
|
+
"mcp",
|
|
60
|
+
"ag-ui",
|
|
61
|
+
"model-context-protocol",
|
|
62
|
+
"ai-tools"
|
|
54
63
|
],
|
|
55
64
|
"author": "Lyndon Leong",
|
|
56
65
|
"license": "MIT",
|
|
@@ -60,7 +69,7 @@
|
|
|
60
69
|
},
|
|
61
70
|
"scripts": {
|
|
62
71
|
"build": "npm run build:lib",
|
|
63
|
-
"build:lib": "tsup src/index.ts src/react/index.ts src/components/index.ts src/auth/index.ts src/persistence/index.ts src/mcp/index.ts --format cjs,esm --dts --clean --tsconfig tsconfig.lib.json",
|
|
72
|
+
"build:lib": "tsup src/index.ts src/react/index.ts src/components/index.ts src/auth/index.ts src/persistence/index.ts src/mcp/index.ts src/agui/index.ts --format cjs,esm --dts --clean --tsconfig tsconfig.lib.json",
|
|
64
73
|
"test": "jest",
|
|
65
74
|
"type-check": "tsc --noEmit",
|
|
66
75
|
"prepublishOnly": "npm run build:lib"
|
package/dist/chunk-Y6FXYEAI.mjs
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
__require
|
|
10
|
-
};
|