@deepseek-harness-tui/dsh-tui 0.8.3 → 0.8.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.
Files changed (198) hide show
  1. package/README.md +29 -10
  2. package/bin/dsh-tui.js +50 -11
  3. package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -13
  4. package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -59
  5. package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -15
  6. package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -32
  7. package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -59
  8. package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -166
  9. package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -42
  10. package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -143
  11. package/dsh-ecosystem-spec/registry/README.md +14 -14
  12. package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -56
  13. package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -13
  14. package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -149
  15. package/lib/types/activityPrefs.d.ts +10 -0
  16. package/lib/types/activityPrefs.d.ts.map +1 -1
  17. package/lib/types/activityPrefs.js +17 -0
  18. package/lib/types/commands.d.ts.map +1 -1
  19. package/lib/types/commands.js +1 -0
  20. package/lib/types/components/LogoV2.d.ts +4 -1
  21. package/lib/types/components/LogoV2.d.ts.map +1 -1
  22. package/lib/types/components/LogoV2.js +8 -3
  23. package/lib/types/components/MessageList.d.ts +4 -1
  24. package/lib/types/components/MessageList.d.ts.map +1 -1
  25. package/lib/types/components/MessageList.js +4 -4
  26. package/lib/types/components/PromptInput.d.ts.map +1 -1
  27. package/lib/types/components/PromptInput.js +1 -3
  28. package/lib/types/components/SplitDiffView.d.ts +3 -1
  29. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  30. package/lib/types/components/SplitDiffView.js +12 -5
  31. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  32. package/lib/types/components/StreamingMarkdown.js +10 -2
  33. package/lib/types/components/TipsPanel.d.ts +14 -0
  34. package/lib/types/components/TipsPanel.d.ts.map +1 -0
  35. package/lib/types/components/TipsPanel.js +37 -0
  36. package/lib/types/components/activityFrames.d.ts +7 -28
  37. package/lib/types/components/activityFrames.d.ts.map +1 -1
  38. package/lib/types/components/activityFrames.js +7 -84
  39. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  40. package/lib/types/components/messages/AssistantThinkingMessage.js +1 -1
  41. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +4 -1
  42. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  43. package/lib/types/components/messages/AssistantToolUseMessage.js +14 -3
  44. package/lib/types/dsh-adapter/channel.d.ts +17 -0
  45. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  46. package/lib/types/dsh-adapter/channel.js +169 -33
  47. package/lib/types/dsh-adapter/index.d.ts +5 -0
  48. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  49. package/lib/types/dsh-adapter/index.js +19 -0
  50. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  51. package/lib/types/dsh-adapter/plugin.js +176 -4
  52. package/lib/types/dsh-adapter/settings-sections.d.ts +13 -0
  53. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
  54. package/lib/types/dsh-adapter/settings-sections.js +31 -6
  55. package/lib/types/effortPrefs.d.ts +7 -6
  56. package/lib/types/effortPrefs.d.ts.map +1 -1
  57. package/lib/types/effortPrefs.js +7 -6
  58. package/lib/types/i18n.d.ts +42 -14
  59. package/lib/types/i18n.d.ts.map +1 -1
  60. package/lib/types/i18n.js +11 -4
  61. package/lib/types/ink/ink.d.ts +10 -0
  62. package/lib/types/ink/ink.d.ts.map +1 -1
  63. package/lib/types/ink/ink.js +35 -1
  64. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  65. package/lib/types/ink/parse-keypress.js +15 -0
  66. package/lib/types/screens/Chat.d.ts.map +1 -1
  67. package/lib/types/screens/Chat.js +44 -7
  68. package/lib/types/screens/Settings.d.ts.map +1 -1
  69. package/lib/types/screens/Settings.js +109 -50
  70. package/lib/types/screens/StatusLine.d.ts +8 -0
  71. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  72. package/lib/types/screens/StatusLine.js +65 -42
  73. package/lib/types/settings-sections.d.ts +1 -1
  74. package/lib/types/settings-sections.d.ts.map +1 -1
  75. package/lib/types/tips.d.ts +30 -0
  76. package/lib/types/tips.d.ts.map +1 -0
  77. package/lib/types/tips.js +575 -0
  78. package/lib/types/tuiDisplayPrefs.d.ts +47 -0
  79. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -0
  80. package/lib/types/tuiDisplayPrefs.js +60 -0
  81. package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
  82. package/node_modules/@dsh-std/command/LICENSE +21 -21
  83. package/node_modules/@dsh-std/command/README.md +26 -26
  84. package/node_modules/@dsh-std/command/README.zh.md +28 -28
  85. package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
  86. package/node_modules/@dsh-std/command/package.json +22 -22
  87. package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  88. package/node_modules/@dsh-std/connection/LICENSE +21 -21
  89. package/node_modules/@dsh-std/connection/README.md +42 -42
  90. package/node_modules/@dsh-std/connection/README.zh.md +42 -42
  91. package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  92. package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  93. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  94. package/node_modules/@dsh-std/connection/package.json +20 -20
  95. package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  96. package/node_modules/@dsh-std/core/LICENSE +21 -21
  97. package/node_modules/@dsh-std/core/README.md +13 -13
  98. package/node_modules/@dsh-std/core/README.zh.md +13 -13
  99. package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  100. package/node_modules/@dsh-std/core/package.json +21 -21
  101. package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  102. package/node_modules/@dsh-std/manifest/LICENSE +21 -21
  103. package/node_modules/@dsh-std/manifest/README.md +5 -5
  104. package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  105. package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  106. package/node_modules/@dsh-std/manifest/package.json +20 -20
  107. package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  108. package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
  109. package/node_modules/@dsh-std/messages/LICENSE +21 -21
  110. package/node_modules/@dsh-std/messages/README.md +5 -5
  111. package/node_modules/@dsh-std/messages/README.zh.md +7 -7
  112. package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
  113. package/node_modules/@dsh-std/messages/package.json +20 -20
  114. package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
  115. package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  116. package/node_modules/@dsh-std/presentation/LICENSE +21 -21
  117. package/node_modules/@dsh-std/presentation/README.md +27 -27
  118. package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  119. package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  120. package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  121. package/node_modules/@dsh-std/presentation/package.json +25 -25
  122. package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
  123. package/node_modules/@dsh-std/storage/LICENSE +21 -21
  124. package/node_modules/@dsh-std/storage/README.md +5 -5
  125. package/node_modules/@dsh-std/storage/README.zh.md +7 -7
  126. package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
  127. package/node_modules/@dsh-std/storage/package.json +20 -20
  128. package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
  129. package/package.json +8 -3
  130. package/presets/liangshen/.dsh-tui-managed.json +1 -1
  131. package/presets/liangshen/agent.cordis.yml +7 -5
  132. package/presets/liangshen/custom-bash.mjs +184 -9
  133. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  134. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
  135. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
  136. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
  137. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  138. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  139. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  140. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
  141. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  142. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
  143. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
  144. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
  145. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  146. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
  147. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  148. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
  149. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
  150. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  151. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  152. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
  153. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  154. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  155. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
  156. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
  157. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  158. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  159. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  160. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
  161. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  162. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
  163. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
  164. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
  165. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  166. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
  167. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  168. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
  169. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
  170. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
  171. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  172. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
  173. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  174. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
  175. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
  176. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
  177. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  178. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
  179. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  180. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
  181. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
  182. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
  183. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  184. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  185. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  186. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
  187. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  188. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
  189. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
  190. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
  191. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  192. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
  193. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  194. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
  195. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
  196. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
  197. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  198. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -21
