dsh-gitbash-shell 0.17.1 → 0.18.0

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/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/dsh-gitbash-shell",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "main": "./src/index.js",
5
5
  "description": "Windows 全模式 Git Bash:用 Git for Windows bash 替换 PowerShell 执行器,并物化 standard/minimal/code/cordis 的 Git Bash 变体 preset。双 era 适配 dsh <= 0.1.1(内置 id 'code')与 >= 0.1.2(改名 'ptc'),启动探测自动选择,preset id 永不变。联动:dsh-ptc-cordis-preset(两者同装时 PTC 创造模式自动物化为 Git Bash 版)+ dsh-better-sidebar(终端 UI 标签与模型 terminal_* 工具自动切到 Git Bash)。",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-gitbash-shell",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "description": "Windows 上让 agent 的每条 shell 命令改经 Git for Windows bash 执行;物化四个内置预设的 Git Bash 变体,统一 MSYS 盘根路径方言,侧栏终端接管可开关。· Run every agent shell command through Git for Windows bash on Windows; materialize Git Bash variants of the built-in presets, unify the MSYS drive-root path dialect, and adopt the sidebar terminal behind a switch.",
5
5
  "type": "module",
6
6
  "repository": {
package/src/index.js CHANGED
@@ -753,6 +753,18 @@ export function rewriteErrorContent(content) {
753
753
  changed = true
754
754
  return { ...block, text: out }
755
755
  })
756
+ // /dev/null x file tools: the harness realpath step rejects device
757
+ // paths, so the failure is EXPECTED — append one guidance line (v0.18.0)
758
+ // instead of leaving the model to puzzle over EINVAL. The original
759
+ // diagnostic stays verbatim; only a hint block is appended.
760
+ const nulHit = content.some((block) => {
761
+ const t = block && typeof block === 'object' && typeof block.text === 'string' ? block.text : ''
762
+ return t.includes('EINVAL') && t.includes('NUL')
763
+ })
764
+ if (nulHit) {
765
+ next.push({ type: 'text', text: 'hint: /dev/null is the NUL device — file tools cannot target device paths (their realpath step rejects them); discard output through bash instead (echo ... > /dev/null)' })
766
+ changed = true
767
+ }
756
768
  return changed ? next : content
757
769
  }
758
770
 
@@ -911,11 +923,53 @@ export function buildTranslateEnv() {
911
923
  * resolve after the drive roots; any other shape returns the input
912
924
  * unchanged. Pure: the env is a plain fact bag, nothing is probed here.
913
925
  */
926
+ /**
927
+ * Expand a leading dollar-sign NAME / braced NAME path variable the way
928
+ * Git Bash would (pure, string surgery, v0.18.0): HOME is the user home,
929
+ * TMPDIR/TMP/TEMP all mean the /tmp mount. Unknown names and NAMEX-style
930
+ * false positives return the input verbatim (written without any dollar
931
+ * literal — a code-transport layer mangles that byte inside quotes).
932
+ */
933
+ function expandLeadingVar(value, env) {
934
+ if (!env || typeof value !== 'string' || value.length < 2) return value
935
+ if (value.charCodeAt(0) !== 36) return value
936
+ let name = ''
937
+ let rest = ''
938
+ if (value.charCodeAt(1) === 123) {
939
+ const close = value.indexOf('}', 2)
940
+ if (close < 0) return value
941
+ name = value.slice(2, close)
942
+ rest = value.slice(close + 1)
943
+ } else {
944
+ const head = value.slice(1)
945
+ let i = 0
946
+ while (i < head.length) {
947
+ const c = head.charCodeAt(i)
948
+ const letter = (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c === 95
949
+ const digit = c >= 48 && c <= 57
950
+ if (i === 0 ? !letter : !(letter || digit)) break
951
+ i++
952
+ }
953
+ if (i === 0) return value
954
+ name = head.slice(0, i)
955
+ rest = head.slice(i)
956
+ }
957
+ if (rest !== '' && rest.charCodeAt(0) !== 47) return value
958
+ let base
959
+ if (name === 'HOME') base = env.home
960
+ else if (name === 'TMPDIR' || name === 'TMP' || name === 'TEMP') base = env.tmpDir
961
+ else return value
962
+ return base ? (rest !== '' ? base + rest : base) : value
963
+ }
914
964
  export function translateMsysPath(value, env) {
915
965
  if (typeof value !== 'string') return value
916
966
  if (env && env.home && (value === '~' || value.startsWith('~/'))) {
917
967
  return value === '~' ? env.home : env.home + '/' + value.slice(2)
918
968
  }
969
+ if (env) {
970
+ const expanded = expandLeadingVar(value, env)
971
+ if (expanded !== value) return expanded
972
+ }
919
973
  const match = MSYS_DRIVE_ROOT.exec(value)
920
974
  if (match) return match[1].toUpperCase() + ':/' + match[2]
921
975
  const bare = MSYS_BARE_DRIVE.exec(value)