@baishuyun/chat-backend 0.0.2 → 0.0.3

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/.env.example CHANGED
@@ -1,17 +1,17 @@
1
- # agent bot api key
2
- BOT_API_KEY=xxxxx
3
-
4
- # agent host
5
- AGENT_HOST=47.99.202.157
6
-
7
- # api auth key
8
- COZE_API_KEY=xxxxx
9
-
10
- # app port
11
- PORT=3001
12
-
13
- # build bot id
14
- BUILD_BOT_ID=xxxxx
15
-
16
- # fill bot id
17
- FILL_BOT_ID=xxxxx
1
+ # agent bot api key
2
+ BOT_API_KEY=xxxxx
3
+
4
+ # agent host
5
+ AGENT_HOST=47.99.202.157
6
+
7
+ # api auth key
8
+ COZE_API_KEY=xxxxx
9
+
10
+ # app port
11
+ PORT=3001
12
+
13
+ # build bot id
14
+ BUILD_BOT_ID=xxxxx
15
+
16
+ # fill bot id
17
+ FILL_BOT_ID=xxxxx
package/CHANGELOG.md CHANGED
@@ -1,9 +1,17 @@
1
- # @baishuyun/chat-backend
2
-
3
- ## 0.0.2
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies
8
- - @baishuyun/coze-provider@0.0.3
9
- - @baishuyun/types@1.0.3
1
+ # @baishuyun/chat-backend
2
+
3
+ ## 0.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @baishuyun/coze-provider@0.0.4
9
+ - @baishuyun/types@1.0.4
10
+
11
+ ## 0.0.2
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies
16
+ - @baishuyun/coze-provider@0.0.3
17
+ - @baishuyun/types@1.0.3
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
- ```
2
- npm install
3
- npm run dev
4
- ```
5
-
6
- ```
7
- open http://localhost:3000
8
- ```
1
+ ```
2
+ npm install
3
+ npm run dev
4
+ ```
5
+
6
+ ```
7
+ open http://localhost:3000
8
+ ```
package/config/default.ts CHANGED
@@ -1,35 +1,35 @@
1
- import { asyncConfig } from "config/async.js";
2
- // load async configurations
3
- const fetchRemoteConfig = async () => {
4
- return {
5
- // mock remote config
6
- foo: "bar",
7
- };
8
- };
9
-
10
- export default {
11
- app: {
12
- port: process.env.PORT || 3001,
13
- host: process.env.HOST || "localhost",
14
- },
15
- agent: {
16
- host: process.env.AGENT_HOST || "47.99.202.157",
17
-
18
- apiAuthKey: process.env.COZE_API_KEY,
19
-
20
- form: {
21
- build: {
22
- botId: process.env.BUILD_BOT_ID || "7579927677256073216",
23
- baseUrl: `http://${process.env.AGENT_HOST}/v3/`,
24
- apiKey: process.env.BOT_API_KEY, // load from env
25
- },
26
-
27
- fill: {
28
- botId: process.env.FILL_BOT_ID || "7586483957357608960",
29
- baseUrl: `http://${process.env.AGENT_HOST}/v3/`,
30
- apiKey: process.env.BOT_API_KEY, // load from env
31
- ocrApiKey: process.env.OCR_API_KEY || "", // load from env
32
- },
33
- },
34
- },
35
- };
1
+ import { asyncConfig } from "config/async.js";
2
+ // load async configurations
3
+ const fetchRemoteConfig = async () => {
4
+ return {
5
+ // mock remote config
6
+ foo: "bar",
7
+ };
8
+ };
9
+
10
+ export default {
11
+ app: {
12
+ port: process.env.PORT || 3001,
13
+ host: process.env.HOST || "localhost",
14
+ },
15
+ agent: {
16
+ host: process.env.AGENT_HOST || "47.99.202.157",
17
+
18
+ apiAuthKey: process.env.COZE_API_KEY,
19
+
20
+ form: {
21
+ build: {
22
+ botId: process.env.BUILD_BOT_ID || "7579927677256073216",
23
+ baseUrl: `http://${process.env.AGENT_HOST}/v3/`,
24
+ apiKey: process.env.BOT_API_KEY, // load from env
25
+ },
26
+
27
+ fill: {
28
+ botId: process.env.FILL_BOT_ID || "7586483957357608960",
29
+ baseUrl: `http://${process.env.AGENT_HOST}/v3/`,
30
+ apiKey: process.env.BOT_API_KEY, // load from env
31
+ ocrApiKey: process.env.OCR_API_KEY || "", // load from env
32
+ },
33
+ },
34
+ },
35
+ };
package/config/index.ts CHANGED
@@ -1,14 +1,14 @@
1
- import path from "path";
2
- import dotenv from "dotenv";
3
- import { fileURLToPath } from "url";
4
-
5
- const __filename = fileURLToPath(import.meta.url);
6
- const __dirname = path.dirname(__filename);
7
-
8
- // export const parseConfig = () => {
9
- if (process.env.NODE_ENV !== "production") {
10
- // 加载本地.env文件到process.env
11
- dotenv.config({
12
- path: path.resolve(__dirname, "../.env"),
13
- });
14
- }
1
+ import path from "path";
2
+ import dotenv from "dotenv";
3
+ import { fileURLToPath } from "url";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+
8
+ // export const parseConfig = () => {
9
+ if (process.env.NODE_ENV !== "production") {
10
+ // 加载本地.env文件到process.env
11
+ dotenv.config({
12
+ path: path.resolve(__dirname, "../.env"),
13
+ });
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baishuyun/chat-backend",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -22,8 +22,8 @@
22
22
  "parse-sse": "^0.1.0",
23
23
  "pino": "^10.1.0",
24
24
  "zod": "^4.1.13",
25
- "@baishuyun/coze-provider": "0.0.3",
26
- "@baishuyun/types": "1.0.3"
25
+ "@baishuyun/coze-provider": "0.0.4",
26
+ "@baishuyun/types": "1.0.4"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/config": "^3.3.5",
@@ -33,7 +33,7 @@
33
33
  "pino-pretty": "^13.1.3",
34
34
  "tsx": "^4.7.1",
35
35
  "typescript": "^5.8.3",
36
- "@baishuyun/typescript-config": "0.0.3"
36
+ "@baishuyun/typescript-config": "0.0.4"
37
37
  },