@@ -1,56 +1,56 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "urn:dsh-std:storage:local-storage:0.15",
4
- "title": "LocalStorage v0.15 operations",
5
- "$defs": {
6
- "jsonValue": {
7
- "oneOf": [
8
- { "type": "null" },
9
- { "type": "boolean" },
10
- { "type": "number" },
11
- { "type": "string" },
12
- { "type": "array", "items": { "$ref": "#/$defs/jsonValue" } },
13
- { "type": "object", "additionalProperties": { "$ref": "#/$defs/jsonValue" } }
14
- ]
15
- },
16
- "getInput": {
17
- "type": "object",
18
- "additionalProperties": false,
19
- "required": ["key"],
20
- "properties": { "key": { "type": "string", "minLength": 1 } }
21
- },
22
- "getOutput": {
23
- "type": "object",
24
- "additionalProperties": false,
25
- "required": ["value"],
26
- "properties": { "value": { "$ref": "#/$defs/jsonValue" } }
27
- },
28
- "setInput": {
29
- "type": "object",
30
- "additionalProperties": false,
31
- "required": ["key", "value"],
32
- "properties": {
33
- "key": { "type": "string", "minLength": 1 },
34
- "value": { "$ref": "#/$defs/jsonValue" }
35
- }
36
- },
37
- "setOutput": {
38
- "type": "object",
39
- "additionalProperties": false,
40
- "required": ["stored"],
41
- "properties": { "stored": { "const": true } }
42
- },
43
- "deleteInput": {
44
- "type": "object",
45
- "additionalProperties": false,
46
- "required": ["key"],
47
- "properties": { "key": { "type": "string", "minLength": 1 } }
48
- },
49
- "deleteOutput": {
50
- "type": "object",
51
- "additionalProperties": false,
52
- "required": ["deleted"],
53
- "properties": { "deleted": { "type": "boolean" } }
54
- }
55
- }
56
- }
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:dsh-std:storage:local-storage:0.15",
4
+ "title": "LocalStorage v0.15 operations",
5
+ "$defs": {
6
+ "jsonValue": {
7
+ "oneOf": [
8
+ { "type": "null" },
9
+ { "type": "boolean" },
10
+ { "type": "number" },
11
+ { "type": "string" },
12
+ { "type": "array", "items": { "$ref": "#/$defs/jsonValue" } },
13
+ { "type": "object", "additionalProperties": { "$ref": "#/$defs/jsonValue" } }
14
+ ]
15
+ },
16
+ "getInput": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "required": ["key"],
20
+ "properties": { "key": { "type": "string", "minLength": 1 } }
21
+ },
22
+ "getOutput": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "required": ["value"],
26
+ "properties": { "value": { "$ref": "#/$defs/jsonValue" } }
27
+ },
28
+ "setInput": {
29
+ "type": "object",
30
+ "additionalProperties": false,
31
+ "required": ["key", "value"],
32
+ "properties": {
33
+ "key": { "type": "string", "minLength": 1 },
34
+ "value": { "$ref": "#/$defs/jsonValue" }
35
+ }
36
+ },
37
+ "setOutput": {
38
+ "type": "object",
39
+ "additionalProperties": false,
40
+ "required": ["stored"],
41
+ "properties": { "stored": { "const": true } }
42
+ },
43
+ "deleteInput": {
44
+ "type": "object",
45
+ "additionalProperties": false,
46
+ "required": ["key"],
47
+ "properties": { "key": { "type": "string", "minLength": 1 } }
48
+ },
49
+ "deleteOutput": {
50
+ "type": "object",
51
+ "additionalProperties": false,
52
+ "required": ["deleted"],
53
+ "properties": { "deleted": { "type": "boolean" } }
54
+ }
55
+ }
56
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepseek-harness-tui/dsh-tui",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Claude Code style interactive TUI front door for DeepSeek Harness agents, built on the ported Ink core.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -105,13 +105,18 @@
105
105
  "verify:packaged-presets": "node scripts/verify-packaged-presets.mjs",
