dsh-plugin-pscad-expert-vyma 1.0.5 → 1.0.7

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
@@ -1,6 +1,6 @@
1
1
  # pscad-dsh-plugin — PSCAD 自动化建模与仿真控制专家插件
2
2
 
3
- > **版本**:1.0.0 | **注册名**:`pscad-automation-expert`
3
+ > **版本**:1.0.7 | **注册名**:`pscad-automation-expert`
4
4
  > **来源**:PSCAD 知识资产固化项目(四阶段:技能文档 → 模板索引 → 工具库 → 插件打包)
5
5
  > 所有知识、工具、模板均来自真实仿真验证(L13~L19 认证轮 + R4 科研轮),**无伪造数据**。
6
6
 
package/index.js CHANGED
@@ -79,7 +79,9 @@ function runPy(tool, args, config, signal) {
79
79
  }
80
80
 
81
81
  // ---------------- 工具渲染(纯函数:不做 I/O) ----------------
82
- function renderJson(value) {
82
+ // 注意:DSH 框架以 render(args, value) 双参调用渲染器;若只声明单参 value,
83
+ // 实际收到的是 args,导致"成功结果恒显示参数/{}"。必须双参并取第二个参数。
84
+ function renderJson(_args, value) {
83
85
  if (value && typeof value === 'object' && value.error === 'ConfigMissing') {
84
86
  // 配置缺失:引导 Agent 立即停止当前任务并询问用户路径
85
87
  return [{ type: 'text', text: `【配置缺失】${value.instruction}` }]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-pscad-expert-vyma",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "PSCAD 自动化建模与仿真控制专家插件(DSH Agent 工具库 + 基准模板 + 领域知识)",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -30,7 +30,10 @@
30
30
  "plugin.yaml",
31
31
  "README.md",
32
32
  "index.js",
33
- "cordis.patch.yml"
33
+ "cordis.patch.yml",
34
+ "!tools/__pycache__/",
35
+ "!**/*.pyc",
36
+ "!**/*.pyo"
34
37
  ],
35
38
  "engines": {
36
39
  "python": ">=3.7"
package/plugin.yaml CHANGED
@@ -3,7 +3,7 @@
3
3
  # 由知识资产固化项目自动生成(2026-08-25)· 部署至 Git 仓库
4
4
  # ============================================================
5
5
  name: pscad-automation-expert
6
- version: 1.0.5
6
+ version: 1.0.7
7
7
  description: PSCAD 自动化建模与仿真控制专家插件
8
8
 
9
9
  # ---- 系统提示词(加载到 Agent 上下文最前置位置)----
package/tools/cli.py CHANGED
@@ -27,9 +27,33 @@ from typing import Any, Dict, List
27
27
  # 将本文件所在目录加入 sys.path,以便 import main(tools/main.py)
28
28
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
29
29
 
30
+ # 统一 stdout 为 UTF-8:Node 桥接按 UTF-8 解码,避免 GBK 中文乱码(Python 3.7+)
31
+ try:
32
+ sys.stdout.reconfigure(encoding='utf-8')
33
+ sys.stderr.reconfigure(encoding='utf-8')
34
+ except Exception:
35
+ pass
36
+
30
37
  import main as pat # noqa: E402
31
38
 
39
+ def _run_simulation_configure(time_duration: float = 0.5,
40
+ time_step: float = 10.0,
41
+ sample_step: float = 50.0,
42
+ timeout_loops: int = 60) -> Dict[str, Any]:
43
+ """组合工具:先配置仿真参数(configure_simulation),再编译运行并监控。
44
+
45
+ 对应桥接层 pscad_run_simulation 的复合语义(配置 + 运行一步到位)。
46
+ """
47
+ cfg = pat.configure_simulation(time_duration=time_duration,
48
+ time_step=time_step,
49
+ sample_step=sample_step)
50
+ if cfg.get('status') != 'success':
51
+ return cfg
52
+ return pat.run_simulation_and_monitor(timeout_loops=timeout_loops)
53
+
54
+
32
55
  # 白名单:仅暴露经过审核的工具函数(防止任意 Python 代码执行)
56
+ # 同时收录桥接层 index.js 注册的 pscad_* 工具名(别名),消除名字脱节。
33
57
  TOOL_WHITELIST: Dict[str, Any] = {
34
58
  'init_pscad_environment': pat.init_pscad_environment,
35
59
  'connect_and_load_project': pat.connect_and_load_project,
@@ -50,6 +74,15 @@ TOOL_WHITELIST: Dict[str, Any] = {
50
74
  'close_connection': pat.close_connection,
51
75
  'build_droop_chain': pat.build_droop_chain,
52
76
  'self_check': pat.self_check,
77
+ # ---- 桥接层别名(index.js 注册的 pscad_* 工具名)----
78
+ 'pscad_init_environment': pat.init_pscad_environment,
79
+ 'pscad_connect_load_project': pat.connect_and_load_project,
80
+ 'pscad_add_component': pat.add_and_configure_component,
81
+ 'pscad_connect_ports': pat.connect_ports_safely,
82
+ 'pscad_connect_signal': pat.connect_signal_by_name,
83
+ 'pscad_run_simulation': _run_simulation_configure,
84
+ 'pscad_read_output': pat.read_output,
85
+ 'pscad_self_check': pat.self_check,
53
86
  }
54
87
 
55
88
 
package/tools/main.py CHANGED
@@ -109,44 +109,73 @@ _NAME_HINT: Dict[str, str] = {
109
109
  }
110
110
 
111
111
  # ---------------------------------------------------------------------------
112
- # 本地配置持久化(工作区 .pscad_config.json)
112
+ # 本地配置持久化(用户级优先:PSCAD 路径是机器属性,跨工作区共享)
113
+ # 查找顺序:PSCAD_CONFIG_DIR 环境变量 → 用户级(DSH_HOME/主目录) → 工作区级(兼容旧版)
113
114
  # ---------------------------------------------------------------------------
114
115
  _config_cache: Optional[Dict[str, Any]] = None
115
116
 
116
117
 
117
- def _config_path() -> str:
118
- """配置文件绝对路径(默认当前工作目录;可被环境变量 PSCAD_CONFIG 覆盖)。"""
119
- base = os.environ.get('PSCAD_CONFIG_DIR') or os.getcwd()
118
+ def _user_config_path() -> str:
119
+ """用户级配置路径:优先 DSH_HOME,其次用户主目录。"""
120
+ dsh_home = os.environ.get('DSH_HOME')
121
+ base = dsh_home if dsh_home else os.path.expanduser('~')
120
122
  return os.path.join(base, CONFIG_FILE_NAME)
121
123
 
122
124
 
125
+ def _config_path() -> str:
126
+ """配置写入路径(保存时使用):显式 PSCAD_CONFIG_DIR 优先,否则用户级。"""
127
+ env_dir = os.environ.get('PSCAD_CONFIG_DIR')
128
+ if env_dir:
129
+ return os.path.join(env_dir, CONFIG_FILE_NAME)
130
+ return _user_config_path()
131
+
132
+
123
133
  def load_config() -> Dict[str, Any]:
124
- """加载工作区本地配置 ``.pscad_config.json``。
134
+ """加载 PSCAD 路径配置(多级查找,**跨工作区共享**)。
135
+
136
+ 查找顺序:
137
+ 1. 环境变量 ``PSCAD_CONFIG_DIR`` 指定目录下的 ``.pscad_config.json``;
138
+ 2. 用户级:``$DSH_HOME/.pscad_config.json``(无 DSH_HOME 时用用户主目录)——
139
+ 一次配置,所有工作区/所有会话共享,**不依赖任何插件仓库目录**;
140
+ 3. 工作区级:当前目录 ``.pscad_config.json``(兼容旧版本遗留配置)。
125
141
 
126
142
  配置键:``pscad_exe_path``(PSCAD 可执行文件)、``mhi_pylib_path``
127
143
  (mhi.pscad 库目录)、``pscad_port``(自动化端口,可选)、``saved_at``。
128
144
 
129
145
  Returns:
130
- 配置字典;文件不存在或损坏时返回 ``{}``(**绝不抛异常**)。
146
+ 配置字典;均不存在或损坏时返回 ``{}``(**绝不抛异常**)。
131
147
  结果会缓存,供懒加载与连接逻辑读取。
132
148
  """
133
149
  global _config_cache
134
150
  if _config_cache is not None:
135
151
  return _config_cache
136
- try:
137
- path = _config_path()
138
- if os.path.isfile(path):
139
- with open(path, encoding='utf-8') as fh:
140
- _config_cache = json.load(fh)
141
- else:
142
- _config_cache = {}
143
- except Exception:
144
- _config_cache = {}
152
+ candidates: List[str] = []
153
+ env_dir = os.environ.get('PSCAD_CONFIG_DIR')
154
+ if env_dir:
155
+ candidates.append(os.path.join(env_dir, CONFIG_FILE_NAME))
156
+ candidates.append(_user_config_path())
157
+ candidates.append(os.path.join(os.getcwd(), CONFIG_FILE_NAME))
158
+ cfg: Dict[str, Any] = {}
159
+ for path in candidates:
160
+ try:
161
+ if os.path.isfile(path):
162
+ with open(path, encoding='utf-8') as fh:
163
+ data = json.load(fh)
164
+ if isinstance(data, dict) and data:
165
+ cfg = data
166
+ break
167
+ except Exception:
168
+ continue
169
+ _config_cache = cfg
145
170
  return _config_cache
146
171
 
147
172
 
148
173
  def save_config(exe_path: str, pylib_path: str) -> Dict[str, Any]:
149
- """将 PSCAD 路径配置持久化到工作区 ``.pscad_config.json``。
174
+ """将 PSCAD 路径配置持久化到**用户级** ``.pscad_config.json``(跨工作区共享)。
175
+
176
+ 写入位置:``PSCAD_CONFIG_DIR`` 环境变量(若设置)→ 否则 ``$DSH_HOME``(无则用户
177
+ 主目录)。**不写入当前工作区**——保证在其他任意工作区、其他电脑(无插件仓库)
178
+ 都能通过 load_config 读到同一份配置。
150
179
 
151
180
  Args:
152
181
  exe_path: PSCAD 可执行文件绝对路径(如 '<PSCAD_INSTALL_DIR>/bin/win64/Pscad.exe')。