dsh-gitbash-shell 0.14.0 → 0.16.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/README.md +25 -4
- package/README_EN.md +31 -4
- package/assets/cordis-gitbash/agent.cordis.ptc.ps.yml +11 -1
- package/dsh.plugin.json +1 -1
- package/package.json +1 -1
- package/src/client.js +468 -37
- package/src/index.js +190 -60
package/README.md
CHANGED
|
@@ -144,9 +144,30 @@ preset 会被插件自动清理;宿主 shell 回退为 PowerShell。
|
|
|
144
144
|
> 切换生效后若 `ptc-cordis` 目录已存在且被旧版本物化,删除
|
|
145
145
|
> `~/.dsh/.agent-presets/ptc-cordis` 并重启,即由新逻辑重新物化。
|
|
146
146
|
|
|
147
|
-
## POSIX
|
|
148
|
-
|
|
149
|
-
Windows 上本插件把宿主 shell 换成 Git Bash
|
|
147
|
+
## POSIX 路径方言(v0.7.0 引入,受 `posixPaths` 开关门控)
|
|
148
|
+
|
|
149
|
+
Windows 上本插件把宿主 shell 换成 Git Bash 的同时,让**模型看到的路径**统一成 MSYS 盘根
|
|
150
|
+
POSIX 形式(`/c/Users/...`、`/c/Program Files/...`)。开关是 settings 命名空间
|
|
151
|
+
`gitbash-shell` 的布尔字段 `posixPaths`,**默认开启**(v0.10.0 起),可在 **设置 → 插件**
|
|
152
|
+
里本插件的「Git Bash 路径方言」卡片上随时切换;不修改任何 preset / 组合文件,标准/极简/
|
|
153
|
+
PTC/创造及用户自建模式一律覆盖。
|
|
154
|
+
|
|
155
|
+
开启时(仅 Win32),`posixPaths` 门控以下全部行为:
|
|
156
|
+
|
|
157
|
+
- **提示词源头替换**:组装期(`system-prompt/assemble`)把官方提示词 sections / contexts /
|
|
158
|
+
variables 里的 Windows 绝对路径**原位**改写成 `/c/...`——不增删任何内容、不动工具 schema;
|
|
159
|
+
- **一句话指示**:经 `systemPrompt.context`(order 126)注入全局指示——shell 是 Git for
|
|
160
|
+
Windows bash,路径用 MSYS 盘根,所有工具都直接接受这种写法;
|
|
161
|
+
- **参数翻译**:`tools/execute` 上把文件工具的路径参数(`file_path` / `path` / `workdir`)由
|
|
162
|
+
`/c/...` 翻回 `C:/...` 交给 Node 文件工具;bash 的 `command` 字段不动——那是 Git Bash 母语;
|
|
163
|
+
- **结果回流**:成功结果里的路径元数据(`read`/`write`/`edit` 的 `path`、`glob` 的 `paths[]`、
|
|
164
|
+
`grep` 的 `matches[].path`)改写回 MSYS 形式;文件内容与错误结果不动;
|
|
165
|
+
- **运行时事实**:向官方 `dsh-shell-env` 注册表贡献 `DSH_PATH_DIALECT=msys`,模型可在执行时
|
|
166
|
+
核验(随开关实时生效)。
|
|
167
|
+
|
|
168
|
+
关闭后回到 dsh 原生行为:指示文本为空(组装期直接丢弃,零提示噪声),路径参数与结果元数据
|
|
169
|
+
都不再改写,文件工具收 Windows 路径。**bash 始终是 Git Bash,不受此开关影响**——它只决定
|
|
170
|
+
跨工具的路径方言。
|
|
150
171
|
|
|
151
172
|
## 与 dsh-better-sidebar 联动
|
|
152
173
|
|
|
@@ -158,4 +179,4 @@ Windows 上本插件把宿主 shell 换成 Git Bash 的同时,会向**每个会
|
|
|
158
179
|
|
|
159
180
|
## 许可
|
|
160
181
|
|
|
161
|
-
MIT © KannaKuron。参考与致敬:[dsh-ptc-cordis-preset](https://github.com/KannaKuron/dsh-ptc-cordis-preset)。
|
|
182
|
+
MIT © KannaKuron。参考与致敬:[dsh-ptc-cordis-preset](https://github.com/KannaKuron/dsh-ptc-cordis-preset)。
|
package/README_EN.md
CHANGED
|
@@ -83,9 +83,36 @@ the PTC preset is materialized as Git Bash automatically (tool-bash on,
|
|
|
83
83
|
tool-pwsh off) — no extra mode, no manual edits. Without this plugin the PTC
|
|
84
84
|
preset stays as its own plugin manages it.
|
|
85
85
|
|
|
86
|
-
## POSIX path
|
|
87
|
-
|
|
88
|
-
While replacing the host shell with Git Bash, this plugin
|
|
86
|
+
## POSIX path dialect (introduced in v0.7.0, gated by the `posixPaths` switch)
|
|
87
|
+
|
|
88
|
+
While replacing the host shell with Git Bash on Windows, this plugin makes every path the
|
|
89
|
+
model sees use the MSYS drive-root POSIX form (/c/Users/..., /c/Program Files/...). The switch
|
|
90
|
+
is the `posixPaths` boolean in the `gitbash-shell` settings namespace; it is **on by default**
|
|
91
|
+
(since v0.10.0) and can be toggled any time on this plugin's "Git Bash path dialect" card in
|
|
92
|
+
**Settings → Plugins**. No preset or composition file is touched, and every mode —
|
|
93
|
+
standard/minimal/PTC/creation and user-authored presets — is covered.
|
|
94
|
+
|
|
95
|
+
While it is on (Windows only), `posixPaths` gates all of the following:
|
|
96
|
+
|
|
97
|
+
- **Source-level rewrite**: during assembly (`system-prompt/assemble`) every Windows absolute
|
|
98
|
+
path in the official prompt's sections, contexts, and variables is rewritten in place to the
|
|
99
|
+
/c/... form — nothing is added or removed, and tool schemas stay untouched;
|
|
100
|
+
- **One-sentence directive**: a global directive via `systemPrompt.context` (order 126) — the
|
|
101
|
+
shell is Git for Windows bash, paths use MSYS drive roots, and every tool accepts that form
|
|
102
|
+
directly;
|
|
103
|
+
- **Argument translation**: on `tools/execute` the file tools' path arguments (`file_path` /
|
|
104
|
+
`path` / `workdir`) are translated from /c/... back to C:/... for the Node-backed file tools;
|
|
105
|
+
a bash command's `command` field is left alone — that is Git Bash's native form;
|
|
106
|
+
- **Result round-trip**: path metadata in successful results (`path` of read/write/edit,
|
|
107
|
+
`paths[]` of glob, `matches[].path` of grep) flows back in the MSYS form; file contents and
|
|
108
|
+
error results are untouched;
|
|
109
|
+
- **Runtime fact**: `DSH_PATH_DIALECT=msys` is contributed to the official `dsh-shell-env`
|
|
110
|
+
registry, so the model can verify the dialect at execution time (it follows the live switch).
|
|
111
|
+
|
|
112
|
+
With the switch off, dsh-native behavior returns: the directive text is empty (dropped at
|
|
113
|
+
assembly, so zero prompt noise), path arguments and result metadata are no longer rewritten, and
|
|
114
|
+
the file tools receive Windows paths. **Bash stays Git Bash either way** — the switch only
|
|
115
|
+
governs the cross-tool path dialect.
|
|
89
116
|
|
|
90
117
|
## Cooperation with dsh-better-sidebar
|
|
91
118
|
|
|
@@ -98,4 +125,4 @@ When [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar) (v0.1
|
|
|
98
125
|
## License
|
|
99
126
|
|
|
100
127
|
MIT © KannaKuron. Inspired by
|
|
101
|
-
[dsh-ptc-cordis-preset](https://github.com/KannaKuron/dsh-ptc-cordis-preset).
|
|
128
|
+
[dsh-ptc-cordis-preset](https://github.com/KannaKuron/dsh-ptc-cordis-preset).
|
|
@@ -34,10 +34,20 @@
|
|
|
34
34
|
|
|
35
35
|
Two planes decide where an edit belongs. The HOST composition holds the registries and anything shared across sessions — persistence, the sandbox and approval stack, the model route, the subagent registry and its backends. An AGENT PRESET holds what one session contributes to those registries: its tools, its persona, its prompt sections. A row that publishes a service belongs in the host composition, or inside an `isolate` realm if the preset genuinely owns that service and nothing outside one agent reads it.
|
|
36
36
|
|
|
37
|
-
Presets you author live one directory per preset under `${DSH_HOME:-$HOME/.dsh}/.agent-presets/<id
|
|
37
|
+
Presets you author live one directory per preset under `${DSH_HOME:-$HOME/.dsh}/.agent-presets/<id>/`. Load `editing-cordis-compositions` for file discovery and copying instructions. NEVER edit or delete the shipped preset install (the `agent-presets` directory beside the deployment's own config): it belongs to the deployment, an upgrade overwrites it, and corrupting the `cordis` preset would disable this very mode. To change what a shipped preset does, copy its composition into a new preset directory and edit the copy.
|
|
38
38
|
|
|
39
39
|
Load the `editing-cordis-compositions` skill before writing or changing a composition.
|
|
40
40
|
|
|
41
|
+
Use plugin_manager for persistent bundle installation, removal and enablement in the current profile. Author plugin code and configuration as ordinary workspace bundle files. Changes affect every session in that profile. Read saved-state and activation outcomes separately; restart-required means the new capability is not available yet.
|
|
42
|
+
|
|
43
|
+
In Creator mode, requests to make a visual object, decoration, or widget mean creating an installed UI plugin that displays it in this Harness Web UI, unless the user specifies another destination. Choose reasonable visual details and proceed. Load cordis-plugin-development, inspect the Client slots, build the plugin in the workspace, and install it with plugin_manager. Install a minimal working version before visual refinement; use the connected page as its preview. Verify that the open page renders it; a standalone image or HTML file does not complete an in-app creation request.
|
|
44
|
+
|
|
45
|
+
Load the cordis-plugin-development skill before authoring an installed plugin. Use cordis_inspect_list to discover Host and Client providers, then cordis_inspect_query to read exact Service, Event, Tool, Theme or Slot APIs. These tools are read-only; queries do not invoke business methods.
|
|
46
|
+
|
|
47
|
+
To connect an MCP server, create a configuration-only bundle whose patch inserts @deepseek-ai/dsh-mcp-client, then install it with plugin_manager. Load cordis-plugin-development for the package and YAML examples. After successful activation, call one of the newly available mcp__<serverName>__<tool> tools to verify the connection.
|
|
48
|
+
|
|
49
|
+
Use installed bundles for new plugin code. Package installation may require explicit user approval for build scripts. Preserve returned failures and pending states; only report success after observing the requested capability.
|
|
50
|
+
|
|
41
51
|
- id: agent-instructions
|
|
42
52
|
name: '@deepseek-ai/dsh-agent-instructions'
|
|
43
53
|
config:
|
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-gitbash-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.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.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "DSH plugin: run every agent shell command through Git for Windows bash on Windows instead of PowerShell. Replaces the pwsh executor with a Git Bash ctx.shell provider and materializes Git Bash variants of the standard/minimal/code/cordis agent presets into your user preset root at startup. On Windows it also adopts dsh-better-sidebar's terminal shell (UI tabs and the model-facing terminal_* tools) through the sidebar's official settings seam, and pairs with dsh-ptc-cordis-preset so the PTC Creation-mode preset materializes as its Git Bash variant. Ships both composition eras for dsh <= 0.1.1 (built-in preset id 'code') and dsh >= 0.1.2 (renamed id 'ptc') — the era is probed per boot and re-materialized automatically after a dsh upgrade, in either upgrade order; preset ids never change so pinned sessions stay valid.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/client.js
CHANGED
|
@@ -21,7 +21,11 @@
|
|
|
21
21
|
* (react and @deepseek-ai/dsh-client-ui-primitives only, smoke-enforced);
|
|
22
22
|
* - plain React.createElement, no JSX/TS; components at module level;
|
|
23
23
|
* - dsh.client.inject in package.json lists the packages that must load
|
|
24
|
-
* first so locale / settingsScope / slots exist when this applies
|
|
24
|
+
* first so locale / settingsScope / slots exist when this applies;
|
|
25
|
+
* - copy ships in three layers: zh/en inline, one LOCALES entry per third
|
|
26
|
+
* language (each preceded by a locale marker line), every dictionary
|
|
27
|
+
* key-aligned with zh (smoke-enforced) and read through a live lookup —
|
|
28
|
+
* DSH's language preference switches without a page reload.
|
|
25
29
|
*/
|
|
26
30
|
window.__ModuleLoader__.load({
|
|
27
31
|
id: "dsh-gitbash-shell",
|
|
@@ -35,6 +39,7 @@ window.__ModuleLoader__.load({
|
|
|
35
39
|
|
|
36
40
|
var E = React.createElement;
|
|
37
41
|
var useState = React.useState;
|
|
42
|
+
var useEffect = React.useEffect;
|
|
38
43
|
|
|
39
44
|
var TAG = "[gitbash-shell/client]";
|
|
40
45
|
/** Dictionary namespace (the plugin's own t seat). */
|
|
@@ -42,11 +47,15 @@ window.__ModuleLoader__.load({
|
|
|
42
47
|
/** The settings namespace the HOST half serves. */
|
|
43
48
|
var SETTINGS_NAMESPACE = "gitbash-shell";
|
|
44
49
|
|
|
45
|
-
// ── dictionaries
|
|
50
|
+
// ── dictionaries ────────────────────────────────────────────────────────
|
|
51
|
+
// zh/en stay inline; the third languages live in LOCALES below, one entry
|
|
52
|
+
// per language behind a locale marker line. EVERY shipped dictionary MUST
|
|
53
|
+
// carry zh's exact key set: a missing key falls back to English at lookup
|
|
54
|
+
// time, which reads as a half-translated card (smoke-enforced).
|
|
46
55
|
|
|
47
56
|
var zh = {
|
|
48
57
|
"title": "Git Bash 路径方言",
|
|
49
|
-
"cardDesc": "所有工具统一 /c/ POSIX 路径形式(
|
|
58
|
+
"cardDesc": "所有工具统一 /c/ POSIX 路径形式(默认开启)",
|
|
50
59
|
"state.label": "当前状态",
|
|
51
60
|
"state.on": "已启用",
|
|
52
61
|
"state.off": "已关闭",
|
|
@@ -54,11 +63,13 @@ window.__ModuleLoader__.load({
|
|
|
54
63
|
"switch.off": "停用",
|
|
55
64
|
"error": "写入失败",
|
|
56
65
|
"hint": "启用后:所有工具(bash 命令与 workdir、read/write/edit/read_image/glob/grep 的路径参数)统一使用 MSYS 盘根 POSIX 路径(/c/Users/...);文件工具的路径参数由宿主自动翻译,模型无感。停用后恢复 dsh 原生行为(文件工具用 Windows 路径)。bash 始终是 Git Bash,不受此开关影响。",
|
|
66
|
+
"adopt.label": "接管侧栏终端",
|
|
67
|
+
"adopt.hint": "开启时把 dsh-better-sidebar 的终端 shell 写成 Git Bash(默认开启);关闭后恢复接管前的值,已手动改过的终端设置不会被碰。模型侧的 bash 工具不受此开关影响——那由插件本体提供。",
|
|
57
68
|
};
|
|
58
69
|
|
|
59
70
|
var en = {
|
|
60
71
|
"title": "Git Bash path dialect",
|
|
61
|
-
"cardDesc": "One /c/ POSIX path style for every tool (
|
|
72
|
+
"cardDesc": "One /c/ POSIX path style for every tool (on by default)",
|
|
62
73
|
"state.label": "Current state",
|
|
63
74
|
"state.on": "Enabled",
|
|
64
75
|
"state.off": "Disabled",
|
|
@@ -66,8 +77,344 @@ window.__ModuleLoader__.load({
|
|
|
66
77
|
"switch.off": "Disable",
|
|
67
78
|
"error": "write failed",
|
|
68
79
|
"hint": "Enabled: every tool (bash commands and workdir, read/write/edit/read_image/glob/grep path arguments) uses MSYS drive-root POSIX paths (/c/Users/...); the host translates path fields for the file tools automatically. Disabled restores dsh-native behavior (Windows paths for file tools). Bash is always Git Bash while the plugin is installed; this switch only governs the cross-tool path dialect.",
|
|
80
|
+
"adopt.label": "Adopt sidebar terminal",
|
|
81
|
+
"adopt.hint": "On (default) writes Git Bash into dsh-better-sidebar's terminal shell; turning it off restores the pre-adoption value and never touches a manually chosen one. The model-side bash tool is unaffected — the plugin itself provides that.",
|
|
69
82
|
};
|
|
70
83
|
|
|
84
|
+
/* Third-language dictionaries: one entry per language, each preceded
|
|
85
|
+
by a locale marker line the smoke test slices on. Adding a language is
|
|
86
|
+
one entry here and nothing else — the dictionaries also ride the
|
|
87
|
+
ctx.locale.register call below, so host-side consumers read the same
|
|
88
|
+
copy the card does. Every key set MUST equal zh's exactly: a missing
|
|
89
|
+
key falls back to English silently and the card looks half-translated.
|
|
90
|
+
zh-hk and zh-mo ship one Cantonese-flavoured copy; zh-tw carries the
|
|
91
|
+
Taiwan wording. */
|
|
92
|
+
var LOCALES = {
|
|
93
|
+
/* locale: ar */
|
|
94
|
+
"ar": {
|
|
95
|
+
"title": "لهجة مسارات Git Bash",
|
|
96
|
+
"cardDesc": "صيغة مسار POSIX موحّدة /c/ لكل الأدوات (مُفعَّلة افتراضيًا)",
|
|
97
|
+
"state.label": "الحالة الحالية",
|
|
98
|
+
"state.on": "مُفعَّلة",
|
|
99
|
+
"state.off": "مُعطَّلة",
|
|
100
|
+
"switch.on": "تفعيل",
|
|
101
|
+
"switch.off": "تعطيل",
|
|
102
|
+
"error": "فشل الكتابة",
|
|
103
|
+
"hint": "عند التفعيل: تستخدم كل الأدوات (أوامر bash و workdir، ومعاملات المسار في read/write/edit/read_image/glob/grep) مسارات POSIX من جذر قرص MSYS (/c/Users/...)؛ ويتولّى المضيف ترجمة حقول المسار لأدوات الملفات تلقائيًا. عند التعطيل يعود السلوك الأصلي لـ dsh (مسارات Windows لأدوات الملفات). يبقى bash دائمًا Git Bash ما دامت الإضافة مثبَّتة؛ هذا المفتاح لا يحكم سوى لهجة المسارات بين الأدوات.",
|
|
104
|
+
"adopt.label": "تبنّي طرفية الشريط الجانبي",
|
|
105
|
+
"adopt.hint": "عند التفعيل (افتراضي) تُكتب Git Bash كـ shell لطرفية dsh-better-sidebar؛ وعند التعطيل تُستعاد القيمة السابقة ولا تُلمس القيمة المختارة يدويًا أبدًا. أداة bash الخاصة بالنموذج لا تتأثر — الإضافة نفسها توفرها.",
|
|
106
|
+
},
|
|
107
|
+
/* locale: de */
|
|
108
|
+
"de": {
|
|
109
|
+
"title": "Git-Bash-Pfaddialekt",
|
|
110
|
+
"cardDesc": "Eine einheitliche /c/-POSIX-Pfadform für alle Tools (standardmäßig an)",
|
|
111
|
+
"state.label": "Aktueller Status",
|
|
112
|
+
"state.on": "Aktiviert",
|
|
113
|
+
"state.off": "Deaktiviert",
|
|
114
|
+
"switch.on": "Aktivieren",
|
|
115
|
+
"switch.off": "Deaktivieren",
|
|
116
|
+
"error": "Schreiben fehlgeschlagen",
|
|
117
|
+
"hint": "Aktiviert: Alle Tools (bash-Befehle und workdir sowie Pfadargumente von read/write/edit/read_image/glob/grep) verwenden POSIX-Pfade ab der MSYS-Laufwerkswurzel (/c/Users/...); der Host übersetzt die Pfadfelder der Dateitools automatisch. Deaktiviert stellt das dsh-native Verhalten wieder her (Windows-Pfade für Dateitools). Bash ist bei installiertem Plugin immer Git Bash; dieser Schalter steuert nur den Pfaddialekt zwischen den Tools.",
|
|
118
|
+
"adopt.label": "Sidebar-Terminal übernehmen",
|
|
119
|
+
"adopt.hint": "Ein (Standard) schreibt Git Bash als Shell des dsh-better-sidebar-Terminals; Aus stellt den vorherigen Wert wieder her und fasst nie eine manuell gewählte Einstellung an. Das bash-Werkzeug des Modells bleibt unberührt — das liefert das Plugin selbst.",
|
|
120
|
+
},
|
|
121
|
+
/* locale: fr */
|
|
122
|
+
"fr": {
|
|
123
|
+
"title": "Dialecte de chemins Git Bash",
|
|
124
|
+
"cardDesc": "Une forme de chemin POSIX /c/ unique pour tous les outils (activée par défaut)",
|
|
125
|
+
"state.label": "État actuel",
|
|
126
|
+
"state.on": "Activé",
|
|
127
|
+
"state.off": "Désactivé",
|
|
128
|
+
"switch.on": "Activer",
|
|
129
|
+
"switch.off": "Désactiver",
|
|
130
|
+
"error": "échec de l'écriture",
|
|
131
|
+
"hint": "Activé : tous les outils (commandes bash et workdir, arguments de chemin de read/write/edit/read_image/glob/grep) utilisent des chemins POSIX à racine de lecteur MSYS (/c/Users/...) ; l'hôte traduit automatiquement les champs de chemin des outils de fichiers. Désactivé rétablit le comportement natif de dsh (chemins Windows pour les outils de fichiers). Bash reste toujours Git Bash tant que le plugin est installé ; ce commutateur ne régit que le dialecte de chemins entre outils.",
|
|
132
|
+
"adopt.label": "Adopter le terminal latéral",
|
|
133
|
+
"adopt.hint": "Activé (par défaut) : écrit Git Bash comme shell du terminal dsh-better-sidebar ; désactivé : restaure la valeur davant et ne touche jamais un choix manuel. Loutil bash du modèle nest pas concerné — le plugin le fournit lui-même.",
|
|
134
|
+
},
|
|
135
|
+
/* locale: hi */
|
|
136
|
+
"hi": {
|
|
137
|
+
"title": "Git Bash पथ शैली",
|
|
138
|
+
"cardDesc": "सभी टूल के लिए एक ही /c/ POSIX पथ रूप (डिफ़ॉल्ट रूप से सक्षम)",
|
|
139
|
+
"state.label": "वर्तमान स्थिति",
|
|
140
|
+
"state.on": "सक्षम",
|
|
141
|
+
"state.off": "अक्षम",
|
|
142
|
+
"switch.on": "सक्षम करें",
|
|
143
|
+
"switch.off": "अक्षम करें",
|
|
144
|
+
"error": "लिखना विफल रहा",
|
|
145
|
+
"hint": "सक्षम होने पर: सभी टूल (bash कमांड और workdir, तथा read/write/edit/read_image/glob/grep के पथ तर्क) MSYS ड्राइव-रूट POSIX पथ (/c/Users/...) का उपयोग करते हैं; फ़ाइल टूल के पथ फ़ील्ड होस्ट स्वतः अनुवादित करता है। अक्षम करने पर dsh का मूल व्यवहार बहाल होता है (फ़ाइल टूल के लिए Windows पथ)। जब तक प्लगइन इंस्टॉल है bash हमेशा Git Bash रहता है; यह स्विच केवल टूल के बीच पथ शैली नियंत्रित करता है।",
|
|
146
|
+
"adopt.label": "साइडबार टर्मिनल अपनाएँ",
|
|
147
|
+
"adopt.hint": "चालू (डिफ़ॉल्ट) होने पर dsh-better-sidebar के टर्मिनल में Git Bash लिखा जाता है; बंद करने पर पहले वाली मान बहाल होती है और मैन्युअल चुनी गई सेटिंग कभी नहीं छुई जाती। मॉडल का bash टूल अप्रभावित रहता है — वह प्लगइन स्वयं देता है।",
|
|
148
|
+
},
|
|
149
|
+
/* locale: id */
|
|
150
|
+
"id": {
|
|
151
|
+
"title": "Dialek path Git Bash",
|
|
152
|
+
"cardDesc": "Satu bentuk path POSIX /c/ untuk semua alat (aktif secara bawaan)",
|
|
153
|
+
"state.label": "Status saat ini",
|
|
154
|
+
"state.on": "Aktif",
|
|
155
|
+
"state.off": "Nonaktif",
|
|
156
|
+
"switch.on": "Aktifkan",
|
|
157
|
+
"switch.off": "Nonaktifkan",
|
|
158
|
+
"error": "gagal menulis",
|
|
159
|
+
"hint": "Saat aktif: semua alat (perintah bash dan workdir, serta argumen path read/write/edit/read_image/glob/grep) memakai path POSIX berakar drive MSYS (/c/Users/...); host menerjemahkan bidang path untuk alat berkas secara otomatis. Saat nonaktif, perilaku asli dsh dipulihkan (path Windows untuk alat berkas). Bash selalu Git Bash selama plugin terpasang; sakelar ini hanya mengatur dialek path antaralat.",
|
|
160
|
+
"adopt.label": "Adopsi terminal sidebar",
|
|
161
|
+
"adopt.hint": "Nyala (bawaan) menulis Git Bash sebagai shell terminal dsh-better-sidebar; dimatikan memulihkan nilai sebelumnya dan tidak pernah menyentuh pilihan manual. Alat bash sisi model tak terpengaruh — plugin sendiri yang menyediakannya.",
|
|
162
|
+
},
|
|
163
|
+
/* locale: it */
|
|
164
|
+
"it": {
|
|
165
|
+
"title": "Dialetto dei percorsi Git Bash",
|
|
166
|
+
"cardDesc": "Un'unica forma di percorso POSIX /c/ per tutti gli strumenti (attivata per impostazione predefinita)",
|
|
167
|
+
"state.label": "Stato attuale",
|
|
168
|
+
"state.on": "Attivato",
|
|
169
|
+
"state.off": "Disattivato",
|
|
170
|
+
"switch.on": "Attiva",
|
|
171
|
+
"switch.off": "Disattiva",
|
|
172
|
+
"error": "scrittura non riuscita",
|
|
173
|
+
"hint": "Attivato: tutti gli strumenti (comandi bash e workdir, argomenti di percorso di read/write/edit/read_image/glob/grep) usano percorsi POSIX con radice di unità MSYS (/c/Users/...); l'host traduce automaticamente i campi di percorso degli strumenti per i file. Disattivato ripristina il comportamento nativo di dsh (percorsi Windows per gli strumenti per i file). Bash resta sempre Git Bash finché il plugin è installato; questo interruttore governa solo il dialetto dei percorsi tra gli strumenti.",
|
|
174
|
+
"adopt.label": "Adotta il terminale laterale",
|
|
175
|
+
"adopt.hint": "Attivo (predefinito) imposta Git Bash come shell del terminale di dsh-better-sidebar; disattivo ripristina il valore precedente e non tocca mai una scelta manuale. Lo strumento bash del modello non è interessato — lo fornisce il plugin stesso.",
|
|
176
|
+
},
|
|
177
|
+
/* locale: ja */
|
|
178
|
+
"ja": {
|
|
179
|
+
"title": "Git Bash パス方言",
|
|
180
|
+
"cardDesc": "すべてのツールで /c/ POSIX パス形式に統一(既定ではオン)",
|
|
181
|
+
"state.label": "現在の状態",
|
|
182
|
+
"state.on": "有効",
|
|
183
|
+
"state.off": "無効",
|
|
184
|
+
"switch.on": "有効にする",
|
|
185
|
+
"switch.off": "無効にする",
|
|
186
|
+
"error": "書き込みに失敗しました",
|
|
187
|
+
"hint": "有効にすると、すべてのツール(bash コマンドと workdir、read/write/edit/read_image/glob/grep のパス引数)が MSYS ドライブルートの POSIX パス(/c/Users/...)を使います。ファイルツールのパスフィールドはホストが自動的に変換します。無効にすると dsh 本来の動作(ファイルツールは Windows パス)に戻ります。bash はプラグインがインストールされている限り常に Git Bash で、このスイッチの影響を受けません。",
|
|
188
|
+
"adopt.label": "サイドバーターミナルを引き継ぐ",
|
|
189
|
+
"adopt.hint": "オン(既定)では dsh-better-sidebar のターミナルシェルに Git Bash を書き込みます。オフにすると以前の値へ戻し、手動で選択した設定には決して触れません。モデル側の bash ツールには影響しません——それはプラグイン本体が提供します。",
|
|
190
|
+
},
|
|
191
|
+
/* locale: ko */
|
|
192
|
+
"ko": {
|
|
193
|
+
"title": "Git Bash 경로 방언",
|
|
194
|
+
"cardDesc": "모든 도구에 하나의 /c/ POSIX 경로 형식 사용(기본값 켜짐)",
|
|
195
|
+
"state.label": "현재 상태",
|
|
196
|
+
"state.on": "사용",
|
|
197
|
+
"state.off": "사용 안 함",
|
|
198
|
+
"switch.on": "사용",
|
|
199
|
+
"switch.off": "사용 안 함",
|
|
200
|
+
"error": "쓰기 실패",
|
|
201
|
+
"hint": "켜면 모든 도구(bash 명령과 workdir, read/write/edit/read_image/glob/grep의 경로 인수)가 MSYS 드라이브 루트 POSIX 경로(/c/Users/...)를 사용합니다. 파일 도구의 경로 필드는 호스트가 자동으로 변환합니다. 끄면 dsh 기본 동작(파일 도구에 Windows 경로 사용)으로 돌아갑니다. 플러그인이 설치되어 있는 동안 bash는 항상 Git Bash이며 이 스위치의 영향을 받지 않습니다.",
|
|
202
|
+
"adopt.label": "사이드바 터미널 인수",
|
|
203
|
+
"adopt.hint": "켜짐(기본)이면 dsh-better-sidebar 터미널 셸에 Git Bash를 기록하고, 끄면 이전 값을 복원하며 수동으로 고른 설정은 절대 건드리지 않습니다. 모델 측 bash 도구에는 영향이 없습니다 — 플러그인이 직접 제공합니다.",
|
|
204
|
+
},
|
|
205
|
+
/* locale: nl */
|
|
206
|
+
"nl": {
|
|
207
|
+
"title": "Git Bash-paddialect",
|
|
208
|
+
"cardDesc": "Eén /c/ POSIX-padvorm voor alle tools (standaard aan)",
|
|
209
|
+
"state.label": "Huidige status",
|
|
210
|
+
"state.on": "Ingeschakeld",
|
|
211
|
+
"state.off": "Uitgeschakeld",
|
|
212
|
+
"switch.on": "Inschakelen",
|
|
213
|
+
"switch.off": "Uitschakelen",
|
|
214
|
+
"error": "schrijven mislukt",
|
|
215
|
+
"hint": "Ingeschakeld: alle tools (bash-opdrachten en workdir, padargumenten van read/write/edit/read_image/glob/grep) gebruiken POSIX-paden vanaf de MSYS-schijfwortel (/c/Users/...); de host vertaalt de padvelden voor de bestandstools automatisch. Uitgeschakeld herstelt het oorspronkelijke dsh-gedrag (Windows-paden voor bestandstools). Bash is altijd Git Bash zolang de plugin is geïnstalleerd; deze schakelaar bepaalt alleen het paddialect tussen de tools.",
|
|
216
|
+
"adopt.label": "Zijbalkterminal overnemen",
|
|
217
|
+
"adopt.hint": "Aan (standaard) schrijft Git Bash als shell van de dsh-better-sidebar-terminal; uit herstelt de vorige waarde en raakt nooit een handmatige keuze aan. De bash-tool van het model blijft buiten beschouwing — die levert de plugin zelf.",
|
|
218
|
+
},
|
|
219
|
+
/* locale: pl */
|
|
220
|
+
"pl": {
|
|
221
|
+
"title": "Dialekt ścieżek Git Bash",
|
|
222
|
+
"cardDesc": "Jedna postać ścieżki POSIX /c/ dla wszystkich narzędzi (domyślnie włączone)",
|
|
223
|
+
"state.label": "Bieżący stan",
|
|
224
|
+
"state.on": "Włączone",
|
|
225
|
+
"state.off": "Wyłączone",
|
|
226
|
+
"switch.on": "Włącz",
|
|
227
|
+
"switch.off": "Wyłącz",
|
|
228
|
+
"error": "zapis nie powiódł się",
|
|
229
|
+
"hint": "Po włączeniu: wszystkie narzędzia (polecenia bash i workdir oraz argumenty ścieżek w read/write/edit/read_image/glob/grep) używają ścieżek POSIX od korzenia dysku MSYS (/c/Users/...); host automatycznie tłumaczy pola ścieżek narzędzi plikowych. Wyłączenie przywraca natywne zachowanie dsh (ścieżki Windows dla narzędzi plikowych). Bash jest zawsze Git Bash, dopóki wtyczka jest zainstalowana; ten przełącznik reguluje wyłącznie dialekt ścieżek między narzędziami.",
|
|
230
|
+
"adopt.label": "Przejmij terminal boczny",
|
|
231
|
+
"adopt.hint": "Włączony (domyślnie) zapisuje Git Bash jako shell terminala dsh-better-sidebar; wyłączony przywraca poprzednią wartość i nigdy nie narusza ręcznie wybranego ustawienia. Narzędzie bash po stronie modelu jest nietknięte — zapewnia je sama wtyczka.",
|
|
232
|
+
},
|
|
233
|
+
/* locale: pt */
|
|
234
|
+
"pt": {
|
|
235
|
+
"title": "Dialeto de caminhos do Git Bash",
|
|
236
|
+
"cardDesc": "Uma única forma de caminho POSIX /c/ para todas as ferramentas (ativada por padrão)",
|
|
237
|
+
"state.label": "Estado atual",
|
|
238
|
+
"state.on": "Ativada",
|
|
239
|
+
"state.off": "Desativada",
|
|
240
|
+
"switch.on": "Ativar",
|
|
241
|
+
"switch.off": "Desativar",
|
|
242
|
+
"error": "falha ao gravar",
|
|
243
|
+
"hint": "Ativada: todas as ferramentas (comandos bash e workdir, argumentos de caminho de read/write/edit/read_image/glob/grep) usam caminhos POSIX a partir da raiz da unidade MSYS (/c/Users/...); o host traduz automaticamente os campos de caminho das ferramentas de arquivo. Desativada restaura o comportamento nativo do dsh (caminhos Windows para as ferramentas de arquivo). O bash é sempre Git Bash enquanto o plugin estiver instalado; este interruptor rege apenas o dialeto de caminhos entre ferramentas.",
|
|
244
|
+
"adopt.label": "Adotar o terminal lateral",
|
|
245
|
+
"adopt.hint": "Ligado (padrão) grava o Git Bash como shell do terminal do dsh-better-sidebar; desligado restaura o valor anterior e nunca altera uma escolha manual. A ferramenta bash do modelo não é afetada — o próprio plug-in a fornece.",
|
|
246
|
+
},
|
|
247
|
+
/* locale: ru */
|
|
248
|
+
"ru": {
|
|
249
|
+
"title": "Диалект путей Git Bash",
|
|
250
|
+
"cardDesc": "Единый POSIX-формат путей /c/ для всех инструментов (по умолчанию включено)",
|
|
251
|
+
"state.label": "Текущее состояние",
|
|
252
|
+
"state.on": "Включено",
|
|
253
|
+
"state.off": "Выключено",
|
|
254
|
+
"switch.on": "Включить",
|
|
255
|
+
"switch.off": "Выключить",
|
|
256
|
+
"error": "не удалось записать",
|
|
257
|
+
"hint": "Включено: все инструменты (команды bash и workdir, аргументы путей read/write/edit/read_image/glob/grep) используют POSIX-пути от корня диска MSYS (/c/Users/...); хост автоматически преобразует поля путей для файловых инструментов. Выключение возвращает исходное поведение dsh (пути Windows для файловых инструментов). Пока плагин установлен, bash всегда остаётся Git Bash; этот переключатель управляет только диалектом путей между инструментами.",
|
|
258
|
+
"adopt.label": "Перехватывать терминал боковой панели",
|
|
259
|
+
"adopt.hint": "Включено (по умолчанию): Git Bash записывается как shell терминала dsh-better-sidebar; выключено — восстанавливается прежнее значение, вручную выбранные настройки не трогаются. Инструмент bash у модели не затронут — его предоставляет сам плагин.",
|
|
260
|
+
},
|
|
261
|
+
/* locale: sv */
|
|
262
|
+
"sv": {
|
|
263
|
+
"title": "Git Bash-sökvägsdialekt",
|
|
264
|
+
"cardDesc": "En /c/ POSIX-sökvägsform för alla verktyg (på som standard)",
|
|
265
|
+
"state.label": "Aktuell status",
|
|
266
|
+
"state.on": "Aktiverad",
|
|
267
|
+
"state.off": "Inaktiverad",
|
|
268
|
+
"switch.on": "Aktivera",
|
|
269
|
+
"switch.off": "Inaktivera",
|
|
270
|
+
"error": "skrivning misslyckades",
|
|
271
|
+
"hint": "Aktiverad: alla verktyg (bash-kommandon och workdir, sökvägsargument för read/write/edit/read_image/glob/grep) använder POSIX-sökvägar från MSYS-enhetsroten (/c/Users/...); värden översätter sökvägsfälten för filverktygen automatiskt. Inaktiverad återställer dsh:s ursprungliga beteende (Windows-sökvägar för filverktyg). Bash är alltid Git Bash så länge insticksprogrammet är installerat; den här växeln styr bara sökvägsdialekten mellan verktygen.",
|
|
272
|
+
"adopt.label": "Överta sidolistterminal",
|
|
273
|
+
"adopt.hint": "På (standard) skriver Git Bash som terminal-shell i dsh-better-sidebar; av återställer det tidigare värdet och rör aldrig ett manuellt val. Modellens bash-verktyg påverkas inte — det tillhandahålls av pluginet självt.",
|
|
274
|
+
},
|
|
275
|
+
/* locale: th */
|
|
276
|
+
"th": {
|
|
277
|
+
"title": "รูปแบบพาธของ Git Bash",
|
|
278
|
+
"cardDesc": "ใช้รูปแบบพาธ POSIX /c/ แบบเดียวกันกับทุกเครื่องมือ (เปิดไว้เป็นค่าเริ่มต้น)",
|
|
279
|
+
"state.label": "สถานะปัจจุบัน",
|
|
280
|
+
"state.on": "เปิดใช้งาน",
|
|
281
|
+
"state.off": "ปิดใช้งาน",
|
|
282
|
+
"switch.on": "เปิดใช้งาน",
|
|
283
|
+
"switch.off": "ปิดใช้งาน",
|
|
284
|
+
"error": "เขียนไม่สำเร็จ",
|
|
285
|
+
"hint": "เมื่อเปิดใช้งาน: เครื่องมือทั้งหมด (คำสั่ง bash และ workdir รวมถึงอาร์กิวเมนต์พาธของ read/write/edit/read_image/glob/grep) ใช้พาธ POSIX จากรากไดรฟ์ของ MSYS (/c/Users/...) โฮสต์จะแปลฟิลด์พาธของเครื่องมือจัดการไฟล์ให้อัตโนมัติ เมื่อปิดใช้งานจะกลับสู่พฤติกรรมดั้งเดิมของ dsh (เครื่องมือจัดการไฟล์ใช้พาธ Windows) bash เป็น Git Bash เสมอเมื่อติดตั้งปลั๊กอินนี้ สวิตช์นี้ควบคุมเฉพาะรูปแบบพาธระหว่างเครื่องมือเท่านั้น",
|
|
286
|
+
"adopt.label": "รับช่วงเทอร์มินัลแถบข้าง",
|
|
287
|
+
"adopt.hint": "เปิด (ค่าเริ่มต้น) จะเขียน Git Bash เป็น shell ของเทอร์มินัล dsh-better-sidebar; ปิดแล้วคืนค่าเดิมและไม่แตะการตั้งค่าที่เลือกเอง เครื่องมือ bash ของโมเดลไม่กระทบ — ปลั๊กอินจัดหาเอง",
|
|
288
|
+
},
|
|
289
|
+
/* locale: tr */
|
|
290
|
+
"tr": {
|
|
291
|
+
"title": "Git Bash yol lehçesi",
|
|
292
|
+
"cardDesc": "Tüm araçlar için tek /c/ POSIX yol biçimi (varsayılan olarak açık)",
|
|
293
|
+
"state.label": "Geçerli durum",
|
|
294
|
+
"state.on": "Etkin",
|
|
295
|
+
"state.off": "Devre dışı",
|
|
296
|
+
"switch.on": "Etkinleştir",
|
|
297
|
+
"switch.off": "Devre dışı bırak",
|
|
298
|
+
"error": "yazma başarısız",
|
|
299
|
+
"hint": "Etkinleştirildiğinde: tüm araçlar (bash komutları ve workdir ile read/write/edit/read_image/glob/grep yol bağımsız değişkenleri) MSYS sürücü kökünden POSIX yolları (/c/Users/...) kullanır; ana süreç dosya araçlarının yol alanlarını otomatik olarak çevirir. Devre dışı bırakıldığında dsh yerel davranışına döner (dosya araçları için Windows yolları). Eklenti kurulu olduğu sürece bash her zaman Git Bash olarak kalır; bu anahtar yalnızca araçlar arası yol lehçesini yönetir.",
|
|
300
|
+
"adopt.label": "Kenar çubuğu terminalini devral",
|
|
301
|
+
"adopt.hint": "Açık (varsayılan) Git Bashi dsh-better-sidebar terminalinin shelli olarak yazar; kapalı önceki değeri geri getirir ve elle seçilmiş bir ayara asla dokunmaz. Model tarafındaki bash aracı etkilenmez — onu eklentinin kendisi sağlar.",
|
|
302
|
+
},
|
|
303
|
+
/* locale: vi */
|
|
304
|
+
"vi": {
|
|
305
|
+
"title": "Phương ngữ đường dẫn Git Bash",
|
|
306
|
+
"cardDesc": "Một dạng đường dẫn POSIX /c/ thống nhất cho mọi công cụ (mặc định bật)",
|
|
307
|
+
"state.label": "Trạng thái hiện tại",
|
|
308
|
+
"state.on": "Đã bật",
|
|
309
|
+
"state.off": "Đã tắt",
|
|
310
|
+
"switch.on": "Bật",
|
|
311
|
+
"switch.off": "Tắt",
|
|
312
|
+
"error": "ghi thất bại",
|
|
313
|
+
"hint": "Khi bật: mọi công cụ (lệnh bash và workdir, tham số đường dẫn của read/write/edit/read_image/glob/grep) dùng đường dẫn POSIX từ gốc ổ đĩa MSYS (/c/Users/...); máy chủ tự động chuyển đổi trường đường dẫn cho các công cụ tệp. Khi tắt, hành vi gốc của dsh được khôi phục (công cụ tệp dùng đường dẫn Windows). bash luôn là Git Bash khi plugin được cài đặt; công tắc này chỉ điều khiển phương ngữ đường dẫn giữa các công cụ.",
|
|
314
|
+
"adopt.label": "Tiếp nhận terminal thanh bên",
|
|
315
|
+
"adopt.hint": "Bật (mặc định) ghi Git Bash làm shell terminal của dsh-better-sidebar; tắt khôi phục giá trị trước đó và không bao giờ đụng tới lựa chọn thủ công. Công cụ bash phía mô hình không bị ảnh hưởng — chính plugin cung cấp nó.",
|
|
316
|
+
},
|
|
317
|
+
/* locale: zh-hk */
|
|
318
|
+
"zh-hk": {
|
|
319
|
+
"title": "Git Bash 路徑方言",
|
|
320
|
+
"cardDesc": "所有工具統一用 /c/ POSIX 路徑格式(預設開啟)",
|
|
321
|
+
"state.label": "目前狀態",
|
|
322
|
+
"state.on": "已啟用",
|
|
323
|
+
"state.off": "已關閉",
|
|
324
|
+
"switch.on": "啟用",
|
|
325
|
+
"switch.off": "停用",
|
|
326
|
+
"error": "寫入失敗",
|
|
327
|
+
"hint": "啟用後:所有工具(bash 指令同 workdir、read/write/edit/read_image/glob/grep 嘅路徑參數)統一使用 MSYS 磁碟根 POSIX 路徑(/c/Users/...);檔案工具嘅路徑參數由宿主自動翻譯,模型無感。停用後回復 dsh 原生行為(檔案工具用 Windows 路徑)。bash 永遠係 Git Bash,唔受呢個開關影響。",
|
|
328
|
+
"adopt.label": "接管側欄終端",
|
|
329
|
+
"adopt.hint": "開啟(預設)會把 dsh-better-sidebar 的終端 shell 寫成 Git Bash;關閉後還原接管前的值,手動改過的設定永不被碰。模型側的 bash 工具不受影響——由插件本身提供。",
|
|
330
|
+
},
|
|
331
|
+
/* locale: zh-mo */
|
|
332
|
+
"zh-mo": {
|
|
333
|
+
"title": "Git Bash 路徑方言",
|
|
334
|
+
"cardDesc": "所有工具統一用 /c/ POSIX 路徑格式(預設開啟)",
|
|
335
|
+
"state.label": "目前狀態",
|
|
336
|
+
"state.on": "已啟用",
|
|
337
|
+
"state.off": "已關閉",
|
|
338
|
+
"switch.on": "啟用",
|
|
339
|
+
"switch.off": "停用",
|
|
340
|
+
"error": "寫入失敗",
|
|
341
|
+
"hint": "啟用後:所有工具(bash 指令同 workdir、read/write/edit/read_image/glob/grep 嘅路徑參數)統一使用 MSYS 磁碟根 POSIX 路徑(/c/Users/...);檔案工具嘅路徑參數由宿主自動翻譯,模型無感。停用後回復 dsh 原生行為(檔案工具用 Windows 路徑)。bash 永遠係 Git Bash,唔受呢個開關影響。",
|
|
342
|
+
"adopt.label": "接管側欄終端",
|
|
343
|
+
"adopt.hint": "開啟(預設)會把 dsh-better-sidebar 的終端 shell 寫成 Git Bash;關閉後還原接管前的值,手動改過的設定永不被碰。模型側的 bash 工具不受影響——由插件本身提供。",
|
|
344
|
+
},
|
|
345
|
+
/* locale: zh-tw */
|
|
346
|
+
"zh-tw": {
|
|
347
|
+
"title": "Git Bash 路徑方言",
|
|
348
|
+
"cardDesc": "所有工具統一採用 /c/ POSIX 路徑格式(預設開啟)",
|
|
349
|
+
"state.label": "目前狀態",
|
|
350
|
+
"state.on": "已啟用",
|
|
351
|
+
"state.off": "已關閉",
|
|
352
|
+
"switch.on": "啟用",
|
|
353
|
+
"switch.off": "停用",
|
|
354
|
+
"error": "寫入失敗",
|
|
355
|
+
"hint": "啟用後:所有工具(bash 指令與 workdir,以及 read/write/edit/read_image/glob/grep 的路徑參數)統一使用 MSYS 磁碟根 POSIX 路徑(/c/Users/...);檔案工具的路徑參數由宿主自動轉譯,模型無感。停用後恢復 dsh 原生行為(檔案工具使用 Windows 路徑)。bash 一律是 Git Bash,不受此開關影響。",
|
|
356
|
+
"adopt.label": "接管側欄終端機",
|
|
357
|
+
"adopt.hint": "開啟(預設)會把 dsh-better-sidebar 的終端機 shell 寫成 Git Bash;關閉後還原接管前的值,手動改過的設定永不被碰。模型側的 bash 工具不受影響——由插件本身提供。",
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// ── locale resolution (live: read per lookup, cached per tag) ───────────
|
|
362
|
+
|
|
363
|
+
function hasOwnKey(bag, key) {
|
|
364
|
+
return Object.prototype.hasOwnProperty.call(bag, key);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/* Resolve one locale tag against what this plugin ships: the exact tag,
|
|
368
|
+
then the primary subtag, then English. Chinese is special-cased because
|
|
369
|
+
the traditional variants are shipped while a bare zh-Hant-* is not
|
|
370
|
+
spelled out. */
|
|
371
|
+
function dictionaryFor(active) {
|
|
372
|
+
var raw = active === undefined || active === null || active === "" ? "en" : String(active);
|
|
373
|
+
var tag = raw.toLowerCase().replace(/_/g, "-");
|
|
374
|
+
var primary = tag.split("-")[0];
|
|
375
|
+
if (primary === "zh") {
|
|
376
|
+
if (hasOwnKey(LOCALES, tag)) return LOCALES[tag];
|
|
377
|
+
if (tag.indexOf("hant") >= 0 || tag === "zh-hk" || tag === "zh-mo" || tag === "zh-tw") {
|
|
378
|
+
return hasOwnKey(LOCALES, "zh-hk") ? LOCALES["zh-hk"] : zh;
|
|
379
|
+
}
|
|
380
|
+
return zh;
|
|
381
|
+
}
|
|
382
|
+
if (hasOwnKey(LOCALES, primary)) return LOCALES[primary];
|
|
383
|
+
return en;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/* The active locale tag, read fresh every time: DSH's language preference
|
|
387
|
+
switches live, so a value captured once at activation would keep answering
|
|
388
|
+
in the language that happened to be active when the card loaded. The
|
|
389
|
+
host-backed preference wins; the browser is the fallback. */
|
|
390
|
+
function activeLocaleOf(ctx) {
|
|
391
|
+
var active = "";
|
|
392
|
+
try {
|
|
393
|
+
var locale = ctx.get("locale");
|
|
394
|
+
if (locale !== undefined && typeof locale.getSnapshot === "function") {
|
|
395
|
+
var snapshot = locale.getSnapshot();
|
|
396
|
+
if (snapshot !== null && typeof snapshot === "object" && typeof snapshot.active === "string") active = snapshot.active;
|
|
397
|
+
}
|
|
398
|
+
} catch (error) { /* fall through to the browser */ }
|
|
399
|
+
if (active === "" && typeof navigator === "object" && navigator !== null && typeof navigator.language === "string") active = navigator.language;
|
|
400
|
+
return active;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* A live lookup: the dictionary is picked per call and cached under the tag
|
|
404
|
+
it was picked for, so a language switch costs one string compare per
|
|
405
|
+
string. Falling back to EN — kept key-complete on purpose — means an
|
|
406
|
+
unsupported language shows English, never a raw key. */
|
|
407
|
+
function translatorOf(ctx) {
|
|
408
|
+
var cachedTag = null;
|
|
409
|
+
var cachedDict = null;
|
|
410
|
+
return function (key) {
|
|
411
|
+
var tag = activeLocaleOf(ctx);
|
|
412
|
+
if (tag !== cachedTag) { cachedTag = tag; cachedDict = dictionaryFor(tag); }
|
|
413
|
+
if (hasOwnKey(cachedDict, key)) return cachedDict[key];
|
|
414
|
+
return hasOwnKey(en, key) ? en[key] : key;
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
71
418
|
// ── styles (gb- prefixed; tokens mirror PluginCard.module.css) ─────────
|
|
72
419
|
|
|
73
420
|
var STYLE_ID = "dsh-gitbash-shell-style";
|
|
@@ -84,6 +431,8 @@ window.__ModuleLoader__.load({
|
|
|
84
431
|
".gb-chevron{flex:none;color:var(--dsw-alias-label-tertiary);transition:transform .16s}",
|
|
85
432
|
".gb-chevron.gb-chevronOpen{transform:rotate(180deg)}",
|
|
86
433
|
".gb-body{display:flex;flex-direction:column;gap:12px;padding:4px 16px 16px;max-width:640px}",
|
|
434
|
+
".gb-page{max-width:640px}",
|
|
435
|
+
".gb-pageBody{display:flex;flex-direction:column;gap:12px;padding:0 0 8px}",
|
|
87
436
|
".gb-row{display:flex;align-items:baseline;gap:8px;font-size:13px;line-height:1.5;color:var(--dsw-alias-label-secondary)}",
|
|
88
437
|
".gb-rowLabel{flex:none;color:var(--dsw-alias-label-tertiary)}",
|
|
89
438
|
".gb-rowValue{min-width:0;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary)}",
|
|
@@ -140,13 +489,40 @@ window.__ModuleLoader__.load({
|
|
|
140
489
|
return this.props.children;
|
|
141
490
|
};
|
|
142
491
|
|
|
492
|
+
// ── live locale (repaint the card on a language switch) ─────────────────
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Wraps the card so a language switch repaints it instead of waiting for a
|
|
496
|
+
* page load. DSH's own components re-render on the locale snapshot, but this
|
|
497
|
+
* card belongs to a plugin: it subscribes for itself, and it hands the card
|
|
498
|
+
* THIS plugin's live lookup (translatorOf) — whose resolution covers the
|
|
499
|
+
* third languages the DSH catalog does not carry. The card stays inside the
|
|
500
|
+
* same quiet boundary as before.
|
|
501
|
+
*/
|
|
502
|
+
function LocaleLive(props) {
|
|
503
|
+
var tickState = useState(0);
|
|
504
|
+
var tick = tickState[0];
|
|
505
|
+
var setTick = tickState[1];
|
|
506
|
+
void tick;
|
|
507
|
+
|
|
508
|
+
useEffect(function () {
|
|
509
|
+
var locale = props.ctx && typeof props.ctx.get === "function" ? props.ctx.get("locale") : undefined;
|
|
510
|
+
if (locale === undefined || typeof locale.subscribe !== "function") return undefined;
|
|
511
|
+
var unsubscribe = locale.subscribe(function () { setTick(function (value) { return value + 1; }); });
|
|
512
|
+
return typeof unsubscribe === "function" ? unsubscribe : undefined;
|
|
513
|
+
}, []);
|
|
514
|
+
|
|
515
|
+
return E(QuietBoundary, null, E(GitBashCard, Object.assign({}, props.cardProps, { t: props.t })));
|
|
516
|
+
}
|
|
517
|
+
|
|
143
518
|
// ── settings card (module-level component) ───────────────────────────────
|
|
144
519
|
|
|
145
520
|
/**
|
|
146
|
-
* The Settings → Plugins card. t arrives
|
|
147
|
-
* locale
|
|
148
|
-
* Snapshots are read per render; each
|
|
149
|
-
* card re-reads without an external-store
|
|
521
|
+
* The Settings → Plugins card. t arrives from LocaleLive (the plugin's own
|
|
522
|
+
* live lookup, keyed on the active locale at call time); scope arrives as a
|
|
523
|
+
* PLAIN prop from the inject factory. Snapshots are read per render; each
|
|
524
|
+
* write bumps a local tick so the card re-reads without an external-store
|
|
525
|
+
* hook adapter.
|
|
150
526
|
*/
|
|
151
527
|
function GitBashCard(props) {
|
|
152
528
|
var t = typeof props.t === "function" ? props.t : function (key) { return key; };
|
|
@@ -175,10 +551,11 @@ window.__ModuleLoader__.load({
|
|
|
175
551
|
|
|
176
552
|
var value = snap.value || {};
|
|
177
553
|
var enabled = value.posixPaths === true;
|
|
554
|
+
var adopt = value.adoptSidebar !== false;
|
|
178
555
|
|
|
179
|
-
function
|
|
556
|
+
function writeField(key, next) {
|
|
180
557
|
setError("");
|
|
181
|
-
scope.set(
|
|
558
|
+
scope.set(key, next)
|
|
182
559
|
.then(function () { bumpTick(function (n) { return n + 1; }); })
|
|
183
560
|
.catch(function (err) {
|
|
184
561
|
bumpTick(function (n) { return n + 1; });
|
|
@@ -188,6 +565,51 @@ window.__ModuleLoader__.load({
|
|
|
188
565
|
|
|
189
566
|
var Chevron = icon("IconChevronDownOutline14");
|
|
190
567
|
|
|
568
|
+
// dsh 0.1.6-alpha.2: the Plugins page renders this card through the
|
|
569
|
+
// `plugins.bundle.config` slot with view="page" — the page draws the
|
|
570
|
+
// title itself, so the collapsible shell is only for the legacy seat.
|
|
571
|
+
var pageView = props.view === "page";
|
|
572
|
+
|
|
573
|
+
var bodyContent = E("div", { className: pageView ? "gb-pageBody" : "gb-body" },
|
|
574
|
+
E("div", { className: "gb-row" },
|
|
575
|
+
E("span", { className: "gb-rowLabel" }, t("state.label") + ":"),
|
|
576
|
+
E("span", { className: "gb-rowValue" }, enabled ? t("state.on") : t("state.off")),
|
|
577
|
+
),
|
|
578
|
+
E("div", { className: "gb-seg" },
|
|
579
|
+
E("button", {
|
|
580
|
+
type: "button",
|
|
581
|
+
className: "gb-segBtn" + (enabled ? " gb-segActive" : ""),
|
|
582
|
+
onClick: function () { if (!enabled) writeField("posixPaths", true); },
|
|
583
|
+
}, t("switch.on")),
|
|
584
|
+
E("button", {
|
|
585
|
+
type: "button",
|
|
586
|
+
className: "gb-segBtn" + (!enabled ? " gb-segActive" : ""),
|
|
587
|
+
onClick: function () { if (enabled) writeField("posixPaths", false); },
|
|
588
|
+
}, t("switch.off")),
|
|
589
|
+
),
|
|
590
|
+
E("p", { className: "gb-hint" }, t("hint")),
|
|
591
|
+
E("div", { className: "gb-row" },
|
|
592
|
+
E("span", { className: "gb-rowLabel" }, t("adopt.label") + ":"),
|
|
593
|
+
E("span", { className: "gb-rowValue" }, adopt ? t("state.on") : t("state.off")),
|
|
594
|
+
),
|
|
595
|
+
E("div", { className: "gb-seg" },
|
|
596
|
+
E("button", {
|
|
597
|
+
type: "button",
|
|
598
|
+
className: "gb-segBtn" + (adopt ? " gb-segActive" : ""),
|
|
599
|
+
onClick: function () { if (!adopt) writeField("adoptSidebar", true); },
|
|
600
|
+
}, t("switch.on")),
|
|
601
|
+
E("button", {
|
|
602
|
+
type: "button",
|
|
603
|
+
className: "gb-segBtn" + (!adopt ? " gb-segActive" : ""),
|
|
604
|
+
onClick: function () { if (adopt) writeField("adoptSidebar", false); },
|
|
605
|
+
}, t("switch.off")),
|
|
606
|
+
),
|
|
607
|
+
E("p", { className: "gb-hint" }, t("adopt.hint")),
|
|
608
|
+
error ? E("p", { className: "gb-error" }, error) : null,
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
if (pageView) return E("div", { className: "gb-page" }, bodyContent);
|
|
612
|
+
|
|
191
613
|
return E("li", { className: "gb-card" + (open ? " gb-open" : "") },
|
|
192
614
|
E("button", {
|
|
193
615
|
type: "button",
|
|
@@ -203,26 +625,7 @@ window.__ModuleLoader__.load({
|
|
|
203
625
|
? E(Chevron, { className: "gb-chevron" + (open ? " gb-chevronOpen" : "") })
|
|
204
626
|
: E("span", { className: "gb-chevron" + (open ? " gb-chevronOpen" : "") }, "▾"),
|
|
205
627
|
),
|
|
206
|
-
open ?
|
|
207
|
-
E("div", { className: "gb-row" },
|
|
208
|
-
E("span", { className: "gb-rowLabel" }, t("state.label") + ":"),
|
|
209
|
-
E("span", { className: "gb-rowValue" }, enabled ? t("state.on") : t("state.off")),
|
|
210
|
-
),
|
|
211
|
-
E("div", { className: "gb-seg" },
|
|
212
|
-
E("button", {
|
|
213
|
-
type: "button",
|
|
214
|
-
className: "gb-segBtn" + (enabled ? " gb-segActive" : ""),
|
|
215
|
-
onClick: function () { if (!enabled) write(true); },
|
|
216
|
-
}, t("switch.on")),
|
|
217
|
-
E("button", {
|
|
218
|
-
type: "button",
|
|
219
|
-
className: "gb-segBtn" + (!enabled ? " gb-segActive" : ""),
|
|
220
|
-
onClick: function () { if (enabled) write(false); },
|
|
221
|
-
}, t("switch.off")),
|
|
222
|
-
),
|
|
223
|
-
error ? E("p", { className: "gb-error" }, error) : null,
|
|
224
|
-
E("p", { className: "gb-hint" }, t("hint")),
|
|
225
|
-
) : null,
|
|
628
|
+
open ? bodyContent : null,
|
|
226
629
|
);
|
|
227
630
|
}
|
|
228
631
|
|
|
@@ -235,11 +638,17 @@ window.__ModuleLoader__.load({
|
|
|
235
638
|
|
|
236
639
|
exports.apply = function (ctx) {
|
|
237
640
|
var scope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
|
|
641
|
+
/* The card's only copy entry point: a live lookup, never a captured
|
|
642
|
+
dictionary — the language preference switches without a reload. */
|
|
643
|
+
var t = translatorOf(ctx);
|
|
238
644
|
|
|
239
645
|
ctx.effect(function () {
|
|
240
646
|
var disposers = [ensureStyles()];
|
|
241
647
|
try {
|
|
242
|
-
|
|
648
|
+
/* Every shipped dictionary rides the DSH locale registry, so host-side
|
|
649
|
+
consumers read the same copy the card does; a missing service simply
|
|
650
|
+
means the card is the only reader. */
|
|
651
|
+
var disposeDict = ctx.locale.register(NS, Object.assign({ zh: zh, en: en }, LOCALES));
|
|
243
652
|
if (typeof disposeDict === "function") disposers.push(disposeDict);
|
|
244
653
|
} catch (error) {
|
|
245
654
|
console.warn(TAG + " dictionary registration failed:", error && error.message ? error.message : error);
|
|
@@ -261,17 +670,39 @@ window.__ModuleLoader__.load({
|
|
|
261
670
|
console.warn(TAG + " slots service unavailable; settings card idle");
|
|
262
671
|
return;
|
|
263
672
|
}
|
|
673
|
+
var injected = function () {
|
|
674
|
+
// The inject factory's returned members become the component's
|
|
675
|
+
// props: the bound settings scope rides here as a PLAIN member
|
|
676
|
+
// (top-level options fields do NOT reach the component).
|
|
677
|
+
return { scope: scope };
|
|
678
|
+
};
|
|
679
|
+
// Legacy seat (dsh <= 0.1.6-alpha.1): Settings → Plugins card.
|
|
264
680
|
slots.inject("settings.plugin.item", function () {
|
|
265
681
|
return slots.register({
|
|
266
682
|
name: "settings.plugin.item",
|
|
267
683
|
key: SETTINGS_NAMESPACE,
|
|
268
684
|
locale: NS,
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
return E(
|
|
685
|
+
inject: injected,
|
|
686
|
+
}, function CardWithLocale(props) {
|
|
687
|
+
/* The registration's locale field also hands out the framework's own
|
|
688
|
+
t seat; the plugin's lookup wins (21 locale tags against the catalog's
|
|
689
|
+
zh/en), passed last so no prop merge order can override it. */
|
|
690
|
+
return E(LocaleLive, { ctx: ctx, t: t, cardProps: props });
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
// dsh 0.1.6-alpha.2+: the Plugins page's bundle configuration seat,
|
|
694
|
+
// keyed by the PACKAGE name. Each inject waits for its own slot
|
|
695
|
+
// declaration, so exactly one seat is live on any host version.
|
|
696
|
+
slots.inject("plugins.bundle.config", function () {
|
|
697
|
+
return slots.register({
|
|
698
|
+
name: "plugins.bundle.config",
|
|
699
|
+
key: "dsh-gitbash-shell",
|
|
700
|
+
locale: NS,
|
|
701
|
+
inject: injected,
|
|
702
|
+
}, function BundleConfigWithBoundary(props) {
|
|
703
|
+
/* Same LocaleLive wrap as the legacy seat: the plugin's 21-tag
|
|
704
|
+
dictionary wins over the catalog's zh/en t seat. */
|
|
705
|
+
return E(LocaleLive, { ctx: ctx, t: t, cardProps: props });
|
|
275
706
|
});
|
|
276
707
|
});
|
|
277
708
|
} catch (error) {
|
package/src/index.js
CHANGED
|
@@ -427,7 +427,7 @@ function pickComposition(base, persona, available) {
|
|
|
427
427
|
}
|
|
428
428
|
|
|
429
429
|
/** Startup decision for an existing unmodified tree: 'refresh' or 'idle'. */
|
|
430
|
-
function syncDecision({ state, marker, version, sourceHashes, base = 'code', persona = 'text', present = false, rows = '' }) {
|
|
430
|
+
function syncDecision({ state, marker, version, sourceHashes, base = 'code', persona = 'text', present = false, pluginManager = false, rows = '' }) {
|
|
431
431
|
if (state !== 'unmodified' || !marker) return 'refresh'
|
|
432
432
|
if (marker.version !== version) return 'refresh'
|
|
433
433
|
if (marker.base !== base) return 'refresh'
|
|
@@ -445,6 +445,10 @@ function syncDecision({ state, marker, version, sourceHashes, base = 'code', per
|
|
|
445
445
|
// host resolves it — and a host upgrade past that point must re-materialize
|
|
446
446
|
// to gain it (same marker-dimension pattern as persona).
|
|
447
447
|
if ((marker.present ?? false) !== present) return 'refresh'
|
|
448
|
+
// Host-capability flip: @deepseek-ai/dsh-plugin-manager/tools first shipped
|
|
449
|
+
// with dsh 0.1.6-alpha.2 — same mount-rejection stakes and the same marker
|
|
450
|
+
// dimension pattern as present above.
|
|
451
|
+
if ((marker.pluginManager ?? false) !== pluginManager) return 'refresh'
|
|
448
452
|
const recorded = {}
|
|
449
453
|
for (const k of Object.keys(marker.files)) if (k.startsWith('skills/')) recorded[k] = marker.files[k]
|
|
450
454
|
if (sourceHashes === null) return Object.keys(recorded).length === 0 ? 'idle' : 'refresh'
|
|
@@ -497,8 +501,48 @@ async function hostHasToolPresent() {
|
|
|
497
501
|
return toolPresentCache
|
|
498
502
|
}
|
|
499
503
|
|
|
504
|
+
/*
|
|
505
|
+
* Conditional plugin-manager-row injection (v0.15.0, dsh 0.1.6-alpha.2 sync).
|
|
506
|
+
* Official ptc/standard/cordis gained `- id: tool-plugin-manager / name:
|
|
507
|
+
* '@deepseek-ai/dsh-plugin-manager/tools'` (persistent plugin management;
|
|
508
|
+
* the official ptc preset carries it DISABLED, Creation keeps it on). The
|
|
509
|
+
* package only exists from 0.1.6-alpha.2 on, so the row is injected as plain
|
|
510
|
+
* text behind a host probe — never committed into the assets — anchored
|
|
511
|
+
* after the present row when there is one, else at the tail, mirroring the
|
|
512
|
+
* official order (tool-presentation → present → tool-plugin-manager).
|
|
513
|
+
* Per-variant shape mirrors each variant's official base: code-gitbash (ptc
|
|
514
|
+
* base) DISABLED, standard/cordis-gitbash ENABLED, minimal untouched
|
|
515
|
+
* (official minimal never gained the row), code-era files frozen history.
|
|
516
|
+
*/
|
|
517
|
+
const PLUGIN_MANAGER_ROW_ON = "- id: tool-plugin-manager\n name: '@deepseek-ai/dsh-plugin-manager/tools'\n"
|
|
518
|
+
const PLUGIN_MANAGER_ROW_OFF = "- id: tool-plugin-manager\n name: '@deepseek-ai/dsh-plugin-manager/tools'\n disabled: true\n"
|
|
519
|
+
const PRESENT_ROW_FULL = "\n- id: present\n name: '@deepseek-ai/dsh-tool-present'\n"
|
|
520
|
+
|
|
521
|
+
function injectPluginManagerRow(text, { enabled }) {
|
|
522
|
+
if (text.includes("'@deepseek-ai/dsh-plugin-manager/tools'")) return text
|
|
523
|
+
const body = enabled ? PLUGIN_MANAGER_ROW_ON : PLUGIN_MANAGER_ROW_OFF
|
|
524
|
+
const at = text.indexOf(PRESENT_ROW_FULL)
|
|
525
|
+
if (at !== -1) return text.slice(0, at + PRESENT_ROW_FULL.length) + body + text.slice(at + PRESENT_ROW_FULL.length)
|
|
526
|
+
return text.endsWith('\n') ? text + body : text + '\n' + body
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
let pluginManagerToolsCache
|
|
531
|
+
/** Probe whether THIS host can resolve the plugin-manager tools package (cached per boot). */
|
|
532
|
+
async function hostHasPluginManagerTools() {
|
|
533
|
+
if (pluginManagerToolsCache !== undefined) return pluginManagerToolsCache
|
|
534
|
+
try {
|
|
535
|
+
const { createRequire } = await import('node:module')
|
|
536
|
+
createRequire(import.meta.url).resolve('@deepseek-ai/dsh-plugin-manager/tools')
|
|
537
|
+
pluginManagerToolsCache = true
|
|
538
|
+
} catch {
|
|
539
|
+
pluginManagerToolsCache = false
|
|
540
|
+
}
|
|
541
|
+
return pluginManagerToolsCache
|
|
542
|
+
}
|
|
543
|
+
|
|
500
544
|
/** Write one preset directory from scratch. Returns 'ok' or 'no-skills-source'. */
|
|
501
|
-
function materialize({ target, presetId, skillsSource, version, base = 'code', persona = 'text', present = false, rows }) {
|
|
545
|
+
function materialize({ target, presetId, skillsSource, version, base = 'code', persona = 'text', present = false, pluginManager = false, rows }) {
|
|
502
546
|
rmSync(target, { recursive: true, force: true })
|
|
503
547
|
mkdirSync(target, { recursive: true })
|
|
504
548
|
|
|
@@ -506,6 +550,12 @@ function materialize({ target, presetId, skillsSource, version, base = 'code', p
|
|
|
506
550
|
const compositionFile = pickComposition(base, persona, available)
|
|
507
551
|
let composition = readFileSync(join(pkgDir, 'assets', presetId, compositionFile), 'utf8')
|
|
508
552
|
if (present && compositionFile.includes('.ptc.')) composition = injectPresentRow(composition)
|
|
553
|
+
// v0.15.0: ptc-era files only; the ptc-based variant mirrors the official
|
|
554
|
+
// ptc DISABLED form, standard/cordis mirror their ENABLED bases, minimal is
|
|
555
|
+
// untouched (official minimal never gained the row).
|
|
556
|
+
if (pluginManager && compositionFile.includes('.ptc.') && presetId !== 'minimal-gitbash') {
|
|
557
|
+
composition = injectPluginManagerRow(composition, { enabled: presetId !== 'code-gitbash' })
|
|
558
|
+
}
|
|
509
559
|
// Row-form alignment (v0.14.0): the committed assets pin one spelling of the
|
|
510
560
|
// workflow-engine row, but a host renames it out from under them (dsh
|
|
511
561
|
// 0.1.6-alpha.1) and a row whose module fails to import rejects the whole
|
|
@@ -531,7 +581,7 @@ function materialize({ target, presetId, skillsSource, version, base = 'code', p
|
|
|
531
581
|
}
|
|
532
582
|
}
|
|
533
583
|
|
|
534
|
-
const marker = { managedBy: MANAGED_BY, version, presetId, base, persona, present, rows: rowFingerprint(rows, presetId), files: hashTree(target) }
|
|
584
|
+
const marker = { managedBy: MANAGED_BY, version, presetId, base, persona, present, pluginManager, rows: rowFingerprint(rows, presetId), files: hashTree(target) }
|
|
535
585
|
writeFileSync(join(target, MARKER_FILE), JSON.stringify(marker, null, 2) + '\n')
|
|
536
586
|
return skills
|
|
537
587
|
}
|
|
@@ -633,6 +683,20 @@ export function readPosixPaths(ctxLike) {
|
|
|
633
683
|
}
|
|
634
684
|
}
|
|
635
685
|
|
|
686
|
+
/**
|
|
687
|
+
* Read the adoptSidebar switch (v0.15.0, default ON). Unlike posixPaths the
|
|
688
|
+
* default is on, so only an explicit false disables the takeover.
|
|
689
|
+
*/
|
|
690
|
+
export function readAdoptSidebar(ctxLike) {
|
|
691
|
+
try {
|
|
692
|
+
const settings = ctxLike && typeof ctxLike.get === 'function' ? ctxLike.get('settings') : undefined
|
|
693
|
+
const value = settings && typeof settings.get === 'function' ? settings.get(SETTINGS_NAMESPACE) : undefined
|
|
694
|
+
return !(value && value.adoptSidebar === false)
|
|
695
|
+
} catch {
|
|
696
|
+
return true
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
636
700
|
// Windows absolute path -> MSYS drive-root form, for rewriting the OFFICIAL
|
|
637
701
|
// prompt text in place (v0.10.0). Two patterns keep quoted spaced paths
|
|
638
702
|
// ("C:\Program Files\Git") whole while bare paths stop at whitespace or a
|
|
@@ -772,72 +836,119 @@ const SIDEBAR_NS = 'dsh-better-sidebar'
|
|
|
772
836
|
const SIDEBAR_TRIES = 12
|
|
773
837
|
const SIDEBAR_RETRY_MS = 1500
|
|
774
838
|
|
|
839
|
+
// Owner scope of the gitbash-shell namespace once registered (shared with
|
|
840
|
+
// the register callback so a late registration can reconcile + watch).
|
|
841
|
+
let sidebarScope = undefined
|
|
842
|
+
|
|
843
|
+
// Reconciler installed by adoptSidebarShell; a no-op until then.
|
|
844
|
+
let reconcileSidebar = () => {}
|
|
845
|
+
|
|
775
846
|
/**
|
|
776
|
-
*
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
847
|
+
* Reconcile the better-sidebar `terminalShell` takeover with the adoptSidebar
|
|
848
|
+
* setting (v0.15.0, default ON). ON writes our bashPath (remembering what was
|
|
849
|
+
* there before); OFF restores that previous value — but only while the current
|
|
850
|
+
* value is still ours, so a user's manual choice is never clobbered. The
|
|
851
|
+
* polling keeps the original ready-wait behavior: at boot the settings
|
|
852
|
+
* service may not be provided yet when this row's apply runs. Never throws.
|
|
781
853
|
*/
|
|
782
854
|
function adoptSidebarShell(ctx, bashPath) {
|
|
855
|
+
let adopted = false
|
|
856
|
+
let previous = ''
|
|
783
857
|
let tried = 0
|
|
784
858
|
let timer = null
|
|
785
859
|
ctx.effect(() => () => { if (timer) clearTimeout(timer) }, 'dsh-gitbash-shell: sidebar adoption polling')
|
|
786
|
-
|
|
787
|
-
|
|
860
|
+
|
|
861
|
+
const readShell = () => {
|
|
788
862
|
const settings = ctx.get('settings')
|
|
789
|
-
|
|
790
|
-
if (!ready) {
|
|
791
|
-
if (tried < SIDEBAR_TRIES) {
|
|
792
|
-
timer = setTimeout(run, SIDEBAR_RETRY_MS)
|
|
793
|
-
return
|
|
794
|
-
}
|
|
795
|
-
console.log(`${TAG} better-sidebar shell adoption skipped: settings service unavailable after ${tried} tries`)
|
|
796
|
-
return
|
|
797
|
-
}
|
|
798
|
-
let current
|
|
863
|
+
if (!settings || typeof settings.get !== 'function' || typeof settings.update !== 'function') return null
|
|
799
864
|
try {
|
|
800
|
-
|
|
865
|
+
const value = settings.get(SIDEBAR_NS)
|
|
866
|
+
return value && typeof value === 'object' && typeof value.terminalShell === 'string' ? value.terminalShell : ''
|
|
801
867
|
} catch {
|
|
802
|
-
|
|
868
|
+
return null // namespace not registered yet / sidebar absent
|
|
803
869
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
reconcileSidebar = (desired) => {
|
|
873
|
+
const current = readShell()
|
|
874
|
+
if (current === null) return false
|
|
875
|
+
const settings = ctx.get('settings')
|
|
876
|
+
if (desired && current !== bashPath) {
|
|
877
|
+
const was = current
|
|
878
|
+
settings.update(SIDEBAR_NS, { terminalShell: bashPath })
|
|
879
|
+
.then(() => {
|
|
880
|
+
previous = was
|
|
881
|
+
adopted = true
|
|
882
|
+
console.log(
|
|
883
|
+
`${TAG} dsh-better-sidebar terminal shell -> Git Bash (${bashPath})` +
|
|
884
|
+
(was ? ` (took over from '${was}')` : ''),
|
|
885
|
+
)
|
|
886
|
+
})
|
|
887
|
+
.catch((error) => {
|
|
888
|
+
console.log(`${TAG} better-sidebar shell adoption unavailable: ${error?.message ?? error}`)
|
|
889
|
+
})
|
|
890
|
+
return true
|
|
891
|
+
}
|
|
892
|
+
if (desired && current === bashPath) {
|
|
893
|
+
adopted = true
|
|
894
|
+
return true
|
|
895
|
+
}
|
|
896
|
+
if (!desired && adopted && current === bashPath) {
|
|
897
|
+
settings.update(SIDEBAR_NS, { terminalShell: previous })
|
|
898
|
+
.then(() => {
|
|
899
|
+
adopted = false
|
|
900
|
+
console.log(`${TAG} dsh-better-sidebar terminal shell restored ('${previous || 'sidebar default'}') — adoptSidebar off`)
|
|
901
|
+
})
|
|
902
|
+
.catch(() => {})
|
|
903
|
+
return true
|
|
904
|
+
}
|
|
905
|
+
return true
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
const run = () => {
|
|
909
|
+
tried += 1
|
|
910
|
+
const ok = reconcileSidebar(readAdoptSidebar(ctx))
|
|
911
|
+
if (ok) {
|
|
912
|
+
// The namespace scope may register after the settings service; hook
|
|
913
|
+
// the live watch once it exists (idempotent via the effect disposer).
|
|
914
|
+
if (sidebarScope && typeof sidebarScope.watch === 'function' && !run.watched) {
|
|
915
|
+
run.watched = true
|
|
916
|
+
try {
|
|
917
|
+
const off = sidebarScope.watch((next) => { reconcileSidebar(next && next.adoptSidebar !== false) })
|
|
918
|
+
ctx.effect(() => off, 'dsh-gitbash-shell: adoptSidebar watch (polling path)')
|
|
919
|
+
} catch { /* best effort */ }
|
|
812
920
|
}
|
|
813
|
-
console.log(`${TAG} better-sidebar shell adoption unavailable: ${error?.message ?? error}`)
|
|
814
921
|
return
|
|
815
922
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
const s = ctx.get('settings')
|
|
822
|
-
if (!s || typeof s.update !== 'function') return
|
|
823
|
-
let now
|
|
824
|
-
try {
|
|
825
|
-
now = s.get(SIDEBAR_NS)
|
|
826
|
-
} catch {
|
|
827
|
-
return
|
|
828
|
-
}
|
|
829
|
-
if (String(now?.terminalShell ?? '') === bashPath) {
|
|
830
|
-
s.update(SIDEBAR_NS, { terminalShell: previous }).catch(() => {})
|
|
831
|
-
}
|
|
832
|
-
},
|
|
833
|
-
'dsh-gitbash-shell: sidebar shell revert',
|
|
834
|
-
)
|
|
835
|
-
console.log(
|
|
836
|
-
`${TAG} dsh-better-sidebar terminal shell -> Git Bash (${bashPath})` +
|
|
837
|
-
(previous ? ` (took over from '${previous}')` : ''),
|
|
838
|
-
)
|
|
923
|
+
if (tried < SIDEBAR_TRIES) {
|
|
924
|
+
timer = setTimeout(run, SIDEBAR_RETRY_MS)
|
|
925
|
+
return
|
|
926
|
+
}
|
|
927
|
+
console.log(`${TAG} better-sidebar shell adoption skipped: settings service unavailable after ${tried} tries`)
|
|
839
928
|
}
|
|
929
|
+
run.watched = false
|
|
840
930
|
void run()
|
|
931
|
+
|
|
932
|
+
// Dispose: while we still hold the value, restore what was there before.
|
|
933
|
+
let reverted = false
|
|
934
|
+
ctx.effect(
|
|
935
|
+
() => () => {
|
|
936
|
+
if (reverted || !adopted) return
|
|
937
|
+
reverted = true
|
|
938
|
+
const s = ctx.get('settings')
|
|
939
|
+
if (!s || typeof s.update !== 'function') return
|
|
940
|
+
let now
|
|
941
|
+
try {
|
|
942
|
+
now = s.get(SIDEBAR_NS)
|
|
943
|
+
} catch {
|
|
944
|
+
return
|
|
945
|
+
}
|
|
946
|
+
if (String(now?.terminalShell ?? '') === bashPath) {
|
|
947
|
+
s.update(SIDEBAR_NS, { terminalShell: previous }).catch(() => {})
|
|
948
|
+
}
|
|
949
|
+
},
|
|
950
|
+
'dsh-gitbash-shell: sidebar shell revert',
|
|
951
|
+
)
|
|
841
952
|
}
|
|
842
953
|
|
|
843
954
|
// ── plugin ──────────────────────────────────────────────────────────────────
|
|
@@ -923,7 +1034,7 @@ export async function apply(ctx, config = {}) {
|
|
|
923
1034
|
const disposeGitBash = ctx.provide('gitBash', gitBashCapability)
|
|
924
1035
|
ctx.effect(() => disposeGitBash, 'dsh-gitbash-shell: gitBash capability')
|
|
925
1036
|
|
|
926
|
-
// ── settings namespace: the posixPaths switch (default
|
|
1037
|
+
// ── settings namespace: the posixPaths switch (default ON, v0.10.0) ──────
|
|
927
1038
|
// Served on the host so the Plugins tab pairs it with the browser card
|
|
928
1039
|
// (the tab dispatches Host-served namespaces ∩ registered cards). Dynamic
|
|
929
1040
|
// imports keep the zero-dependency smoke path importable; the schema MUST
|
|
@@ -940,10 +1051,24 @@ export async function apply(ctx, config = {}) {
|
|
|
940
1051
|
const ns = typeof ds.settingsNamespace === 'function'
|
|
941
1052
|
? ds.settingsNamespace(SETTINGS_NAMESPACE)
|
|
942
1053
|
: SETTINGS_NAMESPACE
|
|
943
|
-
settings.register(ns, Schema.object({
|
|
1054
|
+
const scope = settings.register(ns, Schema.object({
|
|
944
1055
|
posixPaths: Schema.boolean().default(true),
|
|
1056
|
+
adoptSidebar: Schema.boolean().default(true),
|
|
945
1057
|
}))
|
|
946
|
-
|
|
1058
|
+
sidebarScope = scope
|
|
1059
|
+
console.log(`${TAG} settings namespace registered: ${SETTINGS_NAMESPACE} (posixPaths default on, adoptSidebar default on)`)
|
|
1060
|
+
// A late register (settings service up after the adoption polling
|
|
1061
|
+
// finished) still reconciles once, and the live watch flips the
|
|
1062
|
+
// takeover when the user toggles the card switch.
|
|
1063
|
+
try {
|
|
1064
|
+
if (typeof scope?.watch === 'function') {
|
|
1065
|
+
const off = scope.watch((next) => { reconcileSidebar(next && next.adoptSidebar !== false) })
|
|
1066
|
+
ctx.effect(() => off, 'dsh-gitbash-shell: adoptSidebar watch')
|
|
1067
|
+
}
|
|
1068
|
+
reconcileSidebar(readAdoptSidebar(ctx))
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
console.log(`${TAG} adoptSidebar watch wiring failed: ${error?.message ?? error}`)
|
|
1071
|
+
}
|
|
947
1072
|
})
|
|
948
1073
|
.catch((error) => {
|
|
949
1074
|
console.log(`${TAG} settings namespace registration FAILED: ${error && error.stack || String(error)}`)
|
|
@@ -1145,6 +1270,11 @@ export async function apply(ctx, config = {}) {
|
|
|
1145
1270
|
// resolving from this plugin's own tree (covers hosts where the roster
|
|
1146
1271
|
// probe is unavailable).
|
|
1147
1272
|
const present = (await detectPresentSupport(ctx.agentPresets)) || (await hostHasToolPresent())
|
|
1273
|
+
// v0.15.0 (dsh 0.1.6-alpha.2): official ptc/standard/cordis gained the
|
|
1274
|
+
// tool-plugin-manager row; inject behind the same host-package probe as
|
|
1275
|
+
// present (resolve-only is sufficient — the package cannot exist on an
|
|
1276
|
+
// older host, so a roster text probe adds nothing).
|
|
1277
|
+
const pluginManager = await hostHasPluginManagerTools()
|
|
1148
1278
|
// Row spellings of the built-in presets these variants mirror: the
|
|
1149
1279
|
// workflow-engine row was renamed and its old package deleted in dsh
|
|
1150
1280
|
// 0.1.6-alpha.1, so the materializer copies whatever the host itself ships.
|
|
@@ -1179,12 +1309,12 @@ export async function apply(ctx, config = {}) {
|
|
|
1179
1309
|
const sourceHashes = presetId === 'cordis-gitbash' ? skillsHashes(skillsSource) : null
|
|
1180
1310
|
const marker = readMarker(target)
|
|
1181
1311
|
const markerRows = rowFingerprint(rows, presetId)
|
|
1182
|
-
if (state === 'unmodified' && syncDecision({ state, marker, version, sourceHashes, base, persona, present, rows: markerRows }) === 'idle') {
|
|
1312
|
+
if (state === 'unmodified' && syncDecision({ state, marker, version, sourceHashes, base, persona, present, pluginManager, rows: markerRows }) === 'idle') {
|
|
1183
1313
|
ctx.logger?.('gitbash-shell')?.debug?.( `preset '${presetId}' up to date (v${version}, ${base}-era${persona === 'split' ? ', persona-split' : ''}) — idle`)
|
|
1184
1314
|
continue
|
|
1185
1315
|
}
|
|
1186
1316
|
|
|
1187
|
-
const skills = materialize({ target, presetId, skillsSource, version, base, persona, present, rows })
|
|
1317
|
+
const skills = materialize({ target, presetId, skillsSource, version, base, persona, present, pluginManager, rows })
|
|
1188
1318
|
const verb = state === 'absent' ? 'materialized' : 'refreshed'
|
|
1189
1319
|
console.log(
|
|
1190
1320
|
`${TAG} ${verb} preset '${presetId}' into ${userRootPath} (v${version}, ${base}-era composition${persona === 'split' ? ', persona-split' : ''})` +
|
|
@@ -1194,4 +1324,4 @@ export async function apply(ctx, config = {}) {
|
|
|
1194
1324
|
}
|
|
1195
1325
|
|
|
1196
1326
|
// Test surface: pure helpers, no Cordis context required.
|
|
1197
|
-
export const _internal = { PRESET_IDS, translateMsysPath, translatePathArguments, readPosixPaths, windowsToMsys, rewriteResultPaths, MARKER_FILE, classify, materialize, cleanupOnDispose, firstUserRoot, hashTree, skillsHashes, syncDecision, installRegisterShim, baseForRoster, detectBase, pickComposition, personaEraForText, detectPersonaEra, injectPresentRow, hostHasToolPresent, detectPresentSupport, rowFormOf, rowFormsOf, alignEngineRow, alignRalphRow, ROW_SOURCE }
|
|
1327
|
+
export const _internal = { PRESET_IDS, translateMsysPath, translatePathArguments, readPosixPaths, readAdoptSidebar, windowsToMsys, rewriteResultPaths, MARKER_FILE, classify, materialize, cleanupOnDispose, firstUserRoot, hashTree, skillsHashes, syncDecision, installRegisterShim, baseForRoster, detectBase, pickComposition, personaEraForText, detectPersonaEra, injectPresentRow, hostHasToolPresent, detectPresentSupport, injectPluginManagerRow, hostHasPluginManagerTools, rowFormOf, rowFormsOf, alignEngineRow, alignRalphRow, ROW_SOURCE }
|