106
106
  "verify:minimal-preset-tools": "node scripts/verify-minimal-preset-tools.mjs",
107
107
  "verify:liangshen-bootstrap": "node scripts/verify-liangshen-bootstrap.mjs",
108
+ "verify:liangshen-bash": "node scripts/verify-liangshen-bash.mjs",
108
109
  "verify:package": "npm pack --dry-run --json --ignore-scripts | node scripts/verify-package.mjs",
109
110
  "verify:prompt-debug": "npm run build && node scripts/verify-prompt-debug.mjs",
110
111
  "verify:clipboard-image": "node --import tsx/esm scripts/verify-clipboard-image.ts",
111
112
  "verify:plugin-ledger": "node --import tsx/esm scripts/verify-plugin-ledger.ts",
112
113
  "verify:plugin-commands": "node --import tsx/esm scripts/verify-plugin-commands.ts",
113
114
  "verify:plugin-negotiation": "node --import tsx/esm scripts/verify-plugin-negotiation.ts",
114
- "verify:plugin-lifecycle": "node --import tsx/esm scripts/verify-plugin-lifecycle.ts"
115
+ "verify:plugin-lifecycle": "node --import tsx/esm scripts/verify-plugin-lifecycle.ts",
116
+ "verify:tips": "node --import tsx/esm scripts/verify-tips.tsx",
117
+ "verify:thinking-preview": "node --import tsx/esm scripts/verify-thinking-preview.tsx",
118
+ "sync:profile": "node scripts/sync-profile.mjs",
119
+ "sync:profile:check": "node scripts/sync-profile.mjs --check"
115
120
  },
116
121
  "peerDependencies": {
117
122
  "@deepseek-ai/cordis": "^4.0.1",
@@ -156,7 +161,7 @@
156
161
  "cli-highlight": "^2.1.11",
157
162
  "code-excerpt": "^3.0.0 || ^4.0.0",
158
163
  "diff": "^8.0.4",
159
- "dsh-working-activity": "^0.2.6",
164
+ "dsh-working-activity": "^0.3.2",
160
165
  "emoji-regex": "^10.0.0",
161
166
  "figures": "^6.1.0",
162
167
  "get-east-asian-width": "^1.0.0",
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "owner": "@deepseek-harness-tui/dsh-tui",
3
3
  "preset": "liangshen",
4
- "revision": "liangshen-toolcall-full-catalog-subagents-v3"
4
+ "revision": "liangshen-toolcall-full-catalog-subagents-v4"
5
5
  }
