qiaotong-agent-kit 0.2.0__tar.gz

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.
Files changed (46) hide show
  1. qiaotong_agent_kit-0.2.0/PKG-INFO +165 -0
  2. qiaotong_agent_kit-0.2.0/README.md +148 -0
  3. qiaotong_agent_kit-0.2.0/pyproject.toml +40 -0
  4. qiaotong_agent_kit-0.2.0/setup.cfg +4 -0
  5. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/__init__.py +22 -0
  6. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/adapter.py +160 -0
  7. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/bridge_model.py +433 -0
  8. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/cli.py +75 -0
  9. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/continuous_beam.py +307 -0
  10. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/continuous_beam_rules.py +211 -0
  11. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/frame_orientation.py +75 -0
  12. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/mcp_server.py +225 -0
  13. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/modeling_rules.py +204 -0
  14. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/privacy.py +81 -0
  15. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/arch_bridge.evidence.json +143 -0
  16. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/arch_bridge.rules.json +131 -0
  17. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/cable_stayed_bridge.evidence.json +1161 -0
  18. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/cable_stayed_bridge.rules.json +153 -0
  19. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/cable_stayed_suspension_bridge.evidence.json +35 -0
  20. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/cable_stayed_suspension_bridge.rules.json +113 -0
  21. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/cable_supported_unclassified.evidence.json +129 -0
  22. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/cable_supported_unclassified.rules.json +126 -0
  23. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/catalog.json +118 -0
  24. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/composite_girder_bridge.evidence.json +70 -0
  25. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/composite_girder_bridge.rules.json +99 -0
  26. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/continuous_beam_bridge.evidence.json +479 -0
  27. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/continuous_beam_bridge.rules.json +121 -0
  28. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/continuous_rigid_frame_bridge.evidence.json +254 -0
  29. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/continuous_rigid_frame_bridge.rules.json +131 -0
  30. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/other_complete_bridge.evidence.json +226 -0
  31. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/other_complete_bridge.rules.json +133 -0
  32. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/simply_supported_beam_bridge.evidence.json +104 -0
  33. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/simply_supported_beam_bridge.rules.json +97 -0
  34. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/suspension_bridge.evidence.json +377 -0
  35. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/resources/modeling_rules/suspension_bridge.rules.json +148 -0
  36. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/service.py +421 -0
  37. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit/tool_schema.py +33 -0
  38. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit.egg-info/PKG-INFO +165 -0
  39. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit.egg-info/SOURCES.txt +44 -0
  40. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit.egg-info/dependency_links.txt +1 -0
  41. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit.egg-info/entry_points.txt +5 -0
  42. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit.egg-info/requires.txt +6 -0
  43. qiaotong_agent_kit-0.2.0/src/qiaotong_agent_kit.egg-info/top_level.txt +1 -0
  44. qiaotong_agent_kit-0.2.0/tests/test_continuous_beam.py +182 -0
  45. qiaotong_agent_kit-0.2.0/tests/test_modeling_rules.py +75 -0
  46. qiaotong_agent_kit-0.2.0/tests/test_service.py +68 -0
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.4
2
+ Name: qiaotong-agent-kit
3
+ Version: 0.2.0
4
+ Summary: Agent-safe tools for Qiaotong bridge finite element modeling
5
+ Author: Qiaotong Agent Kit Maintainers
6
+ Keywords: bridge,finite-element,agent,qtmodel,mcp
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Classifier: Topic :: Scientific/Engineering
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: qtmodel<3.0,>=2.5.0
15
+ Provides-Extra: mcp
16
+ Requires-Dist: mcp<2,>=1.27; python_version >= "3.10" and extra == "mcp"
17
+
18
+ # qiaotong-agent-kit
19
+
20
+ 桥通有限元软件的 Agent 工具适配层。该包与 `qtmodel` 独立发行:工程模型、
21
+ 截面几何和截面特性算法仍由 `qtmodel` 提供,本包只负责为 Agent 暴露稳定、
22
+ 可发现、JSON 可序列化的受控工具。
23
+
24
+ ## 安装
25
+
26
+ ```bash
27
+ pip install qiaotong-agent-kit
28
+ ```
29
+
30
+ 如需 MCP stdio 服务(Python 3.10 及以上):
31
+
32
+ ```bash
33
+ pip install "qiaotong-agent-kit[mcp]"
34
+ qiaotong-mcp
35
+ ```
36
+
37
+ 安装包会自动安装 `qtmodel>=2.5.0`,并内置脱敏后的桥型规则和匿名参考证据;
38
+ 不需要复制开发机上的 `qtmodels` 目录,也不会发布原始模型脚本、模型名或文件路径。
39
+
40
+ ## Python 调用
41
+
42
+ ```python
43
+ from qiaotong_agent_kit import SectionToolService
44
+
45
+ service = SectionToolService()
46
+ result = service.invoke("calculate_parameter_section_property", {
47
+ "sec_type": "矩形",
48
+ "sec_info": {"W": 2.0, "H": 1.0},
49
+ })
50
+ print(result["property"]["Ax"])
51
+ ```
52
+
53
+ ## JSON-lines 子进程协议
54
+
55
+ ```bash
56
+ qiaotong-agent-kit list-tools
57
+ qiaotong-agent-kit serve
58
+ ```
59
+
60
+ `serve` 从标准输入逐行接收:
61
+
62
+ ```json
63
+ {"id": 1, "tool": "calculate_parameter_section_property", "arguments": {"sec_type": "矩形", "sec_info": {"W": 2, "H": 1}}}
64
+ ```
65
+
66
+ 并逐行返回:
67
+
68
+ ```json
69
+ {"id": 1, "ok": true, "result": {}}
70
+ ```
71
+
72
+ 本地截面计算和连续梁计划不需要打开桥通。读取、审查、建模和恢复工具会连接
73
+ 桥通 HTTP 服务。
74
+
75
+ ## 脱敏参考规则库
76
+
77
+ Agent 应先查询规则,再生成建模计划:
78
+
79
+ ```python
80
+ from qiaotong_agent_kit import QiaotongToolService
81
+
82
+ service = QiaotongToolService()
83
+ catalog = service.invoke("get_modeling_rule_catalog")
84
+ rule = service.invoke("get_modeling_rule", {"bridge_type": "连续梁桥"})
85
+ evidence = service.invoke("search_reference_evidence", {
86
+ "bridge_type": "连续梁桥",
87
+ "spans": "30+40+30",
88
+ "standard": "JTG D60-2015",
89
+ "limit": 3,
90
+ })
91
+ ```
92
+
93
+ 规则资源随 wheel 发布,包含十类桥型的建模规则和 62 个匿名参考记录的技术统计。
94
+ 参考结果只用于归纳结构、阶段和荷载规律;其中不包含原始 `build_model.py`,也不允许
95
+ 从匿名编号反推项目或桥梁名称。
96
+
97
+ ## 连续梁一键建模
98
+
99
+ 用户只需要提供三个工程输入:规范、跨度和桥型。例如:
100
+
101
+ ```python
102
+ from qiaotong_agent_kit import QiaotongToolService
103
+
104
+ service = QiaotongToolService()
105
+ plan = service.invoke("plan_continuous_beam", {
106
+ "design_code": "JTG D60-2015",
107
+ "spans": "2×30+40+2×30",
108
+ "bridge_type": "预应力混凝土连续梁",
109
+ })
110
+ ```
111
+
112
+ 计划会自动生成材料、等效箱形截面、沿桥向网格、逐跨结构组、支承、结构自重、
113
+ 规范移动荷载和运营分析设置,并把所有默认值写入 `assumptions` 和 `warnings`。
114
+
115
+ 整体坐标固定为:
116
+
117
+ - 主梁沿整体 `+X`;
118
+ - 横桥向为整体 `+Y`;
119
+ - 竖向及桥塔正方向为整体 `+Z`;
120
+ - 主梁单元 I 端在小 X 侧、J 端在大 X 侧;
121
+ - 单元局部轴遵循桥通源码
122
+ `FrameElement.UpdateLocalOrientation`,Agent 只负责节点顺序和 beta 角。
123
+
124
+ 真正写入模型前应先向用户展示计划。`build_continuous_beam` 的
125
+ `confirm_replace=true` 只是危险操作确认,不是第四个工程参数。写入过程会先保存当前
126
+ 模型快照,失败时自动恢复;成功后返回快照路径和读回审查结果。自动生成的是概念/
127
+ 初始分析模型,当前不会自动设计预应力束,也不会替代正式设计复核。
128
+
129
+ 当前支持 JTG D60-2015、JTG 3362-2018、CJJ 11-2019、TB 10002-2017、
130
+ TB 10092-2017,以及预应力混凝土连续箱梁和钢连续箱梁。可调用
131
+ `list_continuous_beam_defaults` 获取机器可读清单。
132
+
133
+ ## 在 QpyIDE 中配置 MCP
134
+
135
+ 推荐把只读与建模能力拆成两个 MCP 入口:
136
+
137
+ ```text
138
+ qiaotong-readonly-mcp # 截面、计划、模型摘要和审查,不暴露写模型工具
139
+ qiaotong-model-mcp # 包含建模与快照恢复,QpyIDE 应对工具调用弹出确认
140
+ ```
141
+
142
+ QpyIDE 的 Agent 应遵循以下调用顺序:
143
+
144
+ 1. 调用 `plan_continuous_beam`,把假设、警告、节点/单元/支点数量展示给用户;
145
+ 2. 用户确认后调用 `build_continuous_beam`;
146
+ 3. 检查返回的 `audit`,有 error 时不发起计算;
147
+ 4. 需要撤销时,使用返回的 `snapshot_path` 调用 `restore_model_snapshot`。
148
+
149
+ 模型审查无 error 后,QpyIDE 可先请求用户确认并调用 `solve_current_model`。求解完成后,
150
+ 使用 `get_bridge_result` 提取明确范围的结果:
151
+
152
+ - `deformation`:节点变形;
153
+ - `element_force`:单元内力;
154
+ - `element_stress`:单元应力;
155
+ - `reaction`:节点反力。
156
+
157
+ 运营阶段查询使用 `stage_id=-1` 并必须指定 `case_name`;`ids` 必须明确给出,默认最多
158
+ 返回 500 行,避免自然语言误操作导出整个大型模型。
159
+
160
+ 检查当前打开模型时,可用 `audit_bridge_model` 做全局拓扑/支承/坐标审查;对“检查
161
+ 第 N 号单元截面是否正常”这类问题,使用 `inspect_bridge_element` 一次读取该单元的
162
+ I/J 节点、材料截面号、截面数据、截面特性和按源码计算的局部坐标系。
163
+
164
+ CLI 和 `list-tools` 输出为每个工具提供 `mutates_model`、`risk_level`、
165
+ `requires_confirmation`、`undoable` 元数据,QpyIDE 可据此统一实施审批策略。
@@ -0,0 +1,148 @@
1
+ # qiaotong-agent-kit
2
+
3
+ 桥通有限元软件的 Agent 工具适配层。该包与 `qtmodel` 独立发行:工程模型、
4
+ 截面几何和截面特性算法仍由 `qtmodel` 提供,本包只负责为 Agent 暴露稳定、
5
+ 可发现、JSON 可序列化的受控工具。
6
+
7
+ ## 安装
8
+
9
+ ```bash
10
+ pip install qiaotong-agent-kit
11
+ ```
12
+
13
+ 如需 MCP stdio 服务(Python 3.10 及以上):
14
+
15
+ ```bash
16
+ pip install "qiaotong-agent-kit[mcp]"
17
+ qiaotong-mcp
18
+ ```
19
+
20
+ 安装包会自动安装 `qtmodel>=2.5.0`,并内置脱敏后的桥型规则和匿名参考证据;
21
+ 不需要复制开发机上的 `qtmodels` 目录,也不会发布原始模型脚本、模型名或文件路径。
22
+
23
+ ## Python 调用
24
+
25
+ ```python
26
+ from qiaotong_agent_kit import SectionToolService
27
+
28
+ service = SectionToolService()
29
+ result = service.invoke("calculate_parameter_section_property", {
30
+ "sec_type": "矩形",
31
+ "sec_info": {"W": 2.0, "H": 1.0},
32
+ })
33
+ print(result["property"]["Ax"])
34
+ ```
35
+
36
+ ## JSON-lines 子进程协议
37
+
38
+ ```bash
39
+ qiaotong-agent-kit list-tools
40
+ qiaotong-agent-kit serve
41
+ ```
42
+
43
+ `serve` 从标准输入逐行接收:
44
+
45
+ ```json
46
+ {"id": 1, "tool": "calculate_parameter_section_property", "arguments": {"sec_type": "矩形", "sec_info": {"W": 2, "H": 1}}}
47
+ ```
48
+
49
+ 并逐行返回:
50
+
51
+ ```json
52
+ {"id": 1, "ok": true, "result": {}}
53
+ ```
54
+
55
+ 本地截面计算和连续梁计划不需要打开桥通。读取、审查、建模和恢复工具会连接
56
+ 桥通 HTTP 服务。
57
+
58
+ ## 脱敏参考规则库
59
+
60
+ Agent 应先查询规则,再生成建模计划:
61
+
62
+ ```python
63
+ from qiaotong_agent_kit import QiaotongToolService
64
+
65
+ service = QiaotongToolService()
66
+ catalog = service.invoke("get_modeling_rule_catalog")
67
+ rule = service.invoke("get_modeling_rule", {"bridge_type": "连续梁桥"})
68
+ evidence = service.invoke("search_reference_evidence", {
69
+ "bridge_type": "连续梁桥",
70
+ "spans": "30+40+30",
71
+ "standard": "JTG D60-2015",
72
+ "limit": 3,
73
+ })
74
+ ```
75
+
76
+ 规则资源随 wheel 发布,包含十类桥型的建模规则和 62 个匿名参考记录的技术统计。
77
+ 参考结果只用于归纳结构、阶段和荷载规律;其中不包含原始 `build_model.py`,也不允许
78
+ 从匿名编号反推项目或桥梁名称。
79
+
80
+ ## 连续梁一键建模
81
+
82
+ 用户只需要提供三个工程输入:规范、跨度和桥型。例如:
83
+
84
+ ```python
85
+ from qiaotong_agent_kit import QiaotongToolService
86
+
87
+ service = QiaotongToolService()
88
+ plan = service.invoke("plan_continuous_beam", {
89
+ "design_code": "JTG D60-2015",
90
+ "spans": "2×30+40+2×30",
91
+ "bridge_type": "预应力混凝土连续梁",
92
+ })
93
+ ```
94
+
95
+ 计划会自动生成材料、等效箱形截面、沿桥向网格、逐跨结构组、支承、结构自重、
96
+ 规范移动荷载和运营分析设置,并把所有默认值写入 `assumptions` 和 `warnings`。
97
+
98
+ 整体坐标固定为:
99
+
100
+ - 主梁沿整体 `+X`;
101
+ - 横桥向为整体 `+Y`;
102
+ - 竖向及桥塔正方向为整体 `+Z`;
103
+ - 主梁单元 I 端在小 X 侧、J 端在大 X 侧;
104
+ - 单元局部轴遵循桥通源码
105
+ `FrameElement.UpdateLocalOrientation`,Agent 只负责节点顺序和 beta 角。
106
+
107
+ 真正写入模型前应先向用户展示计划。`build_continuous_beam` 的
108
+ `confirm_replace=true` 只是危险操作确认,不是第四个工程参数。写入过程会先保存当前
109
+ 模型快照,失败时自动恢复;成功后返回快照路径和读回审查结果。自动生成的是概念/
110
+ 初始分析模型,当前不会自动设计预应力束,也不会替代正式设计复核。
111
+
112
+ 当前支持 JTG D60-2015、JTG 3362-2018、CJJ 11-2019、TB 10002-2017、
113
+ TB 10092-2017,以及预应力混凝土连续箱梁和钢连续箱梁。可调用
114
+ `list_continuous_beam_defaults` 获取机器可读清单。
115
+
116
+ ## 在 QpyIDE 中配置 MCP
117
+
118
+ 推荐把只读与建模能力拆成两个 MCP 入口:
119
+
120
+ ```text
121
+ qiaotong-readonly-mcp # 截面、计划、模型摘要和审查,不暴露写模型工具
122
+ qiaotong-model-mcp # 包含建模与快照恢复,QpyIDE 应对工具调用弹出确认
123
+ ```
124
+
125
+ QpyIDE 的 Agent 应遵循以下调用顺序:
126
+
127
+ 1. 调用 `plan_continuous_beam`,把假设、警告、节点/单元/支点数量展示给用户;
128
+ 2. 用户确认后调用 `build_continuous_beam`;
129
+ 3. 检查返回的 `audit`,有 error 时不发起计算;
130
+ 4. 需要撤销时,使用返回的 `snapshot_path` 调用 `restore_model_snapshot`。
131
+
132
+ 模型审查无 error 后,QpyIDE 可先请求用户确认并调用 `solve_current_model`。求解完成后,
133
+ 使用 `get_bridge_result` 提取明确范围的结果:
134
+
135
+ - `deformation`:节点变形;
136
+ - `element_force`:单元内力;
137
+ - `element_stress`:单元应力;
138
+ - `reaction`:节点反力。
139
+
140
+ 运营阶段查询使用 `stage_id=-1` 并必须指定 `case_name`;`ids` 必须明确给出,默认最多
141
+ 返回 500 行,避免自然语言误操作导出整个大型模型。
142
+
143
+ 检查当前打开模型时,可用 `audit_bridge_model` 做全局拓扑/支承/坐标审查;对“检查
144
+ 第 N 号单元截面是否正常”这类问题,使用 `inspect_bridge_element` 一次读取该单元的
145
+ I/J 节点、材料截面号、截面数据、截面特性和按源码计算的局部坐标系。
146
+
147
+ CLI 和 `list-tools` 输出为每个工具提供 `mutates_model`、`risk_level`、
148
+ `requires_confirmation`、`undoable` 元数据,QpyIDE 可据此统一实施审批策略。
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.3", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "qiaotong-agent-kit"
7
+ version = "0.2.0"
8
+ description = "Agent-safe tools for Qiaotong bridge finite element modeling"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ authors = [{name = "Qiaotong Agent Kit Maintainers"}]
12
+ keywords = ["bridge", "finite-element", "agent", "qtmodel", "mcp"]
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Intended Audience :: Developers",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ "Topic :: Scientific/Engineering",
19
+ ]
20
+ dependencies = [
21
+ "qtmodel>=2.5.0,<3.0",
22
+ ]
23
+
24
+ [project.optional-dependencies]
25
+ mcp = ["mcp>=1.27,<2; python_version >= '3.10'"]
26
+
27
+ [project.scripts]
28
+ qiaotong-agent-kit = "qiaotong_agent_kit.cli:main"
29
+ qiaotong-mcp = "qiaotong_agent_kit.mcp_server:main"
30
+ qiaotong-readonly-mcp = "qiaotong_agent_kit.mcp_server:readonly_main"
31
+ qiaotong-model-mcp = "qiaotong_agent_kit.mcp_server:model_main"
32
+
33
+ [tool.setuptools]
34
+ package-dir = {"" = "src"}
35
+
36
+ [tool.setuptools.packages.find]
37
+ where = ["src"]
38
+
39
+ [tool.setuptools.package-data]
40
+ qiaotong_agent_kit = ["resources/modeling_rules/*.json"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,22 @@
1
+ """桥通 Agent 的独立工具适配包。"""
2
+
3
+ from .adapter import QtModelSectionAdapter
4
+ from .bridge_model import BridgeModelService, QtModelBridgeAdapter
5
+ from .continuous_beam import ContinuousBeamPlanner, validate_continuous_beam_plan
6
+ from .modeling_rules import ModelingRuleLibrary
7
+ from .service import QiaotongToolService, SectionToolService
8
+ from .tool_schema import ToolDefinition
9
+
10
+ __version__ = "0.2.0"
11
+
12
+ __all__ = [
13
+ "QtModelSectionAdapter",
14
+ "QtModelBridgeAdapter",
15
+ "BridgeModelService",
16
+ "ContinuousBeamPlanner",
17
+ "validate_continuous_beam_plan",
18
+ "ModelingRuleLibrary",
19
+ "SectionToolService",
20
+ "QiaotongToolService",
21
+ "ToolDefinition",
22
+ ]
@@ -0,0 +1,160 @@
1
+ """qtmodel 的窄接口适配器。
2
+
3
+ Agent 不直接接触 mdb 全局门面。本适配器只调用 qtmodel 的公开、确定性接口;
4
+ 唯一连接桥通的方法在名称和返回元数据中均明确标识。
5
+ """
6
+
7
+ from importlib.metadata import PackageNotFoundError, version
8
+ from typing import Any, Dict, Mapping, Optional, Sequence
9
+
10
+ from qtmodel.core.section_db import SectionDB
11
+ from qtmodel.core.section_geometry import SectionGeometryDB
12
+ from qtmodel.core.section_property_solver import SectionPropertySolver
13
+
14
+
15
+ def _package_version(name: str) -> str:
16
+ try:
17
+ return version(name)
18
+ except PackageNotFoundError:
19
+ return "editable"
20
+
21
+
22
+ class QtModelSectionAdapter:
23
+ """面向 Agent 的无状态截面适配器。"""
24
+
25
+ @staticmethod
26
+ def capabilities() -> Dict[str, Any]:
27
+ return {
28
+ "agent_kit_version": _package_version("qiaotong-agent-kit"),
29
+ "qtmodel_version": _package_version("qtmodel"),
30
+ "coordinate_unit": "m",
31
+ "thickness_unit": "m",
32
+ "area_unit": "m²",
33
+ "inertia_unit": "m⁴",
34
+ "local_section_property": {
35
+ "calculated": [
36
+ "Ax", "CentY", "CentZ", "Iy", "Iz", "Iyz", "PeriO",
37
+ "PeriI", "bounding_box", "control_points",
38
+ ],
39
+ "not_calculated": [
40
+ "Ay", "Az", "Ix", "ShearCenterY", "ShearCenterZ",
41
+ "Hys", "Hzs", "Sys", "Szs",
42
+ ],
43
+ "requires_bridge": False,
44
+ },
45
+ }
46
+
47
+ @staticmethod
48
+ def list_section_types() -> Dict[str, Any]:
49
+ return {
50
+ "section_types": list(SectionDB.supported_types()),
51
+ "count": len(SectionDB.supported_types()),
52
+ }
53
+
54
+ @staticmethod
55
+ def get_section_schema(sec_type: str) -> Dict[str, Any]:
56
+ schema = SectionDB.get_schema(sec_type)
57
+ schema["geometry_source"] = SectionGeometryDB.get_source_info(schema["sec_type"])
58
+ schema["local_property_solver"] = {
59
+ "method": "calculate_parameter_section_property",
60
+ "requires_bridge": False,
61
+ "units": {"length": "m", "area": "m²", "inertia": "m⁴"},
62
+ }
63
+ return schema
64
+
65
+ @staticmethod
66
+ def parameter_section_shape(
67
+ sec_type: str,
68
+ sec_info: Mapping[str, Any],
69
+ name: str = "",
70
+ ) -> Dict[str, Any]:
71
+ kwargs = SectionDB.build_parameter_section_kwargs(sec_type, sec_info)
72
+ shape = SectionGeometryDB.generate(
73
+ kwargs["sec_type"],
74
+ kwargs["sec_info"],
75
+ name=name or f"{kwargs['sec_type']}预览",
76
+ symmetry=kwargs.get("symmetry", True),
77
+ chamfer_info=kwargs.get("chamfer_info"),
78
+ box_num=kwargs.get("box_num", 3),
79
+ box_height=kwargs.get("box_height", 2),
80
+ )
81
+ return shape.to_dict()
82
+
83
+ @staticmethod
84
+ def calculate_parameter_section_property(
85
+ sec_type: str,
86
+ sec_info: Mapping[str, Any],
87
+ mat_combine: Optional[Sequence[float]] = None,
88
+ reference_role: str = "main",
89
+ ) -> Dict[str, Any]:
90
+ if mat_combine is not None and len(mat_combine) != 5:
91
+ raise ValueError("mat_combine 必须包含5个组合材料参数")
92
+ kwargs = SectionDB.build_parameter_section_kwargs(sec_type, sec_info)
93
+ shape = SectionGeometryDB.generate(
94
+ kwargs["sec_type"],
95
+ kwargs["sec_info"],
96
+ symmetry=kwargs.get("symmetry", True),
97
+ chamfer_info=kwargs.get("chamfer_info"),
98
+ box_num=kwargs.get("box_num", 3),
99
+ box_height=kwargs.get("box_height", 2),
100
+ )
101
+ result = SectionPropertySolver.calculate_detailed(
102
+ shape,
103
+ elastic_modulus_ratio=(float(mat_combine[0]) if mat_combine else None),
104
+ reference_role=reference_role,
105
+ )
106
+ data = result.to_dict()
107
+ data["shape"] = shape.to_dict()
108
+ data["requires_bridge"] = False
109
+ return data
110
+
111
+ @staticmethod
112
+ def calculate_custom_loop_property(
113
+ loop_segments: Sequence[Mapping[str, Any]],
114
+ secondary_loop_segments: Optional[Sequence[Mapping[str, Any]]] = None,
115
+ elastic_modulus_ratio: Optional[float] = None,
116
+ reference_role: str = "main",
117
+ ) -> Dict[str, Any]:
118
+ sec_type = "自定义组合截面" if secondary_loop_segments else "自定义线圈截面"
119
+ shape = SectionGeometryDB.generate(
120
+ sec_type,
121
+ loop_segments=list(loop_segments),
122
+ secondary_loop_segments=(
123
+ list(secondary_loop_segments) if secondary_loop_segments else None
124
+ ),
125
+ )
126
+ result = SectionPropertySolver.calculate_detailed(
127
+ shape,
128
+ elastic_modulus_ratio=elastic_modulus_ratio,
129
+ reference_role=reference_role,
130
+ )
131
+ data = result.to_dict()
132
+ data["shape"] = shape.to_dict()
133
+ data["requires_bridge"] = False
134
+ return data
135
+
136
+ @staticmethod
137
+ def calculate_custom_line_property(
138
+ sec_lines: Sequence[Sequence[float]],
139
+ ) -> Dict[str, Any]:
140
+ shape = SectionGeometryDB.generate("自定义线宽截面", sec_lines=list(sec_lines))
141
+ result = SectionPropertySolver.calculate_detailed(shape)
142
+ data = result.to_dict()
143
+ data["shape"] = shape.to_dict()
144
+ data["requires_bridge"] = False
145
+ return data
146
+
147
+ @staticmethod
148
+ def get_bridge_section_property(index: int) -> Dict[str, Any]:
149
+ """读取桥通当前模型中的完整截面特性;需要桥通 HTTP 服务。"""
150
+ from qtmodel.odb.odb_model_section import OdbModelSection
151
+
152
+ prop = OdbModelSection.get_section_property(int(index))
153
+ return {
154
+ "property": prop.to_dict(),
155
+ "units": prop.units(),
156
+ "requires_bridge": True,
157
+ }
158
+
159
+
160
+ __all__ = ["QtModelSectionAdapter"]