38
38
  "scripts": {
39
39
  "dev": "cross-env NODE_ENV=development tsx watch src/index.ts",
package/src/app/main.ts CHANGED
@@ -1,17 +1,17 @@
1
- /**
2
- * 后端应用入口
3
- */
4
-
5
- // 应用实例
6
- import app from '../config/hono.config.js';
7
-
8
- // 子路由
9
- import { createFormRouter } from '../routes/form/form.route.js';
10
-
11
- // 挂载子路由
12
- app.route('api/form', createFormRouter());
13
-
14
- // add test route
15
- app.get('/api/test', (c) => {
16
- return c.json({ message: 'Test route is working!' });
17
- });
1
+ /**
2
+ * 后端应用入口
3
+ */
4
+
5
+ // 应用实例
6
+ import app from '../config/hono.config.js';
7
+
8
+ // 子路由
9
+ import { createFormRouter } from '../routes/form/form.route.js';
10
+
11
+ // 挂载子路由
12
+ app.route('api/form', createFormRouter());
13
+
14
+ // add test route
15
+ app.get('/api/test', (c) => {
16
+ return c.json({ message: 'Test route is working!' });
17
+ });
@@ -1,47 +1,47 @@
1
- import { Hono } from "hono";
2
- import { serve } from "@hono/node-server";
3
- import config from "config";
4
- import { cors } from "hono/cors";
5
- import { logMiddleware } from "../logger/log-middleware.js";
6
- import { logger } from "../logger/index.js";
7
-
8
- /**
9
- * 公共配置层,跨域、日志等中间件配置
10
- */
11
- const app = new Hono();
12
-
13
- // Enable CORS for all routes starting with /api/
14
- app.use("/api/*", cors());
15
-
16
- // Logging middleware
17
- app.use(logMiddleware);
18
-
19
- // 全局错误处理中间件(捕获所有路由/中间件异常)
20
- app.onError((err, c) => {
21
- // 记录错误日志(error 级别,包含异常堆栈)
22
- logger.error(
23
- {
24
- err: err, // 异常对象(自动包含 stack 堆栈信息)
25
- method: c.req.method,
26
- path: c.req.path,
27
- status: 500, // 默认 500 错误
28
- },
29
- "Request failed with unhandled error",
30
- ); // 错误描述
31
-
32
- // 返回统一的 JSON 错误响应
33
- return c.json({ message: "Internal Server Error" }, 500);
34
- });
35
-
36
- serve(
37
- {
38
- fetch: app.fetch,
39
- hostname: config.get<string>("app.host") || "",
40
- port: config.get<number>("app.port") || 3001,
41
- },
42
- (info) => {
43
- logger.info(`Server is running on http://localhost:${info.port}`);
44
- },
45
- );
46
-
47
- export default app;
1
+ import { Hono } from "hono";
2
+ import { serve } from "@hono/node-server";
3
+ import config from "config";
4
+ import { cors } from "hono/cors";
5
+ import { logMiddleware } from "../logger/log-middleware.js";
6
+ import { logger } from "../logger/index.js";
7
+
8
+ /**
9
+ * 公共配置层,跨域、日志等中间件配置
10
+ */
11
+ const app = new Hono();
12
+
13
+ // Enable CORS for all routes starting with /api/
14
+ app.use("/api/*", cors());
15
+
16
+ // Logging middleware
17
+ app.use(logMiddleware);
18
+
19
+ // 全局错误处理中间件(捕获所有路由/中间件异常)
20
+ app.onError((err, c) => {
21
+ // 记录错误日志(error 级别,包含异常堆栈)
22
+ logger.error(
23
+ {
24
+ err: err, // 异常对象(自动包含 stack 堆栈信息)
25
+ method: c.req.method,
26
+ path: c.req.path,
27
+ status: 500, // 默认 500 错误
28
+ },
29
+ "Request failed with unhandled error",
30
+ ); // 错误描述
31
+
32
+ // 返回统一的 JSON 错误响应
33
+ return c.json({ message: "Internal Server Error" }, 500);
34
+ });
35
+
36
+ serve(
37
+ {
38
+ fetch: app.fetch,
39
+ hostname: config.get<string>("app.host") || "",
40
+ port: config.get<number>("app.port") || 3001,
41
+ },
42
+ (info) => {
43
+ logger.info(`Server is running on http://localhost:${info.port}`);
44
+ },
45
+ );
46
+
47
+ export default app;
@@ -1,57 +1,57 @@
1
- import { type Context } from "hono";
2
- import config from "config";
3
- import { logger } from "../../logger/index.js";
4
- import { parseImg } from "./fill/utils.js";
5
-
6
- export const uploadAttachment = async (c: Context) => {
7
- const formData = await c.req.formData();
8
- const file = formData.get("file"); // as FormData | null;
9
- // 校验文件是否存在
10
- if (!file || !(file instanceof Blob)) {
11
- return c.json({ error: "请上传有效的文件" }, 400);
12
- }
13
-
14
- const forwardFormData = new FormData();
15
- forwardFormData.append("file", file);
16
-
17
- const apiKey = config.get<string>("agent.apiAuthKey");
18
- const host = config.get<string>("agent.host");
19
- const api = `http://${host}/v1/files/upload`;
20
-
21
- logger.debug(c.body);
22
-
23
- const response = await fetch(api, {
24
- method: "POST",
25
- body: formData,
26
- headers: {
27
- // Add any auth headers
28
- Authorization: `Bearer ${apiKey}`,
29
- },
30
- });
31
-
32
- if (!response.ok) {
33
- const errorData = await response
34
- .json()
35
- .catch(() => ({ message: "上传失败" }));
36
- return c.json({
37
- error: `目标接口返回错误: ${errorData.message}`,
38
- status: response.status,
39
- });
40
- }
41
-
42
- const data = await response.json();
43
- const { url, uri, ...rest } = data?.data || {};
44
-
45
- const orcResult = await parseImg(file);
46
-
47
- return c.json({
48
- url,
49
- name: uri,
50
- contentType: file.type,
51
- parsedData: orcResult,
52
- uploadMetadata: {
53
- ...rest,
54
- orcResult,
55
- },
56
- });
57
- };
1
+ import { type Context } from "hono";
2
+ import config from "config";
3
+ import { logger } from "../../logger/index.js";
4
+ import { parseImg } from "./fill/utils.js";
5
+
6
+ export const uploadAttachment = async (c: Context) => {
7
+ const formData = await c.req.formData();
8
+ const file = formData.get("file"); // as FormData | null;
9
+ // 校验文件是否存在
10
+ if (!file || !(file instanceof Blob)) {
11
+ return c.json({ error: "请上传有效的文件" }, 400);
12
+ }
13
+
14
+ const forwardFormData = new FormData();
15
+ forwardFormData.append("file", file);
16
+
17
+ const apiKey = config.get<string>("agent.apiAuthKey");
18
+ const host = config.get<string>("agent.host");
19
+ const api = `http://${host}/v1/files/upload`;
20
+
21
+ logger.debug(c.body);
22
+
23
+ const response = await fetch(api, {
24
+ method: "POST",
25
+ body: formData,
26
+ headers: {
27
+ // Add any auth headers
28
+ Authorization: `Bearer ${apiKey}`,
29
+ },
30
+ });
31
+
32
+ if (!response.ok) {
33
+ const errorData = await response
34
+ .json()
35
+ .catch(() => ({ message: "上传失败" }));
36
+ return c.json({
37
+ error: `目标接口返回错误: ${errorData.message}`,
38
+ status: response.status,
39
+ });
40
+ }
41
+
42
+ const data = await response.json();
43
+ const { url, uri, ...rest } = data?.data || {};
44
+
45
+ const orcResult = await parseImg(file);
46
+
47
+ return c.json({
48
+ url,
49
+ name: uri,
50
+ contentType: file.type,
51
+ parsedData: orcResult,
52
+ uploadMetadata: {
53
+ ...rest,
54
+ orcResult,
55
+ },
56
+ });
57
+ };
@@ -1,40 +1,40 @@
1
- import { convertToModelMessages, streamText } from "ai";
2
- import { type Context } from "hono";
3
- import { createModel } from "./model.js";
4
- import {
5
- createFieldsJsonTransformStream,
6
- SuggestionTransformStream,
7
- } from "@baishuyun/coze-provider";
8
-
9
- /**
10
- * 搭建表单
11
- * @param c
12
- * @returns
13
- */
14
- export const buildForm = async (c: Context) => {
15
- let requestBody;
16
-
17
- try {
18
- const json = await c.req.json();
19
- requestBody = json;
20
- } catch (_) {
21
- return c.json({ error: "Invalid JSON" }, 400);
22
- }
23
-
24
- const isBuildStage = requestBody.stage === "build";
25
-
26
- const stream = streamText({
27
- model: createModel([
28
- createFieldsJsonTransformStream(isBuildStage),
29
- new SuggestionTransformStream(isBuildStage),
30
- ]),
31
- messages: convertToModelMessages(requestBody.messages),
32
- includeRawChunks: true,
33
- headers: {
34
- "x-user-stage": requestBody.stage,
35
- "x-user-id": Date.now().toString(),
36
- },
37
- });
38
-
39
- return stream.toUIMessageStreamResponse();
40
- };
1
+ import { convertToModelMessages, streamText } from "ai";
2
+ import { type Context } from "hono";
3
+ import { createModel } from "./model.js";
4
+ import {
5
+ createFieldsJsonTransformStream,
6
+ SuggestionTransformStream,
7
+ } from "@baishuyun/coze-provider";
8
+
9
+ /**
10
+ * 搭建表单
11
+ * @param c
12
+ * @returns
13
+ */
14
+ export const buildForm = async (c: Context) => {
15
+ let requestBody;
16
+
17
+ try {
18
+ const json = await c.req.json();
19
+ requestBody = json;
20
+ } catch (_) {
21
+ return c.json({ error: "Invalid JSON" }, 400);
22
+ }
23
+
24
+ const isBuildStage = requestBody.stage === "build";
25
+
26
+ const stream = streamText({
27
+ model: createModel([
28
+ createFieldsJsonTransformStream(isBuildStage),
29
+ new SuggestionTransformStream(isBuildStage),
30
+ ]),
31
+ messages: convertToModelMessages(requestBody.messages),
32
+ includeRawChunks: true,
33
+ headers: {
34
+ "x-user-stage": requestBody.stage,
35
+ "x-user-id": Date.now().toString(),
36
+ },
37
+ });
38
+
39
+ return stream.toUIMessageStreamResponse();
40
+ };
@@ -1,16 +1,16 @@
1
- import type { LanguageModelV2StreamPart } from "@ai-sdk/provider";
2
- import { createCoze } from "@baishuyun/coze-provider";
3
- import config from "config";
4
-
5
- export const createModel = (
6
- extraStreamTransformers: TransformStream<LanguageModelV2StreamPart, any>[],
7
- ) => {
8
- const coze = createCoze({
9
- apiKey: config.get<string>("agent.form.build.apiKey"),
10
- baseURL: config.get<string>("agent.form.build.baseUrl"),
11
- botId: config.get<string>("agent.form.build.botId"),
12
- extraStreamTransformers,
13
- });
14
-
15
- return coze.chat("chat");
16
- };
1
+ import type { LanguageModelV2StreamPart } from "@ai-sdk/provider";
2
+ import { createCoze } from "@baishuyun/coze-provider";
3
+ import config from "config";
4
+
5
+ export const createModel = (
6
+ extraStreamTransformers: TransformStream<LanguageModelV2StreamPart, any>[],
7
+ ) => {
8
+ const coze = createCoze({
9
+ apiKey: config.get<string>("agent.form.build.apiKey"),
10
+ baseURL: config.get<string>("agent.form.build.baseUrl"),
11
+ botId: config.get<string>("agent.form.build.botId"),
12
+ extraStreamTransformers,
13
+ });
14
+
15
+ return coze.chat("chat");
16
+ };
@@ -1,31 +1,31 @@
1
- import type { Context } from "hono";
2
- import config from "config";
3
-
4
- export const clearConversation = async (c: Context) => {
5
- let requestBody;
6
-
7
- const agentHost = config.get<string>("agent.host");
8
-
9
- const baseUrl = `http://${agentHost}/v1`;
10
- const apiKey = config.get<string>("agent.apiAuthKey");
11
-
12
- try {
13
- const json = await c.req.json();
14
- requestBody = json;
15
- } catch (_) {
16
- return c.json({ error: "Invalid JSON" }, 400);
17
- }
18
-
19
- const result = await fetch(
20
- `${baseUrl}/conversations/${requestBody.conversationId}/clear`,
21
- {
22
- method: "POST",
23
- headers: {
24
- // Add any auth headers
25
- Authorization: `Bearer ${apiKey}`,
26
- },
27
- },
28
- );
29
-
30
- return c.json(result);
31
- };
1
+ import type { Context } from "hono";
2
+ import config from "config";
3
+
4
+ export const clearConversation = async (c: Context) => {
5
+ let requestBody;
6
+
7
+ const agentHost = config.get<string>("agent.host");
8
+
9
+ const baseUrl = `http://${agentHost}/v1`;
10
+ const apiKey = config.get<string>("agent.apiAuthKey");
11
+
12
+ try {
13
+ const json = await c.req.json();
14
+ requestBody = json;
15
+ } catch (_) {
16
+ return c.json({ error: "Invalid JSON" }, 400);
17
+ }
18
+
19
+ const result = await fetch(
20
+ `${baseUrl}/conversations/${requestBody.conversationId}/clear`,
21
+ {
22
+ method: "POST",
23
+ headers: {
24
+ // Add any auth headers
25
+ Authorization: `Bearer ${apiKey}`,
26
+ },
27
+ },
28
+ );
29
+
30
+ return c.json(result);
31
+ };