@@ -151,15 +151,17 @@
151
151
  # Windows-only `bash` tool (see custom-bash.mjs): registers the SAME
152
152
  # tool name as the persistent shell with a Minimal-compatible description, but
153
153
  # executes through the ordinary cross-platform subprocess seam (`bash -c`)
154
- # instead of a PTY. `bashPath` defaults to `bash` on PATH; point it at Git
155
- # Bash explicitly when the WSL shim would otherwise be picked up. No OS
156
- # sandbox confinement on Windows (landlock is linux-only); the tool
154
+ # instead of a PTY. The Git Bash executable is DISCOVERED at preset mount:
155
+ # an explicit `config.bashPath` (or DSH_TUI_LIANGSHEN_BASH_PATH) is honored as
156
+ # the only candidate, otherwise a PATH git.exe is followed to its install tree
157
+ # (installer/portable/Scoop layouts, Scoop shims followed), then conventional
158
+ # roots, then bare `bash` — never the System32 WSL launcher. A miss warns and
159
+ # skips registration, which fails the bootstrap open to the full catalog.
160
+ # No OS sandbox confinement on Windows (landlock is linux-only); the tool
157
161
  # description says so.
158
162
  - id: custom-bash
159
163
  name: ./custom-bash.mjs
160
164
  disabled: !!js process.platform !== 'win32'
161
- config:
162
- bashPath: 'C:\Program Files\Git\bin\bash.exe'
163
165
 
164
166
  # ── filesystem ──────────────────────────────────────────────────────────────
165
167
 
@@ -13,9 +13,26 @@
13
13
  * the ordinary (cross-platform) subprocess seam keeps the schema anchor
14
14
  * without the PTY dependency.
15
15
  *
