dsh-plugin-pscad-expert-vyma 1.0.14 → 1.0.15

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.14 | **注册名**:`pscad-automation-expert`
3
+ > **版本**:1.0.15 | **注册名**:`pscad-automation-expert`
4
4
  > **来源**:PSCAD 知识资产固化项目(四阶段:技能文档 → 模板索引 → 工具库 → 插件打包)
5
5
  > 所有知识、工具、模板均来自真实仿真验证(L13~L19 认证轮 + R4 科研轮),**无伪造数据**。
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-pscad-expert-vyma",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "PSCAD 自动化建模与仿真控制专家插件(DSH Agent 工具库 + 基准模板 + 领域知识)",
5
5
  "type": "module",
6
6
  "main": "index.js",
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.14
6
+ version: 1.0.15
7
7
  description: PSCAD 自动化建模与仿真控制专家插件
8
8
 
9
9
  # ---- 系统提示词(加载到 Agent 上下文最前置位置)----
@@ -53,9 +53,9 @@ if (-not (Test-Path -LiteralPath $pkgJson)) {
53
53
  Copy-Item -LiteralPath $pkgJson -Destination "$pkgJson.bak-$(Get-Date -Format yyyyMMdd-HHmmss)" -Force
54
54
  $text = [System.IO.File]::ReadAllText($pkgJson, [System.Text.Encoding]::UTF8)
55
55
 
56
- # 4a) 依赖版本号:无论当前写的是什么,统一替换为最新版
57
- $new = $text -replace '("dsh-plugin-pscad-expert-vyma"\s*:\s*")[^"]*(")', ('${1}' + $latest + '${2}')
58
- if ($new -notmatch ('"' + $pkg + '"\s*:\s*"' + [regex]::Escape($latest) + '"')) {
56
+ # 4a) 依赖版本号:无论当前写的是什么,统一替换为 ^最新(^ 范围让后续 dsh plugin up 可解析新版本)
57
+ $new = $text -replace '("dsh-plugin-pscad-expert-vyma"\s*:\s*")[^"]*(")', ('${1}^' + $latest + '${2}')
58
+ if ($new -notmatch ('"' + $pkg + '"\s*:\s*"\^?' + [regex]::Escape($latest) + '"')) {
59
59
  Write-Host " !! 未在 dependencies 找到插件条目,无法自动改版本,请先把上方输出发回。" -ForegroundColor Red
60
60
  exit 1
61
61
  }
package/tools/main.py CHANGED
@@ -55,6 +55,7 @@ from __future__ import annotations
55
55
  import json
56
56
  import os
57
57
  import re
58
+ import socket
58
59
  import sys
59
60
  import time
60
61
  import math
@@ -668,6 +669,21 @@ def connect_and_load_project(project_name: str,
668
669
  return _err(exc)
669
670
 
670
671
 
672
+ def _port_ready(port: int, timeout_s: float = 1.0) -> bool:
673
+ """毫秒~秒级 TCP 端口探测:PSCAD 自动化端口是否已监听。
674
+
675
+ 背景(P5 实测):mhi-pscad 2.9.7 的 connect(timeout=5) 在 PSCAD 未运行时会
676
+ 内部重试阻塞 ~16s,不尊重超时参数;轮询循环若直接调 connect,单次迭代
677
+ ≈18s,180s 名义上限实际只能尝试约 10 次。改用 socket 探测后单次迭代 ≈2s,
678
+ 且 connect 只在端口就绪后才调用。
679
+ """
680
+ try:
681
+ with socket.create_connection(('127.0.0.1', port), timeout=timeout_s):
682
+ return True
683
+ except Exception:
684
+ return False
685
+
686
+
671
687
  def _ensure_connected() -> Tuple[bool, str]:
672
688
  """确保存在活的 mhi 连接(幂等;懒加载 mhi)。"""
673
689
  global _pscad
@@ -680,6 +696,9 @@ def _ensure_connected() -> Tuple[bool, str]:
680
696
  return True, ''
681
697
  except Exception:
682
698
  _pscad = None
699
+ # 端口未监听时直接快速失败(避免 mhi connect 阻塞 ~16s)
700
+ if not _port_ready(PSCAD_PORT, 0.5):
701
+ return False, 'PSCAD 自动化端口 %d 未就绪(PSCAD 未运行?)' % PSCAD_PORT
683
702
  try:
684
703
  _pscad = mhi.pscad.connect(port=PSCAD_PORT, timeout=CONNECT_TIMEOUT_S)
685
704
  return True, ''
@@ -760,7 +779,13 @@ def _ensure_project() -> Optional[Dict[str, Any]]:
760
779
 
761
780
 
762
781
  def _launch_pscad() -> Tuple[bool, str]:
763
- """拉起 PSCAD 进程并等待自动化端口就绪(崩溃恢复标准路径;懒加载 exe 路径)。"""
782
+ """拉起 PSCAD 进程并等待自动化端口就绪(崩溃恢复标准路径;懒加载 exe 路径)。
783
+
784
+ 轮询用 socket 端口探测(毫秒级)而非直接 mhi.pscad.connect:P5 实测
785
+ mhi 2.9.7 的 connect(timeout=5) 在 PSCAD 未起时阻塞 ~16s(不尊重超时),
786
+ 直接调用会让 180s 名义上限实际只能尝试约 10 次;socket 探测使单次迭代
787
+ ≈2s,端口就绪后才调用 connect 建立自动化连接。
788
+ """
764
789
  global _pscad
765
790
  exe = _cfg_exe()
766
791
  if not exe:
@@ -770,12 +795,14 @@ def _launch_pscad() -> Tuple[bool, str]:
770
795
  '/port:%d' % PSCAD_PORT, '/splash:false'])
771
796
  deadline = time.time() + LAUNCH_WAIT_S
772
797
  while time.time() < deadline:
798
+ if _port_ready(PSCAD_PORT, 1.0):
799
+ try:
800
+ _pscad = mhi.pscad.connect(port=PSCAD_PORT,
801
+ timeout=CONNECT_TIMEOUT_S)
802
+ return True, ''
803
+ except Exception:
804
+ continue
773
805
  time.sleep(2)
774
- try:
775
- _pscad = mhi.pscad.connect(port=PSCAD_PORT, timeout=5)
776
- return True, ''
777
- except Exception:
778
- continue
779
806
  return False, 'PSCAD 启动后 %ds 内端口未就绪' % LAUNCH_WAIT_S
780
807
  except Exception as exc:
781
808
  return False, str(exc)