@kuckit/ai-module 2.0.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.
@@ -0,0 +1,7 @@
1
+ import * as _kuckit_sdk0 from "@kuckit/sdk";
2
+
3
+ //#region src/server/module.d.ts
4
+ type AIModuleConfig = Record<string, never>;
5
+ declare const kuckitModule: _kuckit_sdk0.KuckitModuleDefinition<AIModuleConfig>;
6
+ //#endregion
7
+ export { type AIModuleConfig, kuckitModule };
package/dist/index.js ADDED
@@ -0,0 +1,115 @@
1
+ import { asFunction, defineKuckitModule } from "@kuckit/sdk";
2
+ import { convertToModelMessages, streamText } from "ai";
3
+ import { Router } from "express";
4
+ import { z } from "zod";
5
+
6
+ //#region src/server/use-cases/stream-chat.ts
7
+ const makeStreamChat = ({ aiProvider, logger }) => {
8
+ return async (input) => {
9
+ logger.debug("Starting AI chat stream", { messageCount: input.messages.length });
10
+ return streamText({
11
+ model: aiProvider,
12
+ messages: convertToModelMessages(input.messages)
13
+ });
14
+ };
15
+ };
16
+
17
+ //#endregion
18
+ //#region src/server/validation/chat.schema.ts
19
+ const messagePartSchema = z.discriminatedUnion("type", [
20
+ z.object({
21
+ type: z.literal("text"),
22
+ text: z.string(),
23
+ state: z.string().optional()
24
+ }),
25
+ z.object({
26
+ type: z.literal("image"),
27
+ image: z.string()
28
+ }),
29
+ z.object({ type: z.literal("step-start") })
30
+ ]);
31
+ const uiMessageSchema = z.object({
32
+ id: z.string(),
33
+ role: z.enum([
34
+ "user",
35
+ "assistant",
36
+ "system"
37
+ ]),
38
+ content: z.string().optional(),
39
+ parts: z.array(messagePartSchema).optional()
40
+ });
41
+ const chatRequestSchema = z.object({ messages: z.array(uiMessageSchema).min(1, "At least one message is required") });
42
+
43
+ //#endregion
44
+ //#region src/server/router/ai.router.ts
45
+ const createAiRouter = () => {
46
+ const router = Router();
47
+ router.post("/chat", async (req, res) => {
48
+ const scope = req.scope;
49
+ if (!scope) {
50
+ res.status(500).json({ error: "Internal server error" });
51
+ return;
52
+ }
53
+ const { session, requestLogger: logger, streamChat } = scope.cradle;
54
+ if (!session?.user?.id) {
55
+ logger.warn("Unauthenticated AI chat request");
56
+ res.status(401).json({ error: "Authentication required" });
57
+ return;
58
+ }
59
+ const parseResult = chatRequestSchema.safeParse(req.body);
60
+ if (!parseResult.success) {
61
+ logger.warn("Invalid AI chat request", { errors: parseResult.error.flatten() });
62
+ res.status(400).json({
63
+ error: "Invalid request",
64
+ details: parseResult.error.flatten()
65
+ });
66
+ return;
67
+ }
68
+ try {
69
+ const { messages } = parseResult.data;
70
+ (await streamChat({ messages })).pipeUIMessageStreamToResponse(res);
71
+ } catch (error) {
72
+ if (!res.headersSent) {
73
+ logger.error("AI chat failed", { error });
74
+ res.status(500).json({ error: "AI chat failed" });
75
+ } else logger.error("AI chat stream failed after headers sent", { error });
76
+ }
77
+ });
78
+ return router;
79
+ };
80
+
81
+ //#endregion
82
+ //#region src/server/module.ts
83
+ const kuckitModule = defineKuckitModule({
84
+ id: "kuckit.ai",
85
+ displayName: "AI Chat",
86
+ description: "Streaming AI chat powered by Vercel AI SDK",
87
+ version: "0.1.0",
88
+ capabilities: ["nav.item", "api.public"],
89
+ async register(ctx) {
90
+ const { container } = ctx;
91
+ container.register({ streamChat: asFunction(({ aiProvider, logger }) => makeStreamChat({
92
+ aiProvider,
93
+ logger
94
+ })).scoped() });
95
+ },
96
+ registerApi(ctx) {
97
+ const aiRouter = createAiRouter();
98
+ ctx.addApiRegistration({
99
+ type: "rest-router",
100
+ name: "ai",
101
+ router: aiRouter
102
+ });
103
+ },
104
+ async onBootstrap(ctx) {
105
+ const { container } = ctx;
106
+ container.resolve("logger").info("AI Chat module initialized");
107
+ },
108
+ async onShutdown(ctx) {
109
+ const { container } = ctx;
110
+ container.resolve("logger").info("AI Chat module shutting down");
111
+ }
112
+ });
113
+
114
+ //#endregion
115
+ export { kuckitModule };
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@kuckit/ai-module",
3
+ "version": "2.0.0",
4
+ "description": "AI chat streaming module for Kuckit applications",
5
+ "type": "module",
6
+ "main": "dist/server/module.js",
7
+ "types": "dist/server/module.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/server/module.d.ts",
14
+ "default": "./dist/server/module.js"
15
+ },
16
+ "./client": {
17
+ "types": "./dist/client/index.d.ts",
18
+ "default": "./dist/client/index.js"
19
+ }
20
+ },
21
+ "kuckit": {
22
+ "id": "kuckit.ai",
23
+ "server": ".",
24
+ "client": "./client"
25
+ },
26
+ "scripts": {
27
+ "build": "tsdown",
28
+ "prepublishOnly": "npm run build && node ../../scripts/resolve-workspace-protocols.cjs && node ../../scripts/check-no-workspace-protocol.cjs"
29
+ },
30
+ "peerDependencies": {
31
+ "@kuckit/sdk": "^2.0.0",
32
+ "@kuckit/sdk-react": "^2.0.0",
33
+ "react": "^18 || ^19",
34
+ "typescript": "^5",
35
+ "express": "^4 || ^5"
36
+ },
37
+ "dependencies": {
38
+ "@ai-sdk/react": "^2.0.39",
39
+ "ai": "^5.0.49",
40
+ "zod": "^4.1.11",
41
+ "lucide-react": "^0.511.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/react": "^19.0.0",
45
+ "@types/express": "catalog:",
46
+ "tsdown": "catalog:"
47
+ }
48
+ }