16
- * Executable resolution (config `bashPath`):
17
- * - explicit absolute path (e.g. `C:\Program Files\Git\bin\bash.exe`), or
18
- * - `bash` resolved through `ctx.subprocess.resolveExecutable` (PATH lookup).
16
+ * Executable resolution, in order (an explicit entry is the ONLY candidate:
17
+ * a miss fails loudly instead of silently substituting a guess):
18
+ * 1. explicit `config.bashPath` or the `DSH_TUI_LIANGSHEN_BASH_PATH`
19
+ * environment variable (absolute path to a Git Bash bash.exe);
20
+ * 2. a `git` on PATH followed to its installation tree — every Windows Git
21
+ * install ships bash next to git, wherever it was installed, so this
22
+ * covers installer, portable, and Scoop layouts (a Scoop `.shim` sidecar
23
+ * is followed to the real target) — yielding `<root>\bin\bash.exe` and
24
+ * `<root>\usr\bin\bash.exe`;
25
+ * 3. conventional install roots (`ProgramFiles`, `ProgramFiles(x86)`,
26
+ * `%LOCALAPPDATA%\Programs\Git`);
27
+ * 4. Scoop's conventional roots (`%SCOOP%`, else `%USERPROFILE%\scoop`)
28
+ * under `apps\git\current\` — Scoop does not always export `SCOOP`;
29
+ * 5. bare `bash` on PATH.
30
+ * `C:\Windows\System32\bash.exe` (and Sysnative) is the WSL launcher, not
31
+ * the Git Bash executor: it is ALWAYS rejected, so a PATH lookup can never
32
+ * silently hand the model a WSL shell. Resolution runs ONCE at apply time —
33
+ * a total miss warns and SKIPS registration, so `tool-bootstrap`'s
34
+ * missing-tool path fails open to the full catalog instead of registering a
35
+ * `bash` tool whose every call would fail mid-session.
19
36
  *
20
37
  * Semantics mirror the official bash tool: `bash -c <command>` in a fresh
21
38
  * process, bounded output, non-zero exit reported not thrown. No sandbox
@@ -24,6 +41,8 @@
24
41
  * `str_replace_editor` (Minimal's two tools).
25
42
  */
26
43
 
44
+ import { readFileSync } from 'node:fs'
45
+
27
46
  /** Cordis plugin name used by loader diagnostics. */
28
47
  export const name = 'custom-bash'
29
48
 
@@ -50,11 +69,167 @@ const commandSchema = {
50
69
  additionalProperties: false,
51
70
  }
52
71
 
72
+ function addCandidate(candidates, seen, candidate) {
73
+ if (typeof candidate !== 'string' || candidate.length === 0) return
74
+ const key = candidate.toLowerCase()
75
+ if (seen.has(key)) return
76
+ seen.add(key)
77
+ candidates.push(candidate)
78
+ }
79
+
80
+ /** The explicit override, if any: `config.bashPath`, else the environment variable. */
81
+ function explicitBashPath(config, environment) {
82
+ for (const value of [config.bashPath, environment.DSH_TUI_LIANGSHEN_BASH_PATH]) {
83
+ if (typeof value === 'string' && value.length > 0) return value
84
+ }
85
+ return undefined
86
+ }
87
+
88
+ /** Return conventional Git Bash locations in deterministic order (explicit config first). */
89
+ export function windowsBashCandidates(config = {}, environment = process.env) {
90
+ const explicit = explicitBashPath(config, environment)
91
+ if (explicit !== undefined) return [explicit]
92
+
93
+ const candidates = []
94
+ const seen = new Set()
95
+ for (const root of [
96
+ environment.ProgramFiles,
97
+ environment['ProgramFiles(x86)'],
98
+ ]) {
99
+ if (typeof root !== 'string' || root.length === 0) continue
100
+ addCandidate(candidates, seen, `${root}\\Git\\bin\\bash.exe`)
101
+ addCandidate(candidates, seen, `${root}\\Git\\usr\\bin\\bash.exe`)
102
+ }
103
+ if (typeof environment.LOCALAPPDATA === 'string' && environment.LOCALAPPDATA.length > 0) {
104
+ addCandidate(candidates, seen, `${environment.LOCALAPPDATA}\\Programs\\Git\\bin\\bash.exe`)
105
+ addCandidate(candidates, seen, `${environment.LOCALAPPDATA}\\Programs\\Git\\usr\\bin\\bash.exe`)
106
+ }
107
+ // Scoop keeps Git under its own root; SCOOP is exported by some setups, but
108
+ // the per-user default location works without it.
109
+ const scoopRoots = []
110
+ if (typeof environment.SCOOP === 'string' && environment.SCOOP.length > 0) {
111
+ scoopRoots.push(environment.SCOOP)
112
+ }
113
+ if (typeof environment.USERPROFILE === 'string' && environment.USERPROFILE.length > 0) {
114
+ scoopRoots.push(`${environment.USERPROFILE}\\scoop`)
115
+ }
116
+ for (const root of scoopRoots) {
117
+ addCandidate(candidates, seen, `${root}\\apps\\git\\current\\bin\\bash.exe`)
118
+ addCandidate(candidates, seen, `${root}\\apps\\git\\current\\usr\\bin\\bash.exe`)
119
+ }
120
+ addCandidate(candidates, seen, 'bash')
121
+ return candidates
122
+ }
123
+
124
+ /** Windows' System32 bash.exe is a WSL launcher, not the Git Bash executor. */
125
+ export function isWindowsSubsystemLauncher(path) {
126
+ return /[\\/]windows[\\/](?:system32|sysnative)[\\/]bash\.exe$/i.test(path)
127
+ }
128
+
129
+ /**
130
+ * Scoop-style shim launchers keep the real target in a sibling `.shim` text
131
+ * file (`path = "..."`); follow it so a PATH-resolved git.exe still yields
132
+ * its installation tree.
133
+ */
134
+ export function resolveShimTarget(exePath, reader = readFileSync) {
135
+ for (const sidecar of [exePath.replace(/\.exe$/i, '') + '.shim', `${exePath}.shim`]) {
136
+ try {
137
+ const text = reader(sidecar, 'utf8')
138
+ const match = text.match(/^\s*path\s*=\s*"?(.+?)"?\s*$/mi)
139
+ if (match !== null) return match[1]
140
+ } catch { /* not a shim launcher */ }
141
+ }
142
+ return exePath
143
+ }
144
+
145
+ /** Bash candidates derived from a git.exe inside a Git for Windows tree. */
146
+ export function bashCandidatesFromGit(gitPath) {
147
+ if (typeof gitPath !== 'string' || gitPath.length === 0) return []
148
+ const parts = gitPath.replace(/\//g, '\\').split('\\').filter(part => part.length > 0)
149
+ if (parts.at(-1)?.toLowerCase() !== 'git.exe') return []
150
+ const roots = []
151
+ const push = root => {
152
+ if (root.length > 0 && !roots.includes(root)) roots.push(root)
153
+ }
154
+ // <root>\cmd\git.exe and <root>\bin\git.exe -> <root>
155
+ if (parts.length >= 3) push(parts.slice(0, -2).join('\\'))
156
+ // <root>\mingw64\bin\git.exe -> <root>; a plain <root>\cmd layout must not
157
+ // also strip its real root.
158
+ if (parts.length >= 5
159
+ && parts.at(-2)?.toLowerCase() === 'bin'
160
+ && /^mingw(32|64)$/.test(parts.at(-3) ?? '')) {
161
+ push(parts.slice(0, -3).join('\\'))
162
+ }
163
+ const candidates = []
164
+ for (const root of roots) {
165
+ candidates.push(`${root}\\bin\\bash.exe`, `${root}\\usr\\bin\\bash.exe`)
166
+ }
167
+ return candidates
168
+ }
169
+
170
+ /**
171
+ * Follow the PATH-visible git executable to its installation tree: every
172
+ * Windows Git install ships git-bash next to git, wherever it was installed,
173
+ * so this covers installer, portable, and Scoop layouts without hardcoding.
174
+ */
175
+ async function gitTreeCandidates(subprocess, failures) {
176
+ let gitPath
177
+ try {
178
+ gitPath = await subprocess.resolveExecutable('git')
179
+ } catch (error) {
180
+ failures.push(`git: ${error instanceof Error ? error.message : String(error)}`)
181
+ return []
182
+ }
183
+ return bashCandidatesFromGit(resolveShimTarget(gitPath))
184
+ }
185
+
186
+ /** Resolve Git Bash without accidentally accepting the WSL compatibility shim. */
187
+ export async function resolveWindowsBash(subprocess, config = {}, environment = process.env) {
188
+ const failures = []
189
+ const explicit = explicitBashPath(config, environment)
190
+ const candidates = explicit !== undefined
191
+ // An explicit path is honored as-is: never silently substitute a guess.
192
+ ? [explicit]
193
+ : [...await gitTreeCandidates(subprocess, failures), ...windowsBashCandidates(config, environment)]
194
+ for (const candidate of candidates) {
195
+ try {
196
+ const resolved = await subprocess.resolveExecutable(candidate)
197
+ if (isWindowsSubsystemLauncher(resolved)) {
198
+ failures.push(`${candidate}: resolved to the Windows Subsystem for Linux launcher`)
199
+ continue
200
+ }
201
+ return resolved
202
+ } catch (error) {
203
+ failures.push(`${candidate}: ${error instanceof Error ? error.message : String(error)}`)
204
+ }
205
+ }
206
+ throw new Error(`Git Bash executable unavailable (${failures.join('; ')})`)
207
+ }
208
+
209
+ function warn(ctx, message) {
210
+ try {
211
+ ctx.logger.warn(message)
212
+ } catch {
213
+ // Logger unavailable — registration is skipped either way.
214
+ }
215
+ }
216
+
53
217
  /** Register the model-facing `bash` tool. */
54
- export function apply(ctx, config) {
55
- const bashPath = typeof config?.bashPath === 'string' && config.bashPath.length > 0 ? config.bashPath : 'bash'
56
- const timeoutMs = Number.isSafeInteger(config?.timeoutMs) && config.timeoutMs > 0 ? config.timeoutMs : DEFAULT_TIMEOUT_MS
57
- const maxOutputBytes = Number.isSafeInteger(config?.maxOutputBytes) && config.maxOutputBytes > 0 ? config.maxOutputBytes : DEFAULT_MAX_OUTPUT_BYTES
218
+ export async function apply(ctx, config) {
219
+ const source = config === undefined ? {} : config
220
+ const timeoutMs = Number.isSafeInteger(source.timeoutMs) && source.timeoutMs > 0 ? source.timeoutMs : DEFAULT_TIMEOUT_MS
221
+ const maxOutputBytes = Number.isSafeInteger(source.maxOutputBytes) && source.maxOutputBytes > 0 ? source.maxOutputBytes : DEFAULT_MAX_OUTPUT_BYTES
222
+
223
+ let bashPath
224
+ try {
225
+ bashPath = await resolveWindowsBash(ctx.subprocess, source)
226
+ } catch (error) {
227
+ // Skip registration on a miss: an absent `bash` in the assembled catalog
228
+ // makes tool-bootstrap fail open to the full catalog, while a registered
229
+ // tool that cannot spawn would fail on every call mid-session.
230
+ warn(ctx, `custom-bash: ${error instanceof Error ? error.message : String(error)} — the Windows bootstrap bash tool is not registered; the bootstrap filter will expose the full catalog`)
231
+ return
232
+ }
58
233
 
59
234
  ctx.tools.register({
60
235
  name: 'bash',
@@ -69,6 +244,7 @@ export function apply(ctx, config) {
69
244
  '* NOTE: runs without OS sandbox confinement on Windows (no landlock); treat output as untrusted.',
70
245
  ].join('\n'),
71
246
  parameters: commandSchema,
247
+ timeoutMs,
72
248
  output: {
73
249
  schema: {
74
250
  type: 'object',
@@ -81,13 +257,12 @@ export function apply(ctx, config) {
81
257
  render: (_args, value) => [{ type: 'text', text: value.text }],
82
258
  },
83
259
  async execute(args, exec) {
84
- const shell = await ctx.subprocess.resolveExecutable(bashPath, undefined, exec?.signal)
85
260
  const workdir = typeof args.workdir === 'string' && args.workdir.length > 0
86
261
  ? args.workdir
87
262
  : exec?.agent?.session?.header?.cwd
88
263
  const signal = exec?.signal
89
264
  const handle = ctx.subprocess.spawn({
90
- argv: [shell, '-c', args.command],
265
+ argv: [bashPath, '-c', args.command],
91
266
  ...workdir !== undefined ? { cwd: workdir } : {},
92
267
  stdio: {
93
268
  stdin: 'ignore',
@@ -1,8 +1,8 @@
1
- # Changelog
2
-
3
- Changes to `@dsh-std/connection` are recorded here.
4
-
5
- ## 0.1.0 (draft)
6
-
7
- - Defined connection services, endpoint views, participant publication, capability bindings, and attachments.
8
- - Added an in-memory transport for protocol conformance and host integration tests.
1
+ # Changelog
2
+
3
+ Changes to `@dsh-std/connection` are recorded here.
4
+
5
+ ## 0.1.0 (draft)
6
+
7
+ - Defined connection services, endpoint views, participant publication, capability bindings, and attachments.
8
+ - Added an in-memory transport for protocol conformance and host integration tests.
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 DSH Standard contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DSH Standard contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,42 +1,42 @@
1
- # @dsh-std/connection
2
-
3
- English | [中文](README.zh.md)
4
-
5
- The proposed design is documented in [Endpoint Connection](../../docs/proposals/endpoint-connection.zh.md). It separates the application-facing `ConnectionService` from the Connection Host provider SPI. The remainder of this page describes the current reference implementation, which does not yet complete that split.
6
-
7
- Host-provided communication service, two-endpoint capability negotiation, and implementation-neutral invocation for the DSH Standard.
8
-
9
- ## Endpoint offers
10
-
11
- An endpoint offer contains an endpoint identity, a revision, and the live participant declarations admitted by endpoint policy. It carries no component manifests, installation inventory, or plugin registry.
12
-
13
- `resolveConnection()` passes both sets of declarations to a caller-owned `ProtocolCatalog`. Each protocol definition owns its negotiation and may place invocation bindings in its agreement; connection does not impose consumer/provider semantics on every protocol. `defineCapabilityProtocol()` is an explicit helper for domain protocols that do use RPC-shaped bindings.
14
-
15
- Each invocation binding is participant-scoped and plan-revision-scoped. A client for one participant cannot discover or invoke bindings granted to another participant.
16
-
17
- ## Current reference API
18
-
19
- `StandardConnection` exposes endpoint identities, the active plan, consumer-scoped clients, plan-change observation, and close. `CapabilityClient.invoke()` returns an invocation id, a result promise, an asynchronous progress stream, and cancellation. Domain protocol packages own operation names and input, output, and progress values.
20
-
21
- `ConnectionBroker` selects one registered `ConnectionConnector` for an implementation-neutral target URI. Zero matches and multiple matches are both explicit errors. The broker does not expose the selected connector type through `StandardConnection`.
22
-
23
- These types are an early reference implementation. They do not require a TUI, Web UI, GUI, or business plugin to register and operate its own connector. The protocol direction places the broker, connector/provider registry, carrier, and wire behind a Connection Host's `ConnectionService`. A consumer submits a target and uses scoped typed clients for the negotiated protocols.
24
-
25
- A Connection Host may install or discover a remote service, own authentication, ports, forwarding and reconnection, and produce the `StandardConnection`. An SSH target facet contributes resolution and bootstrap integration while system OpenSSH or another provider may supply the physical SSH implementation. Applications do not observe the selected provider, ports, credentials, or wire.
26
-
27
- ## Lifecycle
28
-
29
- Renegotiation creates a complete new plan revision and publishes it atomically. An invocation admitted under the old revision retains its binding until settlement; later invocations use the new revision. Closing a connection cancels active work and rejects new work with `connection-closed`.
30
-
31
- Transport implementations must preserve invocation isolation, progress order, cancellation, and the error classification exposed by `ConnectionInvocationError`. They are also responsible for authenticating the peer and preventing one connection from reusing another connection's grants.
32
-
33
- ## Reference implementation
34
-
35
- The `@dsh-std/connection/memory` export provides a process-local implementation for tests, adapters, and conformance experiments. It demonstrates symmetric calls, progress, cancellation, isolation, and renegotiation. It is not a required carrier or a wire-format specification.
36
-
37
- ## Known Limitations and Deferred Work
38
-
39
- - The consumer-facing `ConnectionService` and Host provider SPI are not implemented in the current code yet.
40
- - The package does not yet standardize discovery, authentication, encryption, reconnect policy, framing, or serialization.
41
- - A connection has exactly two endpoints in `v1alpha1`; multi-party routing is composed from separate connections.
42
- - The capability helper requires one peer provider by default. Protocols that allow multiple providers must opt into and define that behavior explicitly.
1
+ # @dsh-std/connection
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ The proposed design is documented in [Endpoint Connection](../../docs/proposals/endpoint-connection.zh.md). It separates the application-facing `ConnectionService` from the Connection Host provider SPI. The remainder of this page describes the current reference implementation, which does not yet complete that split.
6
+
7
+ Host-provided communication service, two-endpoint capability negotiation, and implementation-neutral invocation for the DSH Standard.
8
+
9
+ ## Endpoint offers
10
+
11
+ An endpoint offer contains an endpoint identity, a revision, and the live participant declarations admitted by endpoint policy. It carries no component manifests, installation inventory, or plugin registry.
12
+
13
+ `resolveConnection()` passes both sets of declarations to a caller-owned `ProtocolCatalog`. Each protocol definition owns its negotiation and may place invocation bindings in its agreement; connection does not impose consumer/provider semantics on every protocol. `defineCapabilityProtocol()` is an explicit helper for domain protocols that do use RPC-shaped bindings.
14
+
15
+ Each invocation binding is participant-scoped and plan-revision-scoped. A client for one participant cannot discover or invoke bindings granted to another participant.
16
+
17
+ ## Current reference API
18
+
19
+ `StandardConnection` exposes endpoint identities, the active plan, consumer-scoped clients, plan-change observation, and close. `CapabilityClient.invoke()` returns an invocation id, a result promise, an asynchronous progress stream, and cancellation. Domain protocol packages own operation names and input, output, and progress values.
20
+
21
+ `ConnectionBroker` selects one registered `ConnectionConnector` for an implementation-neutral target URI. Zero matches and multiple matches are both explicit errors. The broker does not expose the selected connector type through `StandardConnection`.
22
+
23
+ These types are an early reference implementation. They do not require a TUI, Web UI, GUI, or business plugin to register and operate its own connector. The protocol direction places the broker, connector/provider registry, carrier, and wire behind a Connection Host's `ConnectionService`. A consumer submits a target and uses scoped typed clients for the negotiated protocols.
24
+
25
+ A Connection Host may install or discover a remote service, own authentication, ports, forwarding and reconnection, and produce the `StandardConnection`. An SSH target facet contributes resolution and bootstrap integration while system OpenSSH or another provider may supply the physical SSH implementation. Applications do not observe the selected provider, ports, credentials, or wire.
26
+
27
+ ## Lifecycle
28
+
29
+ Renegotiation creates a complete new plan revision and publishes it atomically. An invocation admitted under the old revision retains its binding until settlement; later invocations use the new revision. Closing a connection cancels active work and rejects new work with `connection-closed`.
30
+
31
+ Transport implementations must preserve invocation isolation, progress order, cancellation, and the error classification exposed by `ConnectionInvocationError`. They are also responsible for authenticating the peer and preventing one connection from reusing another connection's grants.
32
+
33
+ ## Reference implementation
34
+
35
+ The `@dsh-std/connection/memory` export provides a process-local implementation for tests, adapters, and conformance experiments. It demonstrates symmetric calls, progress, cancellation, isolation, and renegotiation. It is not a required carrier or a wire-format specification.
36
+
37
+ ## Known Limitations and Deferred Work
38
+
39
+ - The consumer-facing `ConnectionService` and Host provider SPI are not implemented in the current code yet.
40
+ - The package does not yet standardize discovery, authentication, encryption, reconnect policy, framing, or serialization.
41
+ - A connection has exactly two endpoints in `v1alpha1`; multi-party routing is composed from separate connections.
42
+ - The capability helper requires one peer provider by default. Protocols that allow multiple providers must opt into and define that behavior explicitly.