@ty_krystal/sei-ai 0.1.5 → 0.1.6
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 +701 -175
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +5 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +5 -0
- package/dist/commands/api-docs.d.ts +20 -0
- package/dist/commands/api-docs.js +4 -5
- package/dist/commands/call.d.ts +27 -0
- package/dist/commands/call.js +12 -13
- package/dist/commands/dict/add-category.d.ts +31 -0
- package/dist/commands/dict/add-category.js +9 -10
- package/dist/commands/dict/add-item.d.ts +32 -0
- package/dist/commands/dict/add-item.js +11 -12
- package/dist/commands/dict/list.d.ts +22 -0
- package/dist/commands/dict/list.js +8 -9
- package/dist/commands/init/base-data.d.ts +26 -0
- package/dist/commands/init/base-data.js +14 -15
- package/dist/commands/query-sql.d.ts +24 -0
- package/dist/commands/query-sql.js +6 -8
- package/dist/commands/query.d.ts +21 -0
- package/dist/commands/query.js +6 -7
- package/dist/commands/relogin.d.ts +17 -0
- package/dist/commands/relogin.js +2 -3
- package/dist/commands/save.d.ts +21 -0
- package/dist/commands/save.js +6 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -2
- package/oclif.manifest.json +1302 -0
- package/package.json +63 -54
- package/config.example.json +0 -33
- package/dist/README.md +0 -239
- package/dist/cli-actions.js +0 -157
- package/dist/cli-helpers.js +0 -246
- package/dist/command-base/context.js +0 -10
- package/dist/command-base/output.js +0 -6
- package/dist/command-base/payload.js +0 -33
- package/dist/command-base/sei-command.js +0 -88
- package/dist/commands/stdio.js +0 -16
- package/dist/commands/streamable-http.js +0 -29
- package/dist/config.example.json +0 -33
- package/dist/config.js +0 -82
- package/dist/constants.js +0 -48
- package/dist/env.js +0 -33
- package/dist/errors.js +0 -55
- package/dist/logger.js +0 -71
- package/dist/openapi.js +0 -261
- package/dist/permissions.js +0 -209
- package/dist/schema.js +0 -112
- package/dist/sei-client.js +0 -535
- package/dist/server.js +0 -237
- package/dist/tools.js +0 -175
- package/dist/types.js +0 -1
- package/dist/utils.js +0 -53
package/package.json
CHANGED
|
@@ -1,69 +1,78 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ty_krystal/sei-ai",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"cli",
|
|
9
|
-
"openapi"
|
|
10
|
-
],
|
|
11
|
-
"homepage": "https://github.com/tanyu/sei-ai",
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/tanyu/sei-ai/issues"
|
|
3
|
+
"description": "SEI CLI generated with oclif",
|
|
4
|
+
"version": "0.1.6",
|
|
5
|
+
"author": "tanyu",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sei-ai": "./bin/run.js"
|
|
14
8
|
},
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
"
|
|
9
|
+
"bugs": "https://github.com/tanyu/sei-ai/issues",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@oclif/core": "^4",
|
|
12
|
+
"@oclif/plugin-help": "^6",
|
|
13
|
+
"@oclif/plugin-plugins": "^5",
|
|
14
|
+
"@ty_krystal/sei-ai-core": "workspace:*"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@eslint/compat": "^1",
|
|
18
|
+
"@oclif/prettier-config": "^0.2.1",
|
|
19
|
+
"@oclif/test": "^4",
|
|
20
|
+
"@types/chai": "^4",
|
|
21
|
+
"@types/mocha": "^10",
|
|
22
|
+
"@types/node": "^18",
|
|
23
|
+
"chai": "^4",
|
|
24
|
+
"eslint": "^9",
|
|
25
|
+
"eslint-config-oclif": "^6",
|
|
26
|
+
"eslint-config-prettier": "^10",
|
|
27
|
+
"mocha": "^11",
|
|
28
|
+
"oclif": "^4",
|
|
29
|
+
"shx": "^0.3.4",
|
|
30
|
+
"ts-node": "^10",
|
|
31
|
+
"typescript": "^5"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
18
38
|
},
|
|
19
|
-
"license": "MIT",
|
|
20
|
-
"type": "module",
|
|
21
39
|
"files": [
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
40
|
+
"./bin",
|
|
41
|
+
"./dist",
|
|
42
|
+
"./oclif.manifest.json"
|
|
25
43
|
],
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
44
|
+
"homepage": "https://github.com/tanyu/sei-ai",
|
|
45
|
+
"keywords": ["oclif", "sei", "cli"],
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"main": "dist/index.js",
|
|
48
|
+
"type": "module",
|
|
29
49
|
"oclif": {
|
|
30
50
|
"bin": "sei-ai",
|
|
31
51
|
"dirname": "sei-ai",
|
|
32
|
-
"commands":
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
52
|
+
"commands": "./dist/commands",
|
|
53
|
+
"plugins": [
|
|
54
|
+
"@oclif/plugin-help",
|
|
55
|
+
"@oclif/plugin-plugins"
|
|
56
|
+
],
|
|
57
|
+
"topicSeparator": ":"
|
|
39
58
|
},
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"default": "./dist/index.js"
|
|
44
|
-
}
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "git+https://github.com/tanyu/sei-ai.git"
|
|
45
62
|
},
|
|
46
63
|
"scripts": {
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
64
|
+
"build": "pnpm --filter @ty_krystal/sei-ai-core build && shx rm -rf dist && tsc -b",
|
|
65
|
+
"dev": "node ./bin/dev.js",
|
|
66
|
+
"lint": "eslint",
|
|
67
|
+
"postpack": "shx rm -f oclif.manifest.json",
|
|
68
|
+
"posttest": "pnpm run lint",
|
|
69
|
+
"prepack": "oclif manifest && oclif readme",
|
|
70
|
+
"prepublishOnly": "pnpm run build",
|
|
71
|
+
"publish:npm": "npm publish --access public",
|
|
72
|
+
"start": "node ./bin/run.js",
|
|
54
73
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
"engines": {
|
|
58
|
-
"node": "^22.18.0 || ^24.0.0"
|
|
74
|
+
"test": "pnpm --filter @ty_krystal/sei-ai-core typecheck && mocha --forbid-only \"test/**/*.test.ts\"",
|
|
75
|
+
"version": "oclif readme && git add README.md"
|
|
59
76
|
},
|
|
60
|
-
"
|
|
61
|
-
"access": "public"
|
|
62
|
-
},
|
|
63
|
-
"dependencies": {
|
|
64
|
-
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
65
|
-
"@oclif/core": "^4.11.10",
|
|
66
|
-
"tsx": "^4.22.4",
|
|
67
|
-
"zod": "^3.25.76"
|
|
68
|
-
}
|
|
77
|
+
"types": "dist/index.d.ts"
|
|
69
78
|
}
|
package/config.example.json
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"baseUrl": "http://127.0.0.1:8081",
|
|
3
|
-
"auth": {
|
|
4
|
-
"mode": "ai-login",
|
|
5
|
-
"aiKeyEnv": "SEI_AI_LOGIN_KEY",
|
|
6
|
-
"roleEnv": "SEI_AI_LOGIN_ROLE"
|
|
7
|
-
},
|
|
8
|
-
"tools": {
|
|
9
|
-
"query": true,
|
|
10
|
-
"save": true,
|
|
11
|
-
"schema": true,
|
|
12
|
-
"querySql": false
|
|
13
|
-
},
|
|
14
|
-
"targets": {
|
|
15
|
-
"modules": {
|
|
16
|
-
"demo_order": {
|
|
17
|
-
"mainTable": "demo_order",
|
|
18
|
-
"query": {
|
|
19
|
-
"fields": ["_ID", "ORDER_NO", "STATUS", "AMOUNT"],
|
|
20
|
-
"defaultFields": ["_ID", "ORDER_NO", "STATUS"],
|
|
21
|
-
"allowAllFields": false
|
|
22
|
-
},
|
|
23
|
-
"save": {
|
|
24
|
-
"actions": ["add", "edit"],
|
|
25
|
-
"fields": ["STATUS", "MEMO"]
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
"tables": {},
|
|
30
|
-
"sources": {},
|
|
31
|
-
"views": {}
|
|
32
|
-
}
|
|
33
|
-
}
|
package/dist/README.md
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
# sei-ai
|
|
2
|
-
|
|
3
|
-
独立的 SEI MCP 服务,使用 `@modelcontextprotocol/sdk` 运行。
|
|
4
|
-
支持 `stdio`、`streamable-http` 和开发者 CLI 启动,默认只开放受控的低代码查询、保存和字段元数据工具,`querySql` 默认关闭。
|
|
5
|
-
CLI 已迁移到 `oclif`,命令面改为顶层子命令。
|
|
6
|
-
|
|
7
|
-
## 安装
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install -g sei-ai
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## 命令
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
pnpm -F sei-ai-mcp dev -- --config ./apps/sei-ai-mcp/config.example.json
|
|
17
|
-
pnpm -F sei-ai-mcp run start:stdio
|
|
18
|
-
pnpm -F sei-ai-mcp run start:http
|
|
19
|
-
pnpm -F sei-ai-mcp run build
|
|
20
|
-
pnpm -F sei-ai-mcp run test
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
打包后 CLI:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
sei-ai help
|
|
27
|
-
sei-ai stdio --config ./config.example.json
|
|
28
|
-
sei-ai streamable-http --host 0.0.0.0 --port 3000 --path /mcp --config ./config.example.json
|
|
29
|
-
sei-ai api-docs --format markdown
|
|
30
|
-
sei-ai relogin
|
|
31
|
-
sei-ai query-sql "SELECT _UID,_NAME FROM _SYS_USER"
|
|
32
|
-
sei-ai call POST /api/sei/data/removeAllCache --json '{}'
|
|
33
|
-
sei-ai dict:list --type status
|
|
34
|
-
sei-ai dict:add-category sex 性别
|
|
35
|
-
sei-ai dict:add-item sex male 男
|
|
36
|
-
sei-ai init:base-data --sysid sys --admin-uid admin
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## 开发者 CLI
|
|
40
|
-
|
|
41
|
-
CLI 是新增的开发者命令面,不会改变现有 MCP server 的启动方式、tool 列表或 Host 集成配置。
|
|
42
|
-
|
|
43
|
-
命令示例:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
sei-ai query --json '{"head":{"module":"sys_user"},"option":{"fields":"_UID,_NAME"}}'
|
|
47
|
-
sei-ai save --json '{"head":{"module":"sys_user"},"data":[{"action":"edit","rows":[{"keyVal":"admin","row":{"_NAME":"管理员"}}]}]}'
|
|
48
|
-
sei-ai query-sql "SELECT _UID,_NAME FROM _SYS_USER" --page 1 --size 20
|
|
49
|
-
sei-ai api-docs --keyword login --format json
|
|
50
|
-
sei-ai relogin --role admin
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
常用认证参数:
|
|
54
|
-
|
|
55
|
-
- `--base-url`
|
|
56
|
-
- `--ai-key`
|
|
57
|
-
- `--role`
|
|
58
|
-
- `--account`
|
|
59
|
-
- `--account-project`
|
|
60
|
-
- `--account-checkcode`
|
|
61
|
-
- `--token`
|
|
62
|
-
- `--timeout`
|
|
63
|
-
|
|
64
|
-
环境变量加载规则:
|
|
65
|
-
|
|
66
|
-
- 启动时会自动读取当前工作目录下的 `.env.local` 和 `.env`
|
|
67
|
-
- 加载顺序为 `.env.local` 再 `.env`
|
|
68
|
-
- 已经存在的进程环境变量不会被 `.env` 覆盖
|
|
69
|
-
- 显式 CLI 参数仍然优先于环境变量
|
|
70
|
-
|
|
71
|
-
载荷输入支持:
|
|
72
|
-
|
|
73
|
-
- `--json '<payload>'`
|
|
74
|
-
- `--file ./payload.json`
|
|
75
|
-
- `--stdin`
|
|
76
|
-
|
|
77
|
-
当前命令面:
|
|
78
|
-
|
|
79
|
-
- `stdio`
|
|
80
|
-
- `streamable-http`
|
|
81
|
-
- `query`
|
|
82
|
-
- `save`
|
|
83
|
-
- `call`
|
|
84
|
-
- `query-sql`
|
|
85
|
-
- `sql`
|
|
86
|
-
- `api-docs`
|
|
87
|
-
- `relogin`
|
|
88
|
-
- `dict:list`
|
|
89
|
-
- `dict:add-category`
|
|
90
|
-
- `dict:add-item`
|
|
91
|
-
- `init:base-data`
|
|
92
|
-
|
|
93
|
-
HTTP 模式:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
pnpm -F sei-ai-mcp dev -- --transport streamable-http --host 0.0.0.0 --port 3000 --path /mcp --config ./apps/sei-ai-mcp/config.example.json
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Docker Compose:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
docker compose -f apps/sei-ai-mcp/docker-compose.yml up -d --build
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
容器默认暴露 `http://127.0.0.1:3719/mcp`,并通过 `host.docker.internal` 访问宿主机上的 SEI 后端。
|
|
106
|
-
如果后端也在 compose 中运行,把 `SEI_BASE_URL` 改成对应服务名即可。
|
|
107
|
-
|
|
108
|
-
## 配置
|
|
109
|
-
|
|
110
|
-
支持的配置项:
|
|
111
|
-
|
|
112
|
-
- `baseUrl`
|
|
113
|
-
- `auth.mode`: `ai-login` 或 `token`
|
|
114
|
-
- `auth.token`
|
|
115
|
-
- `auth.aiKey`
|
|
116
|
-
- `auth.account`
|
|
117
|
-
- `auth.role`
|
|
118
|
-
- `tools.query`
|
|
119
|
-
- `tools.save`
|
|
120
|
-
- `tools.schema`
|
|
121
|
-
- `tools.querySql`
|
|
122
|
-
- `targets.modules`
|
|
123
|
-
- `targets.tables`
|
|
124
|
-
- `targets.sources`
|
|
125
|
-
- `targets.views`
|
|
126
|
-
|
|
127
|
-
敏感值可通过环境变量注入:
|
|
128
|
-
|
|
129
|
-
- `SEI_BASE_URL`
|
|
130
|
-
- `SEI_AI_LOGIN_KEY`
|
|
131
|
-
- `SEI_AI_LOGIN_ACCOUNT`
|
|
132
|
-
- `SEI_AI_LOGIN_ROLE`
|
|
133
|
-
- `SEI_TOKEN`
|
|
134
|
-
- `SEI_MCP_TRANSPORT`
|
|
135
|
-
- `SEI_MCP_HOST`
|
|
136
|
-
- `SEI_MCP_PORT`
|
|
137
|
-
- `SEI_MCP_PATH`
|
|
138
|
-
- `SEI_MCP_HTTP_JSON_RESPONSE`
|
|
139
|
-
|
|
140
|
-
例如可以在项目目录写:
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
SEI_BASE_URL=http://127.0.0.1:8081
|
|
144
|
-
SEI_AI_LOGIN_KEY=dev-ai-secret
|
|
145
|
-
SEI_AI_LOGIN_ROLE=admin
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
## 权限模型
|
|
149
|
-
|
|
150
|
-
- 未配置目标时默认拒绝。
|
|
151
|
-
- 查询字段必须命中白名单。
|
|
152
|
-
- 保存字段必须命中白名单。
|
|
153
|
-
- `querySql` 默认关闭,只允许单条 `SELECT/WITH`。
|
|
154
|
-
- stdio 日志只写 `stderr`,不污染 MCP 协议输出。
|
|
155
|
-
|
|
156
|
-
注意:
|
|
157
|
-
|
|
158
|
-
- 上面的权限模型只约束 MCP tool 面。
|
|
159
|
-
- 开发者 CLI 直接调用 SEI HTTP 接口,不走 MCP 白名单过滤,因此它是调试/开发入口,不是给模型暴露的 tool 面。
|
|
160
|
-
|
|
161
|
-
## 工具
|
|
162
|
-
|
|
163
|
-
- `sei_query`
|
|
164
|
-
- `sei_save`
|
|
165
|
-
- `sei_schema`
|
|
166
|
-
- `sei_query_sql`(默认关闭)
|
|
167
|
-
|
|
168
|
-
## MCP Host
|
|
169
|
-
|
|
170
|
-
可直接作为 stdio MCP server 启动,再由上层 Host 注册。
|
|
171
|
-
|
|
172
|
-
stdio Host 配置示例:
|
|
173
|
-
|
|
174
|
-
```json
|
|
175
|
-
{
|
|
176
|
-
"mcpServers": {
|
|
177
|
-
"sei-ai-mcp": {
|
|
178
|
-
"command": "sei-ai",
|
|
179
|
-
"args": [
|
|
180
|
-
"stdio",
|
|
181
|
-
"--config",
|
|
182
|
-
"/abs/path/config.dev.json"
|
|
183
|
-
]
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
HTTP 模式可直接挂载到容器端口,Host 地址示例:
|
|
190
|
-
|
|
191
|
-
```json
|
|
192
|
-
{
|
|
193
|
-
"mcpServers": {
|
|
194
|
-
"sei-ai-mcp": {
|
|
195
|
-
"url": "http://127.0.0.1:3719/mcp"
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Spring AI Java 接入
|
|
202
|
-
|
|
203
|
-
如果 `apps/backend` 通过 Spring AI MCP client 接入,直接使用 `streamable-http`:
|
|
204
|
-
|
|
205
|
-
```yaml
|
|
206
|
-
spring:
|
|
207
|
-
ai:
|
|
208
|
-
mcp:
|
|
209
|
-
client:
|
|
210
|
-
enabled: true
|
|
211
|
-
type: SYNC
|
|
212
|
-
request-timeout: 30s
|
|
213
|
-
toolcallback:
|
|
214
|
-
enabled: true
|
|
215
|
-
streamable-http:
|
|
216
|
-
connections:
|
|
217
|
-
sei-ai-mcp:
|
|
218
|
-
url: http://127.0.0.1:3719
|
|
219
|
-
endpoint: /mcp
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
如果后端默认直接访问宿主机暴露端口,可这样配置:
|
|
223
|
-
|
|
224
|
-
```bash
|
|
225
|
-
SEI_AI_MCP_HTTP_URL=http://127.0.0.1:3719
|
|
226
|
-
SEI_AI_MCP_HTTP_ENDPOINT=/mcp
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
如果是宿主机或外部服务直连容器暴露端口,则访问地址为:
|
|
230
|
-
|
|
231
|
-
```bash
|
|
232
|
-
http://127.0.0.1:3719/mcp
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
npm version patch --no-git-tag-version
|
|
238
|
-
pnpm run build
|
|
239
|
-
npm publish --access public --cache /tmp/sei-ai-npm-cache
|
package/dist/cli-actions.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
import { BASE_SEED_DEFAULT_ADMIN_ROLE, BASE_SEED_DEFAULT_ADMIN_UID } from './constants.js';
|
|
4
|
-
import { formatCliError, SeiMcpError } from './errors.js';
|
|
5
|
-
import { buildBaseSeedSqlVars, buildDictCategoryRow, buildDictItemRow, buildDictQueryPayload, buildDictSavePayload, buildDictTree, removeSqlCommentLines, renderBaseSeedSql, splitSqlStatements, } from './cli-helpers.js';
|
|
6
|
-
import { buildOpenApiDocSummary, renderOpenApiMarkdown } from './openapi.js';
|
|
7
|
-
export async function runApiDocs(options) {
|
|
8
|
-
const raw = await options.client.readApiDocs();
|
|
9
|
-
const summary = buildOpenApiDocSummary(raw, options.keyword);
|
|
10
|
-
const output = options.format === 'json' ? `${JSON.stringify(summary, null, 2)}\n` : renderOpenApiMarkdown(summary);
|
|
11
|
-
await writeOutput(options.outputPath, output);
|
|
12
|
-
}
|
|
13
|
-
export async function runRelogin(options) {
|
|
14
|
-
const token = await options.client.relogin();
|
|
15
|
-
printJson({
|
|
16
|
-
success: true,
|
|
17
|
-
code: 1,
|
|
18
|
-
message: '重新登录成功',
|
|
19
|
-
data: { token },
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
export async function runCall(options) {
|
|
23
|
-
const response = await options.client.call(options.method, options.path, options.payload, {
|
|
24
|
-
allowFailure: options.allowFailure,
|
|
25
|
-
allowEmpty: options.allowEmpty,
|
|
26
|
-
skipAuth: options.skipAuth,
|
|
27
|
-
});
|
|
28
|
-
printJson(response);
|
|
29
|
-
}
|
|
30
|
-
export async function runQuery(options) {
|
|
31
|
-
const response = await options.client.query(options.payload, {
|
|
32
|
-
allowFailure: options.allowFailure,
|
|
33
|
-
});
|
|
34
|
-
printJson(response);
|
|
35
|
-
}
|
|
36
|
-
export async function runSave(options) {
|
|
37
|
-
const response = await options.client.save(options.payload, {
|
|
38
|
-
allowFailure: options.allowFailure,
|
|
39
|
-
});
|
|
40
|
-
printJson(response);
|
|
41
|
-
}
|
|
42
|
-
export async function runQuerySql(options) {
|
|
43
|
-
const response = await options.client.querySql(options.sql, options.page, options.size, {
|
|
44
|
-
allowFailure: options.allowFailure,
|
|
45
|
-
});
|
|
46
|
-
printJson(response);
|
|
47
|
-
}
|
|
48
|
-
export async function runDictList(options) {
|
|
49
|
-
const payload = buildDictQueryPayload(options.typeCode, options.keyword, options.size ?? 1000);
|
|
50
|
-
const response = await options.client.query(payload, {
|
|
51
|
-
allowFailure: options.allowFailure,
|
|
52
|
-
});
|
|
53
|
-
if (!options.flat && isObject(response) && isObject(response.data) && Array.isArray(response.data.rows)) {
|
|
54
|
-
response.data.tree = buildDictTree(response.data.rows);
|
|
55
|
-
}
|
|
56
|
-
printJson(response);
|
|
57
|
-
}
|
|
58
|
-
export async function runDictAddCategory(options) {
|
|
59
|
-
const payload = buildDictSavePayload(buildDictCategoryRow({
|
|
60
|
-
body: stringOrUndefined(options.rowOptions?.body),
|
|
61
|
-
code: stringOrUndefined(options.rowOptions?.code),
|
|
62
|
-
ctype: stringOrUndefined(options.rowOptions?.ctype),
|
|
63
|
-
dictFlag: numberOrUndefined(options.rowOptions?.dictFlag),
|
|
64
|
-
ename: stringOrUndefined(options.rowOptions?.ename),
|
|
65
|
-
memo: stringOrUndefined(options.rowOptions?.memo),
|
|
66
|
-
name: options.name,
|
|
67
|
-
sort: numberOrUndefined(options.rowOptions?.sort),
|
|
68
|
-
sysid: stringOrUndefined(options.rowOptions?.sysid),
|
|
69
|
-
typeCode: options.typeCode,
|
|
70
|
-
uuid: stringOrUndefined(options.rowOptions?.uuid),
|
|
71
|
-
}));
|
|
72
|
-
const response = await options.client.save(payload, {
|
|
73
|
-
allowFailure: options.allowFailure,
|
|
74
|
-
});
|
|
75
|
-
printJson(response);
|
|
76
|
-
}
|
|
77
|
-
export async function runDictAddItem(options) {
|
|
78
|
-
const payload = buildDictSavePayload(buildDictItemRow({
|
|
79
|
-
body: stringOrUndefined(options.rowOptions?.body),
|
|
80
|
-
code: options.code,
|
|
81
|
-
ctype: stringOrUndefined(options.rowOptions?.ctype),
|
|
82
|
-
dictFlag: numberOrUndefined(options.rowOptions?.dictFlag),
|
|
83
|
-
ename: stringOrUndefined(options.rowOptions?.ename),
|
|
84
|
-
memo: stringOrUndefined(options.rowOptions?.memo),
|
|
85
|
-
name: options.name,
|
|
86
|
-
parent: stringOrUndefined(options.rowOptions?.parent),
|
|
87
|
-
sort: numberOrUndefined(options.rowOptions?.sort),
|
|
88
|
-
sysid: stringOrUndefined(options.rowOptions?.sysid),
|
|
89
|
-
typeCode: options.typeCode,
|
|
90
|
-
uuid: stringOrUndefined(options.rowOptions?.uuid),
|
|
91
|
-
}));
|
|
92
|
-
const response = await options.client.save(payload, {
|
|
93
|
-
allowFailure: options.allowFailure,
|
|
94
|
-
});
|
|
95
|
-
printJson(response);
|
|
96
|
-
}
|
|
97
|
-
export async function runInitBaseData(options) {
|
|
98
|
-
const sqlFile = resolveBaseSeedSqlPath(options.sqlFile);
|
|
99
|
-
const template = await readFile(sqlFile, 'utf8');
|
|
100
|
-
const sql = renderBaseSeedSql(template, buildBaseSeedSqlVars({
|
|
101
|
-
adminName: options.adminName,
|
|
102
|
-
adminPassword: options.adminPassword,
|
|
103
|
-
adminRole: options.adminRole,
|
|
104
|
-
adminRoleName: options.adminRoleName,
|
|
105
|
-
adminUid: options.adminUid,
|
|
106
|
-
resetAdminPassword: options.resetAdminPassword,
|
|
107
|
-
sysid: options.sysid,
|
|
108
|
-
}));
|
|
109
|
-
const statements = splitSqlStatements(removeSqlCommentLines(sql));
|
|
110
|
-
if (statements.length === 0) {
|
|
111
|
-
throw new SeiMcpError('初始化 SQL 文件没有可执行语句', 'INVALID_PARAMS');
|
|
112
|
-
}
|
|
113
|
-
const executed = await options.client.executeDdlStatements(statements, {
|
|
114
|
-
allowFailure: options.allowFailure,
|
|
115
|
-
});
|
|
116
|
-
await options.client.call('POST', '/api/sei/data/removeAllCache', {}, { allowFailure: false }).catch(() => undefined);
|
|
117
|
-
printJson({
|
|
118
|
-
success: true,
|
|
119
|
-
code: 1,
|
|
120
|
-
message: '基础源数据初始化完成',
|
|
121
|
-
data: {
|
|
122
|
-
executed: Array.isArray(executed) ? executed.length : 0,
|
|
123
|
-
sqlFile,
|
|
124
|
-
admin: options.adminUid ?? BASE_SEED_DEFAULT_ADMIN_UID,
|
|
125
|
-
role: options.adminRole ?? BASE_SEED_DEFAULT_ADMIN_ROLE,
|
|
126
|
-
},
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
export async function writeOutput(path, text) {
|
|
130
|
-
if (!path) {
|
|
131
|
-
process.stdout.write(text);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
await writeFile(path, text, 'utf8');
|
|
135
|
-
process.stdout.write(`已写入:${path}\n`);
|
|
136
|
-
}
|
|
137
|
-
export function printJson(value) {
|
|
138
|
-
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
139
|
-
}
|
|
140
|
-
export function resolveBaseSeedSqlPath(path) {
|
|
141
|
-
if (path) {
|
|
142
|
-
return resolve(path);
|
|
143
|
-
}
|
|
144
|
-
return resolve(process.cwd(), '.codex/skills/sei-ai/scripts/init-base-data.sql');
|
|
145
|
-
}
|
|
146
|
-
export function formatActionError(error) {
|
|
147
|
-
return formatCliError(error);
|
|
148
|
-
}
|
|
149
|
-
function stringOrUndefined(value) {
|
|
150
|
-
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
151
|
-
}
|
|
152
|
-
function numberOrUndefined(value) {
|
|
153
|
-
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
154
|
-
}
|
|
155
|
-
function isObject(value) {
|
|
156
|
-
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
157
|
-
}
|