flycode-mcp 1.14.3 → 1.14.5

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 CHANGED
@@ -11,15 +11,15 @@ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for the
11
11
  - 基于官方 `@modelcontextprotocol/sdk` 实现,使用标准 `stdio` 传输协议。
12
12
  - 启动即完成 APaaS IDE 平台鉴权链路:账号登录 → 获取租户信息 → 获取 IDE Token。
13
13
  - 内置统一请求层 `request`,自动按请求类型(`center` / `tenant` / `business`)切换中心服务地址、当前租户连接地址或当前租户业务地址,并自动注入鉴权 Token:`business` 类型主要用于 H5 表单查询(需以特定预览账号 token 发起)。
14
- - 当前提供工具:业务逻辑类 `page_model_logic_directories`(分页查询业务逻辑所属目录,返回各业务模型目录项,含 modellogic 用到的 modelcode)、`page_model_logic_list`(分页查询业务逻辑列表)、`get_model_logic`(查询单个业务逻辑详情)、`save_model_logic`(新增业务逻辑:保存完整 `LogicResult`)、`patch_model_logic`(局部补丁修改业务逻辑的 input/output 结构或顶层元数据,无需回传整份对象,替代旧版轻量保存)、`str_replace_flycode`(批量局部替换 flycode 脚本,或用 `rewrite: true` 整份重写);实体类 `page_entity_list`(分页查询实体列表)、`get_entity`(查询实体详情)、`page_entity_directories`(查询实体所属目录,取回的 `directorytypecode` 即 `create_entity` 的 `directorytypecode` 必填入参;该接口不支持分页、全量数百条,故在服务层强制收敛——默认最多回 30 条、硬上限 200 条,未传筛选条件时只回顶级目录,并回 `truncated` / `hint` 提示)、`create_entity`(新增实体:仅传必要参数,完整实体对象由 MCP 侧组装后调平台保存;保存后处于未发布态需手动发布)、`patch_entity`(给已有实体加字段的 patch ops,当前仅实现 `add_field`;修改 / 删除字段保留未实现、运行时提示去 IDE 平台手动操作;数据字典不允许调整字段);表单 / 页面类 `page_form_directories`(查询表单所属目录,取回的 `directorytypecode` 即表单 `pageinfo.directorytypecode` 的取值;该接口不支持分页、全量数百条,故在服务层强制收敛——默认最多回 30 条、硬上限 200 条,未传筛选条件时只回顶级目录,并回 `truncated` / `hint` 提示)、`page_form_list`(分页查询表单 / 页面列表)、`get_form`(查询表单 / 页面详情);H5 表单类 `page_h5_form`(分页查询 H5 表单列表)、`get_h5_form`(查询 H5 表单详情,含 `confjson` 内容 JSON);函数类 `page_function_list`(分页查询 flycode 函数列表)、`get_function`(查询 flycode 函数详情,含 `confjson` 函数代码内容);数据库函数类 `page_database_function_list`(分页查询 PostgreSQL 自定义数据库函数列表,列表结果随行返回函数体 `functionscript`);SQL 执行类 `run_sql`(在业务库中执行一条 SELECT 查询,返回查询结果数据与结果总数);通用类 `generate_unique_code`(生成唯一编码,用于新建实体 / 领域 / 表单时生成 JSON 中的 `code` 字段)。
14
+ - 当前提供工具:业务逻辑类;实体类;表单类;H5 表单类;flycode 函数类;数据库函数类;SQL 执行类;通用类。
15
15
 
16
16
  ---
17
17
 
18
18
  ## 工具渐进式披露(Progressive Disclosure)
19
19
 
20
- 客户端在 `tools/list` 阶段会把全部工具的 schema 一次性塞进上下文,受预算 / 截断策略影响可能只保留一部分,导致 AI 看不到另一些工具。本服务采用 MCP 协议原生支持的渐进式披露机制缓解该问题:
20
+ 部分客户端在 `tools/list` 阶段会把全部工具的 schema 一次性塞进上下文,受预算 / 截断策略影响可能只保留一部分,导致 AI 看不到另一些工具。本服务采用 MCP 协议原生支持的渐进式披露机制缓解该问题:
21
21
 
22
- - **始终可见(连接后)**:`mcp_catalog`(工具目录)、`mcp_activate`(启用 / 收起域)两个网关联工具,外加 `core` 域的 `run_sql`、`generate_unique_code`,共 4 个工具。
22
+ - **始终可见(连接后)**:`mcp_catalog`(工具目录)、`mcp_activate`(启用 / 收起域)两个网关工具,外加 `core` 域的 `run_sql`、`generate_unique_code`,共 4 个工具。
23
23
  - **按需解锁**:其余工具按能力聚为 `entity` / `form` / `logic` / `function` / `h5` 五个域,默认隐藏。AI 先调 `mcp_catalog` 了解有哪些域与工具,再调 `mcp_activate('form')` 启用某域;服务端随即推送 `tools/list_changed` 通知,合规客户端重拉清单后即见该域工具。亦可 `mcp_activate('form', true)` 收起以回收上下文。
24
24
 
25
25
  实现要点:`src/tools/registry.ts` 预注册全部工具并维护「域 → 工具」映射,progressive 模式下对非核心域工具默认 `disable()`;`enable()/disable()` 由 `@modelcontextprotocol/sdk` 的 `RegisteredTool` 提供,并自动触发 `tools/list_changed`。回归用例见 `test/unit/gateway-registry.test.ts`。
