@ty_krystal/sei-ai 0.1.2 → 0.1.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/README.md +15 -0
- package/dist/README.md +15 -0
- package/dist/index.js +232 -158
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,6 +63,13 @@ sei-ai cli api-docs --keyword login --format json
|
|
|
63
63
|
- `--token`
|
|
64
64
|
- `--timeout`
|
|
65
65
|
|
|
66
|
+
环境变量加载规则:
|
|
67
|
+
|
|
68
|
+
- 启动时会自动读取当前工作目录下的 `.env.local` 和 `.env`
|
|
69
|
+
- 加载顺序为 `.env.local` 再 `.env`
|
|
70
|
+
- 已经存在的进程环境变量不会被 `.env` 覆盖
|
|
71
|
+
- 显式 CLI 参数仍然优先于环境变量
|
|
72
|
+
|
|
66
73
|
载荷输入支持:
|
|
67
74
|
|
|
68
75
|
- `--json '<payload>'`
|
|
@@ -123,6 +130,14 @@ docker compose -f apps/sei-ai-mcp/docker-compose.yml up -d --build
|
|
|
123
130
|
- `SEI_MCP_PATH`
|
|
124
131
|
- `SEI_MCP_HTTP_JSON_RESPONSE`
|
|
125
132
|
|
|
133
|
+
例如可以在项目目录写:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
SEI_BASE_URL=http://127.0.0.1:8081
|
|
137
|
+
SEI_AI_LOGIN_KEY=dev-ai-secret
|
|
138
|
+
SEI_AI_LOGIN_ROLE=admin
|
|
139
|
+
```
|
|
140
|
+
|
|
126
141
|
## 权限模型
|
|
127
142
|
|
|
128
143
|
- 未配置目标时默认拒绝。
|
package/dist/README.md
CHANGED
|
@@ -63,6 +63,13 @@ sei-ai cli api-docs --keyword login --format json
|
|
|
63
63
|
- `--token`
|
|
64
64
|
- `--timeout`
|
|
65
65
|
|
|
66
|
+
环境变量加载规则:
|
|
67
|
+
|
|
68
|
+
- 启动时会自动读取当前工作目录下的 `.env.local` 和 `.env`
|
|
69
|
+
- 加载顺序为 `.env.local` 再 `.env`
|
|
70
|
+
- 已经存在的进程环境变量不会被 `.env` 覆盖
|
|
71
|
+
- 显式 CLI 参数仍然优先于环境变量
|
|
72
|
+
|
|
66
73
|
载荷输入支持:
|
|
67
74
|
|
|
68
75
|
- `--json '<payload>'`
|
|
@@ -123,6 +130,14 @@ docker compose -f apps/sei-ai-mcp/docker-compose.yml up -d --build
|
|
|
123
130
|
- `SEI_MCP_PATH`
|
|
124
131
|
- `SEI_MCP_HTTP_JSON_RESPONSE`
|
|
125
132
|
|
|
133
|
+
例如可以在项目目录写:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
SEI_BASE_URL=http://127.0.0.1:8081
|
|
137
|
+
SEI_AI_LOGIN_KEY=dev-ai-secret
|
|
138
|
+
SEI_AI_LOGIN_ROLE=admin
|
|
139
|
+
```
|
|
140
|
+
|
|
126
141
|
## 权限模型
|
|
127
142
|
|
|
128
143
|
- 未配置目标时默认拒绝。
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { createHash, randomUUID } from "node:crypto";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
|
+
import { parseEnv } from "node:util";
|
|
6
7
|
import { createServer } from "node:http";
|
|
7
8
|
import { ZodOptional, z } from "zod";
|
|
8
9
|
import process$1 from "node:process";
|
|
@@ -49,6 +50,7 @@ var PACKAGE_NAME = "sei-ai";
|
|
|
49
50
|
var BIN_NAME = "sei-ai";
|
|
50
51
|
var SERVER_NAME = "sei-ai-mcp-server";
|
|
51
52
|
var SERVER_VERSION = "0.2.0";
|
|
53
|
+
var DEFAULT_AI_KEY = "dev-ai-secret";
|
|
52
54
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
53
55
|
var DEFAULT_LOG_LEVEL = "info";
|
|
54
56
|
var MAX_RESPONSE_TEXT = 2e4;
|
|
@@ -78,6 +80,7 @@ var DICT_FIELDS = [
|
|
|
78
80
|
var BASE_SEED_DEFAULT_ADMIN_UID = "admin";
|
|
79
81
|
var BASE_SEED_DEFAULT_ADMIN_ROLE = "admin";
|
|
80
82
|
var BASE_SEED_DEFAULT_ADMIN_PASSWORD = "123456";
|
|
83
|
+
var ACCOUNT_LOGIN_DEFAULT_CHECKCODE = "abcd";
|
|
81
84
|
var ACCOUNT_LOGIN_DEFAULT_TYPE = "login";
|
|
82
85
|
var TOKEN_CACHE_DIR_NAME = "sei-ai";
|
|
83
86
|
var TOKEN_CACHE_FILE_PREFIX = "token-";
|
|
@@ -94,6 +97,35 @@ var SeiMcpError = class extends Error {
|
|
|
94
97
|
this.details = details;
|
|
95
98
|
}
|
|
96
99
|
};
|
|
100
|
+
function isSeiMcpError(error) {
|
|
101
|
+
return error instanceof SeiMcpError;
|
|
102
|
+
}
|
|
103
|
+
function normalizeErrorMessage(error) {
|
|
104
|
+
return error instanceof Error ? error.message : "Unknown error";
|
|
105
|
+
}
|
|
106
|
+
function formatCliError(error) {
|
|
107
|
+
if (error instanceof SeiMcpError) return `[${error.code}] ${error.message}`;
|
|
108
|
+
return `[INTERNAL_ERROR] ${normalizeErrorMessage(error)}`;
|
|
109
|
+
}
|
|
110
|
+
function toErrorLogMeta(error) {
|
|
111
|
+
if (error instanceof SeiMcpError) return {
|
|
112
|
+
code: error.code,
|
|
113
|
+
message: error.message,
|
|
114
|
+
details: toJsonValue(error.details)
|
|
115
|
+
};
|
|
116
|
+
if (error instanceof Error) return {
|
|
117
|
+
message: error.message,
|
|
118
|
+
stack: error.stack ?? ""
|
|
119
|
+
};
|
|
120
|
+
return { message: normalizeErrorMessage(error) };
|
|
121
|
+
}
|
|
122
|
+
function toJsonValue(value) {
|
|
123
|
+
if (value === null) return null;
|
|
124
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
125
|
+
if (Array.isArray(value)) return value.map((item) => toJsonValue(item));
|
|
126
|
+
if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, toJsonValue(item)]));
|
|
127
|
+
return String(value);
|
|
128
|
+
}
|
|
97
129
|
//#endregion
|
|
98
130
|
//#region src/cli-helpers.ts
|
|
99
131
|
function buildDictQueryPayload(typeCode, keyword, size = 1e3) {
|
|
@@ -359,12 +391,12 @@ function createSeiClient(config, logger, fetchImpl = fetch) {
|
|
|
359
391
|
function createSeiAuthSettings(config, options = {}) {
|
|
360
392
|
return {
|
|
361
393
|
baseUrl: normalizeBaseUrl$1(options.baseUrl ?? config.baseUrl),
|
|
362
|
-
token:
|
|
363
|
-
aiKey:
|
|
394
|
+
token: firstText(options.token, config.auth.token, process.env.SEI_TOKEN),
|
|
395
|
+
aiKey: firstText(options.aiKey, config.auth.aiKey, process.env.SEI_AI_LOGIN_KEY, DEFAULT_AI_KEY),
|
|
364
396
|
role: resolveRole(options.role, config.auth.role),
|
|
365
|
-
account:
|
|
366
|
-
accountProject:
|
|
367
|
-
accountCheckcode:
|
|
397
|
+
account: firstText(options.account, config.auth.account, process.env.SEI_AI_LOGIN_ACCOUNT),
|
|
398
|
+
accountProject: firstText(options.accountProject, process.env.SEI_AI_LOGIN_ACCOUNT_PROJECT, "sys"),
|
|
399
|
+
accountCheckcode: firstText(options.accountCheckcode, process.env.SEI_AI_LOGIN_ACCOUNT_CHECKCODE, ACCOUNT_LOGIN_DEFAULT_CHECKCODE),
|
|
368
400
|
timeoutMs: normalizeTimeout(options.timeoutMs)
|
|
369
401
|
};
|
|
370
402
|
}
|
|
@@ -711,9 +743,14 @@ function normalizeTimeout(value) {
|
|
|
711
743
|
return DEFAULT_TIMEOUT_MS;
|
|
712
744
|
}
|
|
713
745
|
function resolveRole(role, fallback) {
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
746
|
+
return firstText(role, fallback, process.env.SEI_AI_LOGIN_ROLE).toLowerCase();
|
|
747
|
+
}
|
|
748
|
+
function firstText(...values) {
|
|
749
|
+
for (const value of values) {
|
|
750
|
+
const text = toText(value);
|
|
751
|
+
if (text) return text;
|
|
752
|
+
}
|
|
753
|
+
return "";
|
|
717
754
|
}
|
|
718
755
|
function toText(value) {
|
|
719
756
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -731,10 +768,10 @@ var OPENAPI_HTTP_METHODS = [
|
|
|
731
768
|
"TRACE"
|
|
732
769
|
];
|
|
733
770
|
function buildOpenApiDocSummary(openapiDoc, keyword) {
|
|
734
|
-
if (!isObject$2(openapiDoc)) throw new
|
|
771
|
+
if (!isObject$2(openapiDoc)) throw new SeiMcpError("OpenAPI 文档不是 JSON 对象", "INVALID_REQUEST");
|
|
735
772
|
const info = isObject$2(openapiDoc.info) ? openapiDoc.info : {};
|
|
736
773
|
const rawPaths = openapiDoc.paths;
|
|
737
|
-
if (!isObject$2(rawPaths)) throw new
|
|
774
|
+
if (!isObject$2(rawPaths)) throw new SeiMcpError("OpenAPI 文档缺少 paths 对象", "INVALID_REQUEST");
|
|
738
775
|
const normalizedKeyword = normalizeText(keyword).toLowerCase();
|
|
739
776
|
const items = [];
|
|
740
777
|
for (const [path, rawPathItem] of Object.entries(rawPaths)) {
|
|
@@ -880,132 +917,141 @@ function isObject$2(value) {
|
|
|
880
917
|
//#endregion
|
|
881
918
|
//#region src/cli.ts
|
|
882
919
|
async function runCli(argv, options) {
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
}
|
|
888
|
-
const settings = createSeiAuthSettings(options.config, {
|
|
889
|
-
baseUrl: toUndefined(readOption(argv, "--base-url")),
|
|
890
|
-
token: toUndefined(readOption(argv, "--token")),
|
|
891
|
-
aiKey: toUndefined(readOption(argv, "--ai-key")),
|
|
892
|
-
role: toUndefined(readOption(argv, "--role") ?? readOption(argv, "--profile")),
|
|
893
|
-
account: toUndefined(readOption(argv, "--account")),
|
|
894
|
-
accountProject: toUndefined(readOption(argv, "--account-project")),
|
|
895
|
-
accountCheckcode: toUndefined(readOption(argv, "--account-checkcode")),
|
|
896
|
-
timeoutMs: readOptionNumber(argv, "--timeout")
|
|
897
|
-
});
|
|
898
|
-
const client = createCliSeiClient(settings, options.logger, options.fetchImpl ?? fetch);
|
|
899
|
-
switch (command) {
|
|
900
|
-
case "api-docs": {
|
|
901
|
-
const summary = buildOpenApiDocSummary(await client.readApiDocs(), readOption(argv, "--keyword") ?? void 0);
|
|
902
|
-
const output = normalizeFormat(readOption(argv, "--format")) === "json" ? `${JSON.stringify(summary, null, 2)}\n` : renderOpenApiMarkdown(summary);
|
|
903
|
-
await writeOutput(readOption(argv, "--output"), output);
|
|
904
|
-
return;
|
|
905
|
-
}
|
|
906
|
-
case "call": {
|
|
907
|
-
const [method, path] = positionalAfter(argv, command, 2);
|
|
908
|
-
if (!method || !path) throw new SeiMcpError("call 需要 METHOD 和 PATH", "INVALID_PARAMS");
|
|
909
|
-
const payload = await loadPayload(argv, {});
|
|
910
|
-
printJson(await client.call(method, path, payload, {
|
|
911
|
-
allowFailure: hasFlag(argv, "--allow-failure"),
|
|
912
|
-
allowEmpty: hasFlag(argv, "--allow-empty"),
|
|
913
|
-
skipAuth: hasFlag(argv, "--no-token")
|
|
914
|
-
}));
|
|
915
|
-
return;
|
|
916
|
-
}
|
|
917
|
-
case "query": {
|
|
918
|
-
const payload = await loadPayload(argv, {});
|
|
919
|
-
printJson(await client.query(payload, { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
920
|
-
return;
|
|
921
|
-
}
|
|
922
|
-
case "save": {
|
|
923
|
-
const payload = await loadPayload(argv, {});
|
|
924
|
-
printJson(await client.save(payload, { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
925
|
-
return;
|
|
926
|
-
}
|
|
927
|
-
case "query-sql":
|
|
928
|
-
case "sql": {
|
|
929
|
-
const [sql] = positionalAfter(argv, command, 1);
|
|
930
|
-
if (!sql) throw new SeiMcpError("query-sql 需要 SQL 参数", "INVALID_PARAMS");
|
|
931
|
-
printJson(await client.querySql(sql, readOptionNumber(argv, "--page"), readOptionNumber(argv, "--size"), { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
932
|
-
return;
|
|
933
|
-
}
|
|
934
|
-
case "dict-list": {
|
|
935
|
-
const payload = buildDictQueryPayload(readOption(argv, "--type") ?? void 0, readOption(argv, "--keyword") ?? void 0, readOptionNumber(argv, "--size") ?? 1e3);
|
|
936
|
-
const response = await client.query(payload, { allowFailure: hasFlag(argv, "--allow-failure") });
|
|
937
|
-
if (!hasFlag(argv, "--flat") && isObject$1(response) && isObject$1(response.data) && Array.isArray(response.data.rows)) response.data.tree = buildDictTree(response.data.rows);
|
|
938
|
-
printJson(response);
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
case "dict-add-category": {
|
|
942
|
-
const [typeCode, name] = positionalAfter(argv, command, 2);
|
|
943
|
-
if (!typeCode || !name) throw new SeiMcpError("dict-add-category 需要 type_code 和 name", "INVALID_PARAMS");
|
|
944
|
-
const payload = buildDictSavePayload(buildDictCategoryRow({
|
|
945
|
-
body: readOption(argv, "--body") ?? void 0,
|
|
946
|
-
code: readOption(argv, "--code") ?? void 0,
|
|
947
|
-
ctype: readOption(argv, "--ctype") ?? void 0,
|
|
948
|
-
dictFlag: readOptionInteger(argv, "--dict-flag"),
|
|
949
|
-
ename: readOption(argv, "--ename") ?? void 0,
|
|
950
|
-
memo: readOption(argv, "--memo") ?? void 0,
|
|
951
|
-
name,
|
|
952
|
-
sort: readOptionInteger(argv, "--sort"),
|
|
953
|
-
sysid: readOption(argv, "--sysid") ?? void 0,
|
|
954
|
-
typeCode,
|
|
955
|
-
uuid: readOption(argv, "--uuid") ?? void 0
|
|
956
|
-
}));
|
|
957
|
-
printJson(await client.save(payload, { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
958
|
-
return;
|
|
959
|
-
}
|
|
960
|
-
case "dict-add-item": {
|
|
961
|
-
const [typeCode, code, name] = positionalAfter(argv, command, 3);
|
|
962
|
-
if (!typeCode || !code || !name) throw new SeiMcpError("dict-add-item 需要 type_code、code 和 name", "INVALID_PARAMS");
|
|
963
|
-
const payload = buildDictSavePayload(buildDictItemRow({
|
|
964
|
-
body: readOption(argv, "--body") ?? void 0,
|
|
965
|
-
code,
|
|
966
|
-
ctype: readOption(argv, "--ctype") ?? void 0,
|
|
967
|
-
dictFlag: readOptionInteger(argv, "--dict-flag"),
|
|
968
|
-
ename: readOption(argv, "--ename") ?? void 0,
|
|
969
|
-
memo: readOption(argv, "--memo") ?? void 0,
|
|
970
|
-
name,
|
|
971
|
-
parent: readOption(argv, "--parent") ?? void 0,
|
|
972
|
-
sort: readOptionInteger(argv, "--sort"),
|
|
973
|
-
sysid: readOption(argv, "--sysid") ?? void 0,
|
|
974
|
-
typeCode,
|
|
975
|
-
uuid: readOption(argv, "--uuid") ?? void 0
|
|
976
|
-
}));
|
|
977
|
-
printJson(await client.save(payload, { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
920
|
+
try {
|
|
921
|
+
const command = firstPositional(argv);
|
|
922
|
+
if (!command || isHelpFlag(command) || hasFlag(argv, "--help") || hasFlag(argv, "-h")) {
|
|
923
|
+
process.stdout.write(`${renderCliHelp()}\n`);
|
|
978
924
|
return;
|
|
979
925
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
926
|
+
const settings = createSeiAuthSettings(options.config, {
|
|
927
|
+
baseUrl: toUndefined(readOption(argv, "--base-url")),
|
|
928
|
+
token: toUndefined(readOption(argv, "--token")),
|
|
929
|
+
aiKey: toUndefined(readOption(argv, "--ai-key")),
|
|
930
|
+
role: toUndefined(readOption(argv, "--role") ?? readOption(argv, "--profile")),
|
|
931
|
+
account: toUndefined(readOption(argv, "--account")),
|
|
932
|
+
accountProject: toUndefined(readOption(argv, "--account-project")),
|
|
933
|
+
accountCheckcode: toUndefined(readOption(argv, "--account-checkcode")),
|
|
934
|
+
timeoutMs: readOptionNumber(argv, "--timeout")
|
|
935
|
+
});
|
|
936
|
+
const client = createCliSeiClient(settings, options.logger, options.fetchImpl ?? fetch);
|
|
937
|
+
switch (command) {
|
|
938
|
+
case "api-docs": {
|
|
939
|
+
const summary = buildOpenApiDocSummary(await client.readApiDocs(), readOption(argv, "--keyword") ?? void 0);
|
|
940
|
+
const output = normalizeFormat(readOption(argv, "--format")) === "json" ? `${JSON.stringify(summary, null, 2)}\n` : renderOpenApiMarkdown(summary);
|
|
941
|
+
await writeOutput(readOption(argv, "--output"), output);
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
case "call": {
|
|
945
|
+
const [method, path] = positionalAfter(argv, command, 2);
|
|
946
|
+
if (!method || !path) throw new SeiMcpError("call 需要 METHOD 和 PATH", "INVALID_PARAMS");
|
|
947
|
+
const payload = await loadPayload(argv, {});
|
|
948
|
+
printJson(await client.call(method, path, payload, {
|
|
949
|
+
allowFailure: hasFlag(argv, "--allow-failure"),
|
|
950
|
+
allowEmpty: hasFlag(argv, "--allow-empty"),
|
|
951
|
+
skipAuth: hasFlag(argv, "--no-token")
|
|
952
|
+
}));
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
case "query": {
|
|
956
|
+
const payload = await loadPayload(argv, {});
|
|
957
|
+
printJson(await client.query(payload, { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
case "save": {
|
|
961
|
+
const payload = await loadPayload(argv, {});
|
|
962
|
+
printJson(await client.save(payload, { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
case "query-sql":
|
|
966
|
+
case "sql": {
|
|
967
|
+
const [sql] = positionalAfter(argv, command, 1);
|
|
968
|
+
if (!sql) throw new SeiMcpError("query-sql 需要 SQL 参数", "INVALID_PARAMS");
|
|
969
|
+
printJson(await client.querySql(sql, readOptionNumber(argv, "--page"), readOptionNumber(argv, "--size"), { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
case "dict-list": {
|
|
973
|
+
const payload = buildDictQueryPayload(readOption(argv, "--type") ?? void 0, readOption(argv, "--keyword") ?? void 0, readOptionNumber(argv, "--size") ?? 1e3);
|
|
974
|
+
const response = await client.query(payload, { allowFailure: hasFlag(argv, "--allow-failure") });
|
|
975
|
+
if (!hasFlag(argv, "--flat") && isObject$1(response) && isObject$1(response.data) && Array.isArray(response.data.rows)) response.data.tree = buildDictTree(response.data.rows);
|
|
976
|
+
printJson(response);
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
case "dict-add-category": {
|
|
980
|
+
const [typeCode, name] = positionalAfter(argv, command, 2);
|
|
981
|
+
if (!typeCode || !name) throw new SeiMcpError("dict-add-category 需要 type_code 和 name", "INVALID_PARAMS");
|
|
982
|
+
const payload = buildDictSavePayload(buildDictCategoryRow({
|
|
983
|
+
body: readOption(argv, "--body") ?? void 0,
|
|
984
|
+
code: readOption(argv, "--code") ?? void 0,
|
|
985
|
+
ctype: readOption(argv, "--ctype") ?? void 0,
|
|
986
|
+
dictFlag: readOptionInteger(argv, "--dict-flag"),
|
|
987
|
+
ename: readOption(argv, "--ename") ?? void 0,
|
|
988
|
+
memo: readOption(argv, "--memo") ?? void 0,
|
|
989
|
+
name,
|
|
990
|
+
sort: readOptionInteger(argv, "--sort"),
|
|
991
|
+
sysid: readOption(argv, "--sysid") ?? void 0,
|
|
992
|
+
typeCode,
|
|
993
|
+
uuid: readOption(argv, "--uuid") ?? void 0
|
|
994
|
+
}));
|
|
995
|
+
printJson(await client.save(payload, { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
case "dict-add-item": {
|
|
999
|
+
const [typeCode, code, name] = positionalAfter(argv, command, 3);
|
|
1000
|
+
if (!typeCode || !code || !name) throw new SeiMcpError("dict-add-item 需要 type_code、code 和 name", "INVALID_PARAMS");
|
|
1001
|
+
const payload = buildDictSavePayload(buildDictItemRow({
|
|
1002
|
+
body: readOption(argv, "--body") ?? void 0,
|
|
1003
|
+
code,
|
|
1004
|
+
ctype: readOption(argv, "--ctype") ?? void 0,
|
|
1005
|
+
dictFlag: readOptionInteger(argv, "--dict-flag"),
|
|
1006
|
+
ename: readOption(argv, "--ename") ?? void 0,
|
|
1007
|
+
memo: readOption(argv, "--memo") ?? void 0,
|
|
1008
|
+
name,
|
|
1009
|
+
parent: readOption(argv, "--parent") ?? void 0,
|
|
1010
|
+
sort: readOptionInteger(argv, "--sort"),
|
|
1011
|
+
sysid: readOption(argv, "--sysid") ?? void 0,
|
|
1012
|
+
typeCode,
|
|
1013
|
+
uuid: readOption(argv, "--uuid") ?? void 0
|
|
1014
|
+
}));
|
|
1015
|
+
printJson(await client.save(payload, { allowFailure: hasFlag(argv, "--allow-failure") }));
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
case "init-base-data": {
|
|
1019
|
+
const sqlFile = resolveBaseSeedSqlPath(readOption(argv, "--sql-file"));
|
|
1020
|
+
const statements = splitSqlStatements(removeSqlCommentLines(renderBaseSeedSql(await readFile(sqlFile, "utf8"), buildBaseSeedSqlVars({
|
|
1021
|
+
adminName: readOption(argv, "--admin-name") ?? void 0,
|
|
1022
|
+
adminPassword: readOption(argv, "--admin-password") ?? void 0,
|
|
1023
|
+
adminRole: readOption(argv, "--admin-role") ?? void 0,
|
|
1024
|
+
adminRoleName: readOption(argv, "--admin-role-name") ?? void 0,
|
|
1025
|
+
adminUid: readOption(argv, "--admin-uid") ?? void 0,
|
|
1026
|
+
resetAdminPassword: hasFlag(argv, "--reset-admin-password"),
|
|
1027
|
+
sysid: readOption(argv, "--sysid") ?? void 0
|
|
1028
|
+
}))));
|
|
1029
|
+
if (statements.length === 0) throw new SeiMcpError("初始化 SQL 文件没有可执行语句", "INVALID_PARAMS");
|
|
1030
|
+
const executed = await client.executeDdlStatements(statements, { allowFailure: hasFlag(argv, "--allow-failure") });
|
|
1031
|
+
await client.call("POST", "/api/sei/data/removeAllCache", {}, { allowFailure: false });
|
|
1032
|
+
printJson({
|
|
1033
|
+
success: true,
|
|
1034
|
+
code: 1,
|
|
1035
|
+
message: "基础源数据初始化完成",
|
|
1036
|
+
data: {
|
|
1037
|
+
executed: executed.length,
|
|
1038
|
+
sqlFile,
|
|
1039
|
+
admin: readOption(argv, "--admin-uid") ?? "admin",
|
|
1040
|
+
role: readOption(argv, "--admin-role") ?? "admin",
|
|
1041
|
+
baseUrl: settings.baseUrl
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
default: throw new SeiMcpError(`未知 CLI 子命令:${command}`, "INVALID_PARAMS");
|
|
1007
1047
|
}
|
|
1008
|
-
|
|
1048
|
+
} catch (error) {
|
|
1049
|
+
options.logger.error("CLI command failed", {
|
|
1050
|
+
argv,
|
|
1051
|
+
error: toErrorLogMeta(error)
|
|
1052
|
+
});
|
|
1053
|
+
process.stderr.write(`${formatCliError(error)}\n`);
|
|
1054
|
+
throw error;
|
|
1009
1055
|
}
|
|
1010
1056
|
}
|
|
1011
1057
|
function renderCliHelp() {
|
|
@@ -1238,6 +1284,25 @@ function toTargetMap(value) {
|
|
|
1238
1284
|
return Object.fromEntries(Object.entries(value).filter(([, item]) => isObject$4(item)));
|
|
1239
1285
|
}
|
|
1240
1286
|
//#endregion
|
|
1287
|
+
//#region src/env.ts
|
|
1288
|
+
var DEFAULT_ENV_FILES = [".env.local", ".env"];
|
|
1289
|
+
async function loadWorkingDirEnv(cwd = process.cwd(), env = process.env) {
|
|
1290
|
+
for (const fileName of DEFAULT_ENV_FILES) await loadEnvFile(resolve(cwd, fileName), env);
|
|
1291
|
+
}
|
|
1292
|
+
async function loadEnvFile(path, env) {
|
|
1293
|
+
try {
|
|
1294
|
+
const parsed = parseEnv(await readFile(path, "utf8"));
|
|
1295
|
+
for (const [key, value] of Object.entries(parsed)) if (env[key] === void 0) env[key] = value;
|
|
1296
|
+
} catch (error) {
|
|
1297
|
+
if (isMissingFile(error)) return;
|
|
1298
|
+
throw error;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
function isMissingFile(error) {
|
|
1302
|
+
if (!error || typeof error !== "object") return false;
|
|
1303
|
+
return error.code === "ENOENT";
|
|
1304
|
+
}
|
|
1305
|
+
//#endregion
|
|
1241
1306
|
//#region src/logger.ts
|
|
1242
1307
|
var LEVEL_PRIORITY = {
|
|
1243
1308
|
error: 0,
|
|
@@ -4881,7 +4946,7 @@ var $ZodAsyncError = class extends Error {
|
|
|
4881
4946
|
}
|
|
4882
4947
|
};
|
|
4883
4948
|
var globalConfig = {};
|
|
4884
|
-
function config
|
|
4949
|
+
function config(newConfig) {
|
|
4885
4950
|
if (newConfig) Object.assign(globalConfig, newConfig);
|
|
4886
4951
|
return globalConfig;
|
|
4887
4952
|
}
|
|
@@ -5224,7 +5289,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
5224
5289
|
}, ctx);
|
|
5225
5290
|
if (result instanceof Promise) throw new $ZodAsyncError();
|
|
5226
5291
|
if (result.issues.length) {
|
|
5227
|
-
const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
5292
|
+
const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
5228
5293
|
captureStackTrace(e, _params?.callee);
|
|
5229
5294
|
throw e;
|
|
5230
5295
|
}
|
|
@@ -5239,7 +5304,7 @@ var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
|
5239
5304
|
}, ctx);
|
|
5240
5305
|
if (result instanceof Promise) result = await result;
|
|
5241
5306
|
if (result.issues.length) {
|
|
5242
|
-
const e = new (params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
5307
|
+
const e = new (params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
5243
5308
|
captureStackTrace(e, params?.callee);
|
|
5244
5309
|
throw e;
|
|
5245
5310
|
}
|
|
@@ -5258,7 +5323,7 @@ var _safeParse = (_Err) => (schema, value, _ctx) => {
|
|
|
5258
5323
|
if (result instanceof Promise) throw new $ZodAsyncError();
|
|
5259
5324
|
return result.issues.length ? {
|
|
5260
5325
|
success: false,
|
|
5261
|
-
error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
5326
|
+
error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
5262
5327
|
} : {
|
|
5263
5328
|
success: true,
|
|
5264
5329
|
data: result.value
|
|
@@ -5274,7 +5339,7 @@ var _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
|
5274
5339
|
if (result instanceof Promise) result = await result;
|
|
5275
5340
|
return result.issues.length ? {
|
|
5276
5341
|
success: false,
|
|
5277
|
-
error: new _Err(result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
5342
|
+
error: new _Err(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
5278
5343
|
} : {
|
|
5279
5344
|
success: true,
|
|
5280
5345
|
data: result.value
|
|
@@ -6342,7 +6407,7 @@ function handleUnionResults(results, final, inst, ctx) {
|
|
|
6342
6407
|
code: "invalid_union",
|
|
6343
6408
|
input: final.value,
|
|
6344
6409
|
inst,
|
|
6345
|
-
errors: results.map((result) => result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
6410
|
+
errors: results.map((result) => result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
6346
6411
|
});
|
|
6347
6412
|
return final;
|
|
6348
6413
|
}
|
|
@@ -6571,7 +6636,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
6571
6636
|
payload.issues.push({
|
|
6572
6637
|
origin: "record",
|
|
6573
6638
|
code: "invalid_key",
|
|
6574
|
-
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
6639
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
6575
6640
|
input: key,
|
|
6576
6641
|
path: [key],
|
|
6577
6642
|
inst
|
|
@@ -6739,7 +6804,7 @@ var $ZodCatch = /* @__PURE__ */ $constructor("$ZodCatch", (inst, def) => {
|
|
|
6739
6804
|
if (result.issues.length) {
|
|
6740
6805
|
payload.value = def.catchValue({
|
|
6741
6806
|
...payload,
|
|
6742
|
-
error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
6807
|
+
error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config())) },
|
|
6743
6808
|
input: payload.value
|
|
6744
6809
|
});
|
|
6745
6810
|
payload.issues = [];
|
|
@@ -6750,7 +6815,7 @@ var $ZodCatch = /* @__PURE__ */ $constructor("$ZodCatch", (inst, def) => {
|
|
|
6750
6815
|
if (result.issues.length) {
|
|
6751
6816
|
payload.value = def.catchValue({
|
|
6752
6817
|
...payload,
|
|
6753
|
-
error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config
|
|
6818
|
+
error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config())) },
|
|
6754
6819
|
input: payload.value
|
|
6755
6820
|
});
|
|
6756
6821
|
payload.issues = [];
|
|
@@ -22221,6 +22286,7 @@ function toTrimmedString(value) {
|
|
|
22221
22286
|
}
|
|
22222
22287
|
//#endregion
|
|
22223
22288
|
//#region src/index.ts
|
|
22289
|
+
await loadWorkingDirEnv();
|
|
22224
22290
|
var logger = createLogger(process.env.SEI_MCP_LOG_LEVEL ?? "info");
|
|
22225
22291
|
var argv = process.argv.slice(2);
|
|
22226
22292
|
var runtime = parseRuntimeOptions(argv, process.env);
|
|
@@ -22228,23 +22294,31 @@ if (runtime.command === "help") {
|
|
|
22228
22294
|
process.stdout.write(`${renderHelpText()}\n`);
|
|
22229
22295
|
process.exit(0);
|
|
22230
22296
|
}
|
|
22231
|
-
|
|
22232
|
-
|
|
22233
|
-
|
|
22297
|
+
try {
|
|
22298
|
+
const config = await loadConfig(argv, process.env);
|
|
22299
|
+
if (runtime.command === "cli") {
|
|
22300
|
+
await runCli(runtime.cliArgs, {
|
|
22301
|
+
config,
|
|
22302
|
+
logger
|
|
22303
|
+
});
|
|
22304
|
+
process.exit(0);
|
|
22305
|
+
}
|
|
22306
|
+
const client = createSeiClient(config, logger);
|
|
22307
|
+
if (runtime.transport === "streamable-http") await startHttpServer(() => createMcpServer({
|
|
22234
22308
|
config,
|
|
22309
|
+
client,
|
|
22235
22310
|
logger
|
|
22236
|
-
});
|
|
22237
|
-
|
|
22311
|
+
}), runtime, logger);
|
|
22312
|
+
else await startStdioServer(createMcpServer({
|
|
22313
|
+
config,
|
|
22314
|
+
client,
|
|
22315
|
+
logger
|
|
22316
|
+
}));
|
|
22317
|
+
} catch (error) {
|
|
22318
|
+
if (!isSeiMcpError(error) || runtime.command !== "cli") {
|
|
22319
|
+
logger.error("sei-ai startup failed", toErrorLogMeta(error));
|
|
22320
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
22321
|
+
}
|
|
22322
|
+
process.exit(1);
|
|
22238
22323
|
}
|
|
22239
|
-
var client = createSeiClient(config, logger);
|
|
22240
|
-
if (runtime.transport === "streamable-http") await startHttpServer(() => createMcpServer({
|
|
22241
|
-
config,
|
|
22242
|
-
client,
|
|
22243
|
-
logger
|
|
22244
|
-
}), runtime, logger);
|
|
22245
|
-
else await startStdioServer(createMcpServer({
|
|
22246
|
-
config,
|
|
22247
|
-
client,
|
|
22248
|
-
logger
|
|
22249
|
-
}));
|
|
22250
22324
|
//#endregion
|