@@ -33,7 +33,7 @@ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for the
33
33
  环境变量:
34
34
 
35
35
  - `PROGRESSIVE_DISCLOSURE=on`(默认):启用渐进式披露。
36
- - `PROGRESSIVE_DISCLOSURE=off`:退化回「全部 25 个工具始终启用」的原有行为,作为客户端未实现 `tools/list_changed` 重拉时的兜底。若 `mcp_activate` 启用某域后调用域工具仍报 `tool not found`,说明当前客户端不支持该通知,请设为 `off`。
36
+ - `PROGRESSIVE_DISCLOSURE=off`:退化回「全部 27 个工具始终启用」的原有行为,作为客户端未实现 `tools/list_changed` 重拉时的兜底。若 `mcp_activate` 启用某域后调用域工具仍报 `tool not found`,说明当前客户端不支持该通知,请设为 `off`。
37
37
  - `FLYCODE_MCP_INPUT_SCHEMA_PROFILE=full`(默认):`tools/list` 公告原始 schema,保持兼容。
38
38
  - `FLYCODE_MCP_INPUT_SCHEMA_PROFILE=compact`:启用公告 schema 压缩(见上「第三道防线」)。推荐给有 per-schema 大小限制或上下文预算紧张的客户端。
39
39
 
@@ -84,7 +84,7 @@ npm install -g flycode-mcp
84
84
  | 命令 | 说明 |
85
85
  | ----------------------------------- | -------------------------------------------------------------------------------------- |
86
86
  | `flycode-mcp` / `flycode-mcp mcp` | 启动 MCP stdio server(兼容 `key=value` 启动参数写法,行为与直跑 `dist/flycode-mcp.min.js` 一致) |
87
- | `flycode-mcp setup` | 交互安装配套 skill 到所选智能体(初版支持 WorkBuddy / Trae CN),不写任何 `mcp.json` |
87
+ | `flycode-mcp setup` | 交互安装配套 skill 到所选智能体(初版支持 WorkBuddy / Trae CN) |
88
88
  | `flycode-mcp update` | 自更新全局包,并刷新本工具安装过的 skill |
89
89
  | `flycode-mcp --version` / `--help` | 版本与帮助 |
90
90
 
@@ -159,11 +159,31 @@ username=<账号>&password=<密码>&tenantCode=<租户号>&envName=<环境名>
159
159
  }
160
160
  ```
161
161
 
162
+ v1.14.2 及以上版本以上推荐增加两个环境变量组合 `PROGRESSIVE_DISCLOSURE` 和 `FLYCODE_MCP_INPUT_SCHEMA_PROFILE` 获得更优体验:
163
+
164
+ ```json
165
+ {
166
+ "mcpServers": {
167
+ "flycode-mcp-你的环境": {
168
+ "command": "npx",
169
+ "args": [
170
+ "flycode-mcp",
171
+ "username=你的账号&password=你的密码&tenantCode=你的租户号&envName=你的环境名"
172
+ ],
173
+ "env": {
174
+ "PROGRESSIVE_DISCLOSURE": "off",
175
+ "FLYCODE_MCP_INPUT_SCHEMA_PROFILE": "compact"
176
+ }
177
+ }
178
+ }
179
+ }
180
+ ```
181
+
162
182
  ---
163
183
 
164
184
  ## 使用说明书网站(website/)
165
185
 
166
- 本仓库在 `website/` 子目录下附带一份 **面向终端用户的使用说明书网站**(不是给贡献者看的开发文档,而是给「通过 AI 客户端使用本 MCP 的普通用户」看的图文向导)。它用 [VitePress](https://vitepress.dev) 构建,整体二次元卡通风格、带轻量动画,内容是本 README 的「小白友好版」:首页 → 快速开始 → 接入 WorkBuddy / Cursor / Claude Desktop → 准备账号 → 能力清单 → 常见场景 → 排错 FAQ → 版本更新记录。
186
+ 本仓库在 `website/` 子目录下附带一份 **面向终端用户的使用说明书网站**(不是给贡献者看的开发文档,而是给「通过 AI 客户端使用本 MCP 的普通用户」看的图文向导)。它用 [VitePress](https://vitepress.dev) 构建,整体卡通风格、带轻量动画,内容是本 README 的「小白友好版」:首页 → 快速开始 → 接入 WorkBuddy / Cursor / Claude Desktop → 准备账号 → 能力清单 → 常见场景 → 排错 FAQ → 版本更新记录。
167
187
 
168
188
  > 说明:本 README 是开发者与工具行为的权威参考;`website/` 是给最终用户阅读的上手向导,两者内容定位不同、需随工具变更同步更新。
169
189
 
@@ -838,12 +858,12 @@ flycode-mcp/
838
858
 
839
859
  ## 工作原理
840
860
 
841
- 1. **解析配置**:从 `process.argv` 读取 `username / password / tenantCode / envName`(由 `utils/config.ts` 解析)。
842
- 2. **登录**:`service/auth.ts` 中的 `authenticate()` 调用 `/api/multiplat/auth/login` 获取 Token,存入内存。
843
- 3. **定位租户与环境**:`authenticate()` 调用 `/api/multiplat/auth/getTenantInfo`,依据 `tenantCode + envName` 匹配出目标租户,保存其连接信息(`conn.config`)到内存。
844
- 4. **获取 IDE Token**:`authenticate()` 调用 `/api/multiplat/auth/getIdeToken` 换取 IDE 专用 Token 并覆盖内存中的 Token。
845
- 5. **注册并启动**:创建 `McpServer`,注册 `page_model_logic_list`、`get_model_logic`、`save_model_logic`、`patch_model_logic`、`str_replace_flycode`、`page_entity_list`、`get_entity`、`page_entity_directories`、`create_entity`、`patch_entity`、`page_form_list`、`get_form`、`get_form_outline`、`get_form_fragment`、`patch_form`、`save_form`、`page_h5_form`、`get_h5_form`、`page_function_list`、`get_function`、`page_database_function_list`、`run_sql`、`generate_unique_code` 等工具,通过 `StdioServerTransport` 监听请求。
846
- 6. **业务请求**:工具被调用时,`logicClient` / `entityClient` / `formClient` / `functionClient` / `runClient` / `h5Client` 通过 `request({ type: "tenant" })` 或 `request({ type: "business" })` 自动切换到当前租户连接地址或业务地址。`h5Client` 的 H5 表单查询需以特定预览账号(职位为 `SFA系统管理员`)的 token 发起,该 token 由 `service/h5.ts` 通过 `test-case.ts` 的预览账号列表接口解析后,以 `request({ type: "business", token })` 显式传入。`request` 在请求头统一注入 Token:若调用方在配置里显式传入 `token`(如 `request({ url, method, type: "business", token: "xxxx" })`),则优先使用该传入 Token;否则回退到内存中的 Token(由 `authenticate()` 写入或通过 `setToken` 设置)。注入后自定义 `token` 字段会被剔除,不会泄漏给后端。
861
+ 1. **解析配置**:从 `process.argv` 读取 `username / password / tenantCode / envName` 解析。
862
+ 2. **登录**:登录 IDE 获取 Token,存入内存。
863
+ 3. **定位租户与环境**:依据 `tenantCode + envName` 匹配出目标租户,保存其连接信息(`conn.config`)到内存。
864
+ 4. **获取 IDE Token**:换取具体租户环境专用 Token 并覆盖内存中的 Token。
865
+ 5. **注册并启动**:创建 `McpServer`,注册工具,通过 `StdioServerTransport` 监听请求。
866
+ 6. **业务请求**:工具被调用时,分层处理 `Tool` 层定义工具 -> `Service` 层核心处理逻辑 -> `Client` 层发 `HTTP` 请求调用 IDE 接口。
847
867
 
848
868
  ---
849
869
 
package/dist/cli.js CHANGED
@@ -112,7 +112,7 @@ var init_args = __esm({
112
112
  });
113
113
 
114
114
  // src/cli/env.ts
115
- import { readFileSync } from "node:fs";
115
+ import { existsSync, readFileSync } from "node:fs";
116
116
  import { homedir } from "node:os";
117
117
  import { dirname, join as join2, resolve } from "node:path";
118
118
  import { fileURLToPath } from "node:url";
@@ -127,11 +127,16 @@ function resolveCliPaths(packageRoot) {
127
127
  function defaultHome() {
128
128
  return homedir();
129
129
  }
130
- function defaultPackageRoot() {
131
- if (true) {
132
- return resolve("/Users/luorui/Desktop/\u7384\u6B66/\u9879\u76EE/flycode-mcp");
130
+ function pickPackageRoot(here, hasPackageJson) {
131
+ const fromDist = resolve(here, "..");
132
+ if (hasPackageJson(fromDist)) {
133
+ return fromDist;
133
134
  }
134
- return resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
135
+ return resolve(here, "..", "..");
136
+ }
137
+ function defaultPackageRoot() {
138
+ const here = dirname(fileURLToPath(import.meta.url));
139
+ return pickPackageRoot(here, (dir) => existsSync(join2(dir, "package.json")));
135
140
  }
136
141
  function readPackageVersion(packageRoot) {
137
142
  const raw = JSON.parse(readFileSync(join2(packageRoot, "package.json"), "utf8"));
@@ -385,7 +390,7 @@ var init_registry = __esm({
385
390
  { name: "core", title: "\u6838\u5FC3\u5DE5\u5177", description: "\u8DE8\u57DF\u901A\u7528\u5DE5\u5177\uFF08\u5982\u6267\u884C SQL\u3001\u751F\u6210\u552F\u4E00\u7F16\u7801\uFF09\uFF0C\u59CB\u7EC8\u53EF\u7528", alwaysOn: true },
386
391
  { name: "entity", title: "\u5B9E\u4F53", description: "\u5B9E\u4F53\uFF08\u6570\u636E\u8868\uFF09\u7684\u67E5\u8BE2", alwaysOn: false },
387
392
  { name: "form", title: "\u8868\u5355", description: "\u8868\u5355\u7684\u67E5\u8BE2\u4E0E\u4FEE\u6539\uFF08\u542B flycode \u811A\u672C\u7247\u6BB5\uFF09", alwaysOn: false },
388
- { name: "logic", title: "\u4E1A\u52A1\u903B\u8F91", description: "FlyCode \u4E1A\u52A1\u903B\u8F91\u7684\u67E5\u8BE2\u4E0E\u4FEE\u6539", alwaysOn: false },
393
+ { name: "logic", title: "\u4E1A\u52A1\u903B\u8F91", description: "FlyCode \u4E1A\u52A1\u903B\u8F91(modelLogic/\u6A21\u578B\u903B\u8F91/\u9886\u57DF)\u7684\u67E5\u8BE2\u4E0E\u4FEE\u6539", alwaysOn: false },
389
394
  { name: "function", title: "\u51FD\u6570", description: "\u5E73\u53F0\u51FD\u6570\u4E0E\u6570\u636E\u5E93\u51FD\u6570\u7684\u67E5\u8BE2", alwaysOn: false },
390
395
  { name: "h5", title: "H5 \u8868\u5355", description: "H5 \u9875\u9762\u7684\u67E5\u8BE2", alwaysOn: false }
391
396
  ];
@@ -949,7 +954,7 @@ var init_read = __esm({
949
954
  name: "page_model_logic_directories",
950
955
  config: {
951
956
  title: "\u5206\u9875\u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91\u6240\u5C5E\u76EE\u5F55",
952
- description: `\u5206\u9875\u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91\u6240\u5C5E\u76EE\u5F55\uFF08\u4E1A\u52A1\u6A21\u578B\u76EE\u5F55 / ModelDirectory\uFF09\u3002\u8FD4\u56DE\u5404\u4E1A\u52A1\u6A21\u578B\u76EE\u5F55\u9879\uFF0C\u6BCF\u9879\u542B modelcode\uFF08\u5373 modellogic \u4E2D\u7684 modelcode\uFF0C\u67E5\u67D0\u76EE\u5F55\u4E0B\u4E1A\u52A1\u903B\u8F91\u65F6\u8981\u7528\u7684\u7F16\u7801\uFF09\u3001modelname\uFF08\u76EE\u5F55\u540D\uFF09\u3001metamodelcode\u3001directorytypecode\uFF08\u7236\u76EE\u5F55\u7F16\u7801\uFF09\u7B49\u3002
957
+ description: `\u5206\u9875\u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91(\u6A21\u578B\u903B\u8F91/modelLogic/\u9886\u57DF)\u6240\u5C5E\u76EE\u5F55(\u4E1A\u52A1\u6A21\u578B\u76EE\u5F55 / ModelDirectory)\u3002\u8FD4\u56DE\u5404\u4E1A\u52A1\u6A21\u578B\u76EE\u5F55\u9879\uFF0C\u6BCF\u9879\u542B modelcode (\u5373 modellogic \u4E2D\u7684 modelcode\uFF0C\u67E5\u67D0\u76EE\u5F55\u4E0B\u4E1A\u52A1\u903B\u8F91\u65F6\u8981\u7528\u7684\u7F16\u7801)\u3001modelname(\u76EE\u5F55\u540D)\u3001metamodelcode\u3001directorytypecode(\u7236\u76EE\u5F55\u7F16\u7801)\u7B49\u3002
953
958
 
954
959
  \u53EF\u6309 modelname \u6A21\u7CCA\u641C\u7D22\uFF0C\u6216\u4F20\u5165 directorytypecode \u67E5\u8BE2\u67D0\u76EE\u5F55\u4E0B\u7684\u5B50\u76EE\u5F55\uFF08\u9ED8\u8BA4 rootNode \u67E5\u4E00\u7EA7\u76EE\u5F55\uFF09\u3002
955
960
 
@@ -1025,7 +1030,7 @@ ${LOGIC_ENUM}`,
1025
1030
  name: "page_model_logic_list",
1026
1031
  config: {
1027
1032
  title: "\u5206\u9875\u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91",
1028
- description: `\u5206\u9875\u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91\u5217\u8868\uFF08ModelLogic\uFF09\u3002\u652F\u6301\u6309\u6807\u9898/\u7F16\u7801/\u65B9\u6CD5\u540D/\u5173\u952E\u5B57/\u4FEE\u6539\u4EBA/\u7C7B\u578B\u7B5B\u9009\u3002
1033
+ description: `\u5206\u9875\u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91\u5217\u8868(\u6A21\u578B\u903B\u8F91/modelLogic/\u9886\u57DF)\u3002\u652F\u6301\u6309\u6807\u9898/\u7F16\u7801/\u65B9\u6CD5\u540D/\u5173\u952E\u5B57/\u4FEE\u6539\u4EBA/\u7C7B\u578B\u7B5B\u9009\u3002
1029
1034
 
1030
1035
  ${COMMON_ENUM}
1031
1036
  ${LOGIC_ENUM}`,
@@ -1119,7 +1124,7 @@ ${LOGIC_ENUM}`,
1119
1124
  name: "get_model_logic",
1120
1125
  config: {
1121
1126
  title: "\u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91\u8BE6\u60C5",
1122
- description: `\u6309 modellogiccode \u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91\u5B8C\u6574\u8BE6\u60C5\uFF1Aflycode \u811A\u672C\u3001input/output \u53C2\u6570\u53CA\u5B57\u6BB5\u5C5E\u6027\u3001\u64CD\u4F5C\u6B65\u9AA4\u3002\u6CE8\u610F\uFF1A\u8BE6\u60C5\u63A5\u53E3 status \u8FD4\u56DE\u4E0D\u7A33\u5B9A\uFF08\u90E8\u5206\u8C03\u7528\u4E0D\u8FD4\u56DE\uFF09\uFF0Cdatapattern \u662F\u5217\u8868\u63A5\u53E3\u5B57\u6BB5\uFF08\u8BE6\u60C5\u591A\u6570\u4E0D\u8FD4\u56DE\uFF09\u3002
1127
+ description: `\u6309 modellogiccode \u67E5\u8BE2\u4E1A\u52A1\u903B\u8F91(\u6A21\u578B\u903B\u8F91/modelLogic/\u9886\u57DF)\u5B8C\u6574\u8BE6\u60C5\uFF1Aflycode \u811A\u672C\u3001input/output \u53C2\u6570\u53CA\u5B57\u6BB5\u5C5E\u6027\u3001\u64CD\u4F5C\u6B65\u9AA4\u3002
1123
1128
 
1124
1129
  ${COMMON_ENUM}
1125
1130
  ${LOGIC_ENUM}
@@ -2151,7 +2156,7 @@ var init_write = __esm({
2151
2156
  name: "save_model_logic",
2152
2157
  config: {
2153
2158
  title: "\u4FDD\u5B58\u4E1A\u52A1\u903B\u8F91\uFF08\u4EC5\u65B0\u589E / \u6216\u5168\u91CF JSON \u5F88\u5C0F\u5982\u5FAE\u670D\u52A1\uFF09",
2154
- description: `\u5168\u91CF\u4FDD\u5B58\u4E00\u6761\u4E1A\u52A1\u903B\u8F91\u3002\u4EC5\u7528\u4E8E\uFF1A\u2460\u65B0\u589E\uFF1B\u2461\u5DF2\u6709\u903B\u8F91 JSON \u5F88\u5C0F\uFF08\u5982\u5FAE\u670D\u52A1 actioncategory=2\uFF09\u3002\u7F16\u8F91\u666E\u901A flycode \u63A5\u53E3\u7684\u5DF2\u6709\u903B\u8F91\u8BF7\u52FF\u56DE\u4F20\u6574\u4EFD\u5927\u5BF9\u8C61\u2014\u2014\u6539\u811A\u672C\u7528 str_replace_flycode\uFF0C\u6539\u7ED3\u6784/\u5143\u6570\u636E\u7528 patch_model_logic\u3002
2159
+ description: `\u5168\u91CF\u4FDD\u5B58\u4E00\u6761\u4E1A\u52A1\u903B\u8F91(\u6A21\u578B\u903B\u8F91/modelLogic/\u9886\u57DF)\u3002\u4EC5\u7528\u4E8E\uFF1A\u2460\u65B0\u589E\uFF1B\u2461\u5DF2\u6709\u903B\u8F91 JSON \u5F88\u5C0F\uFF08\u5982\u5FAE\u670D\u52A1 actioncategory=2\uFF09\u3002\u7F16\u8F91\u666E\u901A flycode \u63A5\u53E3\u7684\u5DF2\u6709\u903B\u8F91\u8BF7\u52FF\u56DE\u4F20\u6574\u4EFD\u5927\u5BF9\u8C61\u2014\u2014\u6539\u811A\u672C\u7528 str_replace_flycode\uFF0C\u6539\u7ED3\u6784/\u5143\u6570\u636E\u7528 patch_model_logic\u3002
2155
2160
  actioncategory \u679A\u4E3E\u89C1 get_model_logic / page_model_logic_list\u3002
2156
2161
 
2157
2162
  ${COMMON_ENUM}`,
@@ -2202,7 +2207,7 @@ ${COMMON_ENUM}`,
2202
2207
  {
2203
2208
  name: "patch_model_logic",
2204
2209
  config: {
2205
- title: "\u5C40\u90E8\u8865\u4E01\u4FEE\u6539\u4E1A\u52A1\u903B\u8F91\uFF08input/output/\u5143\u6570\u636E\uFF09",
2210
+ title: "\u5C40\u90E8\u8865\u4E01\u4FEE\u6539\u4E1A\u52A1\u903B\u8F91(\u6A21\u578B\u903B\u8F91/modelLogic/\u9886\u57DF)\u7684input/output/\u5143\u6570\u636E",
2206
2211
  description: `\u4EE5 delta ops \u5C40\u90E8\u4FEE\u6539 input/output \u7ED3\u6784\u6216\u9876\u5C42\u5143\u6570\u636E\uFF0C\u65E0\u9700\u56DE\u4F20\u6574\u4EFD LogicResult\u3002ops \u5206\u4E09\u7C7B\uFF1A\u2460input/output \u7ED3\u6784\uFF08add_param/remove_param/set_param_attrs/add_property/remove_property/replace_property\uFF09\uFF1B\u2461\u5143\u6570\u636E\uFF08set_meta\uFF0C\u4E0D\u542B input/output/operations\uFF09\uFF1B\u2462\u5BFC\u51FA\u5217\uFF08\u4EC5 actioncategory=5\uFF1Aadd_export_column/remove_export_column/replace_export_column/set_export_column_attrs/set_bind_meta\uFF09\u3002\u5168\u90E8 op \u9884\u6F14\u6210\u529F\u624D\u843D\u5E93\uFF0C\u4EFB\u4E00\u5931\u8D25\u6574\u6279\u56DE\u6EDA\u3002\u6539 flycode \u811A\u672C\u8BF7\u7528 str_replace_flycode\uFF1B\u5FAE\u670D\u52A1 JSON \u5C0F\u8BF7\u76F4\u63A5\u7528 save_model_logic\u3002
2207
2212
 
2208
2213
  ${COMMON_ENUM}
@@ -2652,7 +2657,7 @@ var init_read2 = __esm({
2652
2657
  name: "page_entity_list",
2653
2658
  config: {
2654
2659
  title: "\u5206\u9875\u67E5\u8BE2\u5B9E\u4F53",
2655
- description: `\u5206\u9875\u67E5\u8BE2\u5B9E\u4F53\u5217\u8868\u3002\u652F\u6301\u6309\u540D\u79F0/\u7C7B\u578B\u7B5B\u9009\u3002
2660
+ description: `\u5206\u9875\u67E5\u8BE2\u5B9E\u4F53(\u6570\u636E\u5E93\u8868)\u5217\u8868\u3002\u652F\u6301\u6309\u540D\u79F0/\u7C7B\u578B\u7B5B\u9009\u3002
2656
2661
 
2657
2662
  ${COMMON_ENUM}
2658
2663
  ${ENTITY_ENUM}`,
@@ -2740,7 +2745,7 @@ ${ENTITY_ENUM}`,
2740
2745
  name: "get_entity",
2741
2746
  config: {
2742
2747
  title: "\u67E5\u8BE2\u5B9E\u4F53\u8BE6\u60C5",
2743
- description: `\u6309 objectcode \u67E5\u8BE2\u5B9E\u4F53\u8BE6\u60C5\uFF1A\u57FA\u672C\u4FE1\u606F\u4E0E\u5C5E\u6027\u6570\u7EC4 properties\u3002\u6CE8\u610F\uFF1A\u8BE6\u60C5\u63A5\u53E3 status \u8FD4\u56DE\u4E0D\u7A33\u5B9A\uFF08\u90E8\u5206\u8C03\u7528\u4E0D\u8FD4\u56DE\uFF09\uFF0Cdatapattern \u662F\u5217\u8868\u63A5\u53E3\u5B57\u6BB5\u3001\u8BE6\u60C5\u591A\u6570\u4E0D\u8FD4\u56DE\u3002
2748
+ description: `\u6309 objectcode \u67E5\u8BE2\u5B9E\u4F53\u8BE6\u60C5\uFF1A\u57FA\u672C\u4FE1\u606F\u4E0E\u5C5E\u6027\u6570\u7EC4 properties\u3002
2744
2749
  propertytypecode \u5B8C\u6574\u679A\u4E3E\u89C1 get_model_logic\u3002
2745
2750
 
2746
2751
  ${COMMON_ENUM}
@@ -2775,9 +2780,8 @@ ${ENTITY_ENUM}`,
2775
2780
  name: "page_entity_directories",
2776
2781
  config: {
2777
2782
  title: "\u67E5\u8BE2\u5B9E\u4F53\u6240\u5C5E\u76EE\u5F55",
2778
- description: `\u67E5\u8BE2\u5B9E\u4F53\uFF08\u6570\u636E\u8868\uFF09\u6240\u5C5E\u76EE\u5F55\uFF08getDirectorys\uFF09\uFF0C\u53D6\u56DE\u7684 directorytypecode \u5373 create_entity \u7684 directorytypecode \u5FC5\u586B\u5165\u53C2\uFF0C\u4E5F\u662F\u4E3A\u5B9E\u4F53\u6307\u5B9A\u76EE\u5F55\u65F6\u8981\u7528\u7684\u7F16\u7801\u3002
2783
+ description: `\u67E5\u8BE2\u5B9E\u4F53\uFF08\u6570\u636E\u8868\uFF09\u6240\u5C5E\u76EE\u5F55\u5217\u8868\uFF0C\u53D6\u56DE\u7684 directorytypecode \u5373\u76EE\u5F55\u7684\u552F\u4E00\u7F16\u7801\uFF0C\u4E3A\u5B9E\u4F53\u6307\u5B9A\u76EE\u5F55\u65F6\u4F7F\u7528\u3002
2779
2784
 
2780
- \u3010\u91CD\u8981\uFF1A\u63A5\u53E3\u4E0D\u652F\u6301\u5206\u9875\uFF0C\u5168\u91CF\u6570\u767E\u6761\uFF0C\u672C\u5DE5\u5177\u5DF2\u5F3A\u5236\u6536\u655B\u3011
2781
2785
  - \u9ED8\u8BA4\u6700\u591A\u56DE ${DIRECTORY_DEFAULT_LIMIT} \u6761\uFF0C\u786C\u4E0A\u9650 ${DIRECTORY_MAX_LIMIT} \u6761\uFF1B
2782
2786
  - \u672A\u4F20\u4EFB\u4F55\u7B5B\u9009\u6761\u4EF6\u65F6\uFF0C\u53EA\u56DE\u9876\u7EA7\u76EE\u5F55\uFF08\u901A\u5E38\u5341\u4F59\u6761\u91CF\u7EA7\uFF09\u5E76\u5728 hint \u4E2D\u8BF4\u660E\uFF1B
2783
2787
  - \u547D\u4E2D\u8FC7\u591A\u65F6 truncated=true\uFF0C\u8BF7\u7F29\u5C0F keys \u6216\u7528 offset \u7FFB\u9875\u3002
@@ -4636,7 +4640,6 @@ var init_read3 = __esm({
4636
4640
  title: "\u67E5\u8BE2\u8868\u5355\u6240\u5C5E\u76EE\u5F55",
4637
4641
  description: `\u67E5\u8BE2\u8868\u5355/\u9875\u9762\u6240\u5C5E\u76EE\u5F55\uFF08getDirectorys\uFF09\uFF0C\u53D6\u56DE\u7684 directorytypecode \u5373\u8868\u5355 pageinfo.directorytypecode \u7684\u53D6\u503C\uFF0C\u4E5F\u662F\u6309\u76EE\u5F55\u7B5B\u8868\u5355\u3001\u6216\u4E3A\u8868\u5355\u6307\u5B9A\u76EE\u5F55\u65F6\u8981\u7528\u7684\u7F16\u7801\u3002
4638
4642
 
4639
- \u3010\u91CD\u8981\uFF1A\u63A5\u53E3\u4E0D\u652F\u6301\u5206\u9875\uFF0C\u5168\u91CF\u6570\u767E\u6761\uFF0C\u672C\u5DE5\u5177\u5DF2\u5F3A\u5236\u6536\u655B\u3011
4640
4643
  - \u9ED8\u8BA4\u6700\u591A\u56DE ${DIRECTORY_DEFAULT_LIMIT} \u6761\uFF0C\u786C\u4E0A\u9650 ${DIRECTORY_MAX_LIMIT} \u6761\uFF1B
4641
4644
  - \u672A\u4F20\u4EFB\u4F55\u7B5B\u9009\u6761\u4EF6\u65F6\uFF0C\u53EA\u56DE\u9876\u7EA7\u76EE\u5F55\uFF08\u901A\u5E38\u5341\u6761\u91CF\u7EA7\uFF09\u5E76\u5728 hint \u4E2D\u8BF4\u660E\uFF1B
4642
4645
  - \u547D\u4E2D\u8FC7\u591A\u65F6 truncated=true\uFF0C\u8BF7\u7F29\u5C0F keys \u6216\u7528 offset \u7FFB\u9875\u3002
@@ -5705,7 +5708,8 @@ var init_read7 = __esm({
5705
5708
  name: "run_sql",
5706
5709
  config: {
5707
5710
  title: "\u6267\u884C SQL \u67E5\u8BE2",
5708
- description: "\u5728\u4E1A\u52A1\u5E93\uFF08PostgreSQL\uFF09\u4E2D\u6267\u884C\u4E00\u6761 SELECT \u67E5\u8BE2\uFF08\u63A5\u53E3\u4EC5\u652F\u6301 SELECT\uFF0C\u4E00\u6B21\u4E00\u6761\uFF0C\u53EA\u80FD\u67E5\u4E1A\u52A1\u8868\uFF1B\u67E5\u8868\u5B57\u6BB5\u7ED3\u6784\u8BF7\u7528 get_entity\uFF09\uFF0C\u8FD4\u56DE\u7ED3\u679C data \u4E0E\u603B\u6570 influenceCount\u3002\u9002\u7528\u4E8E\u76F4\u63A5\u63A2\u67E5\u4E1A\u52A1\u8868\u6570\u636E\u3001\u6838\u5BF9\u5B57\u6BB5\u503C\u3001\u9A8C\u8BC1\u540C\u6B65\u7ED3\u679C\u7B49\u53EA\u8BFB\u573A\u666F\u3002",
5711
+ description: `\u5728\u4E1A\u52A1\u5E93\uFF08PostgreSQL\uFF09\u4E2D\u6267\u884C\u4E00\u6761 SELECT \u67E5\u8BE2\uFF08\u63A5\u53E3\u4EC5\u652F\u6301 SELECT\uFF0C\u4E00\u6B21\u4E00\u6761\uFF0C\u53EA\u80FD\u67E5\u4E1A\u52A1\u8868\uFF1B\u67E5\u8868\u5B57\u6BB5\u7ED3\u6784\u8BF7\u7528 get_entity\uFF09\uFF0C\u8FD4\u56DE\u7ED3\u679C data \u4E0E\u603B\u6570 influenceCount\u3002\u9002\u7528\u4E8E\u76F4\u63A5\u63A2\u67E5\u4E1A\u52A1\u8868\u6570\u636E\u3001\u6838\u5BF9\u5B57\u6BB5\u503C\u3001\u9A8C\u8BC1\u540C\u6B65\u7ED3\u679C\u7B49\u53EA\u8BFB\u573A\u666F\u3002
5712
+ \u6CE8\u610F\uFF1A\u67E5\u8BE2\u7684\u5B57\u6BB5\u548C\u8868\u5FC5\u987B\u5728 get_entity \u4E2D\u80FD\u53D6\u5230\uFF1B\u53EA\u80FD\u7528\u57FA\u7840\u7684\u7B80\u5355\u67E5\u8BE2\u8BED\u53E5\uFF0C\u4E0D\u652F\u6301 WITH \u7B49\u590D\u6742\u8BED\u53E5\uFF1B\u6700\u7EC8\u5B9E\u9645\u6267\u884C\u7684 SQL \u4F1A\u88AB\u5F15\u64CE\u5904\u7406\uFF0C\u4E0D\u652F\u6301 platstatus \u7B49\u5E73\u53F0\u5B57\u6BB5\u3002`,
5709
5713
  inputSchema: {
5710
5714
  sql: z14.string().describe("\u8981\u6267\u884C\u7684 SQL \u67E5\u8BE2\u8BED\u53E5\uFF0C\u53EA\u652F\u6301 SELECT \u67E5\u8BE2\uFF0C\u4E00\u6B21\u53EA\u80FD\u4E00\u6761 SQL")
5711
5715
  },
@@ -6145,7 +6149,7 @@ var init_trash = __esm({
6145
6149
  // src/cli/skill.ts
6146
6150
  import {
6147
6151
  cpSync,
6148
- existsSync,
6152
+ existsSync as existsSync2,
6149
6153
  mkdirSync,
6150
6154
  readFileSync as readFileSync2,
6151
6155
  readdirSync,
@@ -6157,11 +6161,11 @@ import {
6157
6161
  import { dirname as dirname2, join as join3 } from "node:path";
6158
6162
  function inspectSkillDest(destDir, source) {
6159
6163
  const mainPath = join3(destDir, MAIN_FILE);
6160
- if (!existsSync(mainPath)) {
6164
+ if (!existsSync2(mainPath)) {
6161
6165
  return { exists: false, hasMarker: false, markerVersion: null, contentMatchesSource: null };
6162
6166
  }
6163
6167
  const markerPath = join3(destDir, MARKER_FILE);
6164
- const hasMarker = existsSync(markerPath);
6168
+ const hasMarker = existsSync2(markerPath);
6165
6169
  let markerVersion = null;
6166
6170
  if (hasMarker) {
6167
6171
  try {
@@ -6172,7 +6176,7 @@ function inspectSkillDest(destDir, source) {
6172
6176
  }
6173
6177
  }
6174
6178
  let contentMatchesSource = null;
6175
- if (source !== void 0 && existsSync(join3(source.dir, MAIN_FILE))) {
6179
+ if (source !== void 0 && existsSync2(join3(source.dir, MAIN_FILE))) {
6176
6180
  contentMatchesSource = readFileSync2(mainPath, "utf8") === readFileSync2(join3(source.dir, MAIN_FILE), "utf8");
6177
6181
  }
6178
6182
  return { exists: true, hasMarker, markerVersion, contentMatchesSource };
@@ -6182,7 +6186,7 @@ function installSkill(options) {
6182
6186
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
6183
6187
  const trashFn = options.trashFn ?? nativeTrashFn();
6184
6188
  const sourceMain = join3(source.dir, MAIN_FILE);
6185
- if (!existsSync(sourceMain) || !statSync(sourceMain).isFile()) {
6189
+ if (!existsSync2(sourceMain) || !statSync(sourceMain).isFile()) {
6186
6190
  return {
6187
6191
  status: "failed",
6188
6192
  reason: `skill \u6E90\u76EE\u5F55\u7F3A\u5C11 ${MAIN_FILE}\uFF1A${source.dir}`,
@@ -6191,7 +6195,7 @@ function installSkill(options) {
6191
6195
  }
6192
6196
  const parentDir = parentOf(destDir);
6193
6197
  const destMain = join3(destDir, MAIN_FILE);
6194
- const destExists = existsSync(destMain);
6198
+ const destExists = existsSync2(destMain);
6195
6199
  if (destExists) {
6196
6200
  const destIsDir = (() => {
6197
6201
  try {
@@ -6320,7 +6324,7 @@ function verifyInstalled(destDir, source) {
6320
6324
  function sameFileSet(destDir, sourceDir) {
6321
6325
  try {
6322
6326
  const dest = listFiles(destDir).filter((name) => name !== MARKER_FILE);
6323
- return dest.length === listFiles(sourceDir).length && dest.every((name) => existsSync(join3(sourceDir, name)));
6327
+ return dest.length === listFiles(sourceDir).length && dest.every((name) => existsSync2(join3(sourceDir, name)));
6324
6328
  } catch {
6325
6329
  return false;
6326
6330
  }
@@ -6340,7 +6344,7 @@ function listFiles(root) {
6340
6344
  return out.sort();
6341
6345
  }
6342
6346
  function cleanStaleStaging(parentDir) {
6343
- if (!existsSync(parentDir)) return;
6347
+ if (!existsSync2(parentDir)) return;
6344
6348
  for (const entry of readdirSync(parentDir)) {
6345
6349
  if (entry.startsWith(STAGING_PREFIX)) {
6346
6350
  rmSync(join3(parentDir, entry), { recursive: true, force: true });
@@ -6641,7 +6645,7 @@ __export(update_exports, {
6641
6645
  runUpdateCommand: () => runUpdateCommand
6642
6646
  });
6643
6647
  import { spawnSync as spawnSync2 } from "node:child_process";
6644
- import { existsSync as existsSync2, readFileSync as readFileSync3, realpathSync } from "node:fs";
6648
+ import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync } from "node:fs";
6645
6649
  import { join as join4 } from "node:path";
6646
6650
  function detectInstallation(packageRoot, platform = process.platform, spawnFn = defaultSpawn2) {
6647
6651
  if (packageRoot.includes(join4(".bun", "install", "global", "node_modules"))) {
@@ -6745,7 +6749,7 @@ function installWithPackageManager(installation, target) {
6745
6749
  }
6746
6750
  function defaultVerifyInstalledVersion(installation) {
6747
6751
  const pkgPath = join4(installation.packageRoot, "package.json");
6748
- if (!existsSync2(pkgPath)) return null;
6752
+ if (!existsSync3(pkgPath)) return null;
6749
6753
  try {
6750
6754
  const parsed = JSON.parse(readFileSync3(pkgPath, "utf8"));
6751
6755
  return typeof parsed.version === "string" ? parsed.version : null;