dsh-ptc-plus 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,34 @@
1
- # dsh-ptc-plus
1
+ <p align="center">
2
+ <img src="assets/dsh-ptc-plus-banner-en.webp" width="100%" alt="dsh-ptc-plus banner">
3
+ </p>
2
4
 
3
- English | [简体中文](README.zh.md)
5
+ <p align="center">
6
+ <strong>English</strong> ·
7
+ <a href="README.zh.md">简体中文</a>
8
+ </p>
4
9
 
5
- [![Node.js ^22.19.0 || >=24.0.0](https://img.shields.io/badge/Node.js-%5E22.19.0%20%7C%7C%20%3E%3D24.0.0-5fa04e?logo=nodedotjs&logoColor=white)](package.json)
6
- [![npm version](https://img.shields.io/npm/v/dsh-ptc-plus?logo=npm)](https://www.npmjs.com/package/dsh-ptc-plus)
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
- [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek%20Harness-PTC%20mode-4b6bfb)](https://github.com/deepseek-ai/deepseek-harness)
9
- [![Status: community plugin](https://img.shields.io/badge/Status-community%20plugin-lightgrey)](docs/publishing.md)
10
+ <p align="center">
11
+ <a href="#what-default-ptc-mode-gets-wrong">Problems</a> ·
12
+ <a href="#three-scenes-that-matter-most">Scenes</a> ·
13
+ <a href="#settings">Settings</a> ·
14
+ <a href="#scope">Scope</a> ·
15
+ <a href="#install">Install</a> ·
16
+ <a href="#documentation">Docs</a>
17
+ </p>
10
18
 
11
19
  <p align="center">
12
- <img src="assets/dsh-ptc-plus-banner.webp" alt="dsh-ptc-plus banner">
20
+ <a href="https://github.com/deepseek-ai/deepseek-harness"><img alt="DeepSeek Harness PTC mode" src="https://img.shields.io/badge/DeepSeek%20Harness-PTC%20mode-4b6bfb"></a>
21
+ <a href="package.json"><img alt="Node.js ^22.19.0 || >=24.0.0" src="https://img.shields.io/badge/Node.js-%5E22.19.0%20%7C%7C%20%3E%3D24.0.0-5fa04e?logo=nodedotjs&logoColor=white"></a>
22
+ <a href="https://www.npmjs.com/package/dsh-ptc-plus"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-ptc-plus?logo=npm"></a>
23
+ <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg"></a>
13
24
  </p>
14
25
 
26
+ <p align="center">
27
+ <a href="https://awesome-dsh-plugin.com/"><img alt="Awesome DSH Plugin" src="https://awesome-dsh-plugin.com/badge.svg"></a>
28
+ </p>
29
+
30
+ ---
31
+
15
32
  **PTC Plus gives DSH PTC mode a session-bound persistent TypeScript REPL.** Every `run_code` continues in the same session. Variables, imports, and results from one `run_code` are still available in the next one.
16
33
 
17
34
  > [!NOTE]
@@ -20,7 +37,7 @@ English | [简体中文](README.zh.md)
20
37
  > [!IMPORTANT]
21
38
  > Built for `danger-full-access`: direct Node.js and OS access with no extra sandbox. Use it only where that permission scope is acceptable.
22
39
 
23
- ![PTC Plus settings card](assets/ptc-plus-settings.png)
40
+ ![PTC Plus settings card](assets/ptc-plus-settings-en.png)
24
41
 
25
42
  *The settings card exposes live configuration and the `enabled` kill switch.*
26
43
 
@@ -73,6 +90,8 @@ edit_run_code({ edits: [{ old_string: 'deps.length', new_string: 'deps' }] })
73
90
 
74
91
  Only the diff goes in. The full source stays out of the conversation. Exact replacements and regular expressions both have limits, so a bad pattern cannot hang.
75
92
 
93
+ When a rejected cell has exactly one validated missing closing token at the end, its diagnostic includes the complete `edit_run_code(...)` call needed to apply that correction and rerun the cell. That generated call carries an `expected_target_call_seq` precondition, so it is rejected without execution if another cell becomes the edit target first. PTC Plus never applies the suggestion automatically; ambiguous repairs or repairs without a persistent target identity still require corrected source.
94
+
76
95
  ### Module syntax
77
96
 
78
97
  DSH PTC mode executes each `run_code` as an async function body, where static `import` and `export` declarations are invalid. PTC Plus adapts those forms before execution with AST analysis.
@@ -106,7 +125,7 @@ This is one stochastic paired observation, not a performance guarantee. Machine
106
125
 
107
126
  ## Settings
108
127
 
109
- Open **Settings → Plugin configuration** to use the card shown above. The `enabled` switch is live: turning it off leaves only the card and that switch, while turning it on restores the session runtime and `run_code`/`edit_run_code`.
128
+ Open **Settings → Plugin configuration** to use the card shown above. The card follows the DSH UI language: it renders in English when the harness is set to English, and in 中文 when set to Chinese. The `enabled` switch is live: turning it off leaves only the card and that switch, while turning it on restores the session runtime and `run_code`/`edit_run_code`.
110
129
 
111
130
  Every setting applies live and keeps existing bindings. A submitted cell uses one configuration for its complete execution; changes made while it runs apply to cells submitted afterward. A failed change rolls back. Node fixes a worker's V8 old-generation limit when the worker starts, so that one setting is rejected while a session worker is active and can be changed after the session is disposed. A failed enable is rolled back and persisted as disabled.
112
131
 
@@ -137,6 +156,6 @@ Restart that DSH profile after installation. Version-pinned npm, GitHub, local-c
137
156
 
138
157
  ## Documentation
139
158
 
140
- [Installation](docs/installation.md) · [Runtime reference](docs/runtime-reference.md) · [Architecture](docs/architecture.md) · [All docs](docs/README.md)
159
+ [Installation](docs/installation.md) · [Runtime reference](docs/runtime-reference.md) · [Architecture](docs/architecture.md) · [Publishing](docs/publishing.md) · [All docs](docs/README.md)
141
160
 
142
161
  MIT licensed. See [LICENSE](LICENSE).
package/README.zh.md CHANGED
@@ -1,17 +1,34 @@
1
- # dsh-ptc-plus
1
+ <p align="center">
2
+ <img src="assets/dsh-ptc-plus-banner-zh.webp" width="100%" alt="dsh-ptc-plus 横幅">
3
+ </p>
2
4
 
3
- [English](README.md) | 简体中文
5
+ <p align="center">
6
+ <a href="README.md">English</a> ·
7
+ <strong>简体中文</strong>
8
+ </p>
4
9
 
5
- [![Node.js ^22.19.0 || >=24.0.0](https://img.shields.io/badge/Node.js-%5E22.19.0%20%7C%7C%20%3E%3D24.0.0-5fa04e?logo=nodedotjs&logoColor=white)](package.json)
6
- [![npm version](https://img.shields.io/npm/v/dsh-ptc-plus?logo=npm)](https://www.npmjs.com/package/dsh-ptc-plus)
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
- [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek%20Harness-PTC%20mode-4b6bfb)](https://github.com/deepseek-ai/deepseek-harness)
9
- [![Status: community plugin](https://img.shields.io/badge/Status-community%20plugin-lightgrey)](docs/publishing.md)
10
+ <p align="center">
11
+ <a href="#%E9%BB%98%E8%AE%A4-ptc-%E6%A8%A1%E5%BC%8F%E7%9A%84%E9%97%AE%E9%A2%98">问题</a> ·
12
+ <a href="#%E4%B8%89%E4%B8%AA%E6%9C%80%E7%9B%B4%E6%8E%A5%E7%9A%84%E5%9C%BA%E6%99%AF">场景</a> ·
13
+ <a href="#%E8%AE%BE%E7%BD%AE">设置</a> ·
14
+ <a href="#%E8%8C%83%E5%9B%B4">范围</a> ·
15
+ <a href="#%E5%AE%89%E8%A3%85">安装</a> ·
16
+ <a href="#%E6%96%87%E6%A1%A3">文档</a>
17
+ </p>
10
18
 
11
19
  <p align="center">
12
- <img src="assets/dsh-ptc-plus-banner.webp" alt="dsh-ptc-plus 横幅">
20
+ <a href="https://github.com/deepseek-ai/deepseek-harness"><img alt="DeepSeek Harness PTC mode" src="https://img.shields.io/badge/DeepSeek%20Harness-PTC%20mode-4b6bfb"></a>
21
+ <a href="package.json"><img alt="Node.js ^22.19.0 || >=24.0.0" src="https://img.shields.io/badge/Node.js-%5E22.19.0%20%7C%7C%20%3E%3D24.0.0-5fa04e?logo=nodedotjs&logoColor=white"></a>
22
+ <a href="https://www.npmjs.com/package/dsh-ptc-plus"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-ptc-plus?logo=npm"></a>
23
+ <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg"></a>
13
24
  </p>
14
25
 
26
+ <p align="center">
27
+ <a href="https://awesome-dsh-plugin.com/zh/"><img alt="Awesome DSH Plugin" src="https://awesome-dsh-plugin.com/badge.svg"></a>
28
+ </p>
29
+
30
+ ---
31
+
15
32
  **PTC Plus 给 DSH 的 PTC 模式一个会话绑定的持久 TypeScript REPL。** 每次 `run_code` 都在同一个会话里继续。上一次 `run_code` 的变量、导入和结果,下一次还能直接用。
16
33
 
17
34
  > [!NOTE]
@@ -20,7 +37,7 @@
20
37
  > [!IMPORTANT]
21
38
  > 面向 `danger-full-access` 设计:可直接访问 Node.js 与操作系统,不另加沙箱。仅在可接受此权限的环境使用。
22
39
 
23
- ![PTC Plus 设置卡片](assets/ptc-plus-settings.png)
40
+ ![PTC Plus 设置卡片](assets/ptc-plus-settings-zh.png)
24
41
 
25
42
  *设置卡片展示即时配置和 `enabled` 开关。*
26
43
 
@@ -73,6 +90,8 @@ edit_run_code({ edits: [{ old_string: 'deps.length', new_string: 'deps' }] })
73
90
 
74
91
  模型只发改动,完整源码留在对话之外。精确文本替换和正则替换都有限制,坏的正则不会卡住。
75
92
 
93
+ 当被拒 cell 的末尾可唯一验证为缺少一个闭合符时,诊断会直接给出应用该修正并重运行所需的完整 `edit_run_code(...)` 调用。生成的调用带有 `expected_target_call_seq` 前置条件;如果另一个 cell 已先成为 edit 目标,它会拒绝且不执行。PTC Plus 不会自动应用这项建议;有歧义或没有持久目标身份的修复仍需提交修正后的源码。
94
+
76
95
  ### 模块语法
77
96
 
78
97
  DSH 的 PTC 模式把每个 `run_code` 当作 async function body 执行,静态 `import` 和 `export` 声明在这个函数体里无效。PTC Plus 会在执行前用 AST 分析适配这些形式。
@@ -106,7 +125,7 @@ import { readFile } from 'node:fs/promises'
106
125
 
107
126
  ## 设置
108
127
 
109
- 打开 **设置 → 插件配置** 使用上面的设置卡片。`enabled` 是即时生效的总开关:关闭后只保留卡片和这个开关,开启后恢复 session runtime 以及 `run_code`/`edit_run_code`。
128
+ 打开 **设置 → 插件配置** 使用上面的设置卡片。卡片跟随 DSH 界面语言:界面设为 English 时显示英文,设为中文时显示中文。`enabled` 是即时生效的总开关:关闭后只保留卡片和这个开关,开启后恢复 session runtime 以及 `run_code`/`edit_run_code`。
110
129
 
111
130
  所有设置都会实时应用,并保留已有 binding。已提交的 cell 在完整执行期间使用同一份配置;执行期间发生的更新用于随后提交的 cell。更新失败会回滚。Node 在 worker 创建时固定 V8 old-generation 上限,因此活动 session worker 存在时修改这一项会被拒绝,释放 session 后才能修改。启用失败时,运行时会回滚并把设置保持为停用。
112
131
 
@@ -137,6 +156,6 @@ dsh --profile <profile> --dump-config
137
156
 
138
157
  ## 文档
139
158
 
140
- [安装指南](docs/installation.md) · [运行时参考](docs/runtime-reference.md) · [架构](docs/architecture.md) · [全部文档](docs/README.md)
159
+ [安装指南](docs/installation.md) · [运行时参考](docs/runtime-reference.md) · [架构](docs/architecture.md) · [发布](docs/publishing.md) · [全部文档](docs/README.md)
141
160
 
142
161
  使用 [MIT License](LICENSE)。
Binary file
Binary file
package/client.js CHANGED
@@ -8,14 +8,18 @@
8
8
  type: "boolean",
9
9
  default: true,
10
10
  label: "\u542F\u7528 PTC Plus",
11
- description: ""
11
+ labelEn: "Enable PTC Plus",
12
+ description: "",
13
+ descriptionEn: ""
12
14
  },
13
15
  {
14
16
  key: "cordisToolsEnabled",
15
17
  type: "boolean",
16
18
  default: false,
17
19
  label: "\u5728 PTC \u6A21\u5F0F\u4E2D\u542F\u7528 Cordis \u5DE5\u5177",
18
- description: "\u5373\u65F6\u4E3A PTC agent \u52A0\u5165\u6216\u79FB\u9664\u5B98\u65B9 Cordis \u5DE5\u5177\u3002"
20
+ labelEn: "Enable Cordis tools in PTC mode",
21
+ description: "\u5373\u65F6\u4E3A PTC agent \u52A0\u5165\u6216\u79FB\u9664\u5B98\u65B9 Cordis \u5DE5\u5177\u3002",
22
+ descriptionEn: "Adds or removes the official Cordis tools for the PTC agent immediately."
19
23
  },
20
24
  {
21
25
  key: "computeMs",
@@ -24,7 +28,9 @@
24
28
  min: 1,
25
29
  max: Number.MAX_SAFE_INTEGER,
26
30
  label: "\u5355 cell \u6700\u5927 CPU \u65F6\u95F4 (ms)",
27
- description: "\u540C\u6B65\u8BA1\u7B97\u8D85\u8FC7\u8BE5\u9884\u7B97\u7684 cell \u4F1A\u88AB\u4E2D\u65AD\u3002"
31
+ labelEn: "Max CPU time per cell (ms)",
32
+ description: "\u540C\u6B65\u8BA1\u7B97\u8D85\u8FC7\u8BE5\u9884\u7B97\u7684 cell \u4F1A\u88AB\u4E2D\u65AD\u3002",
33
+ descriptionEn: "Cells whose synchronous computation exceeds this budget are interrupted."
28
34
  },
29
35
  {
30
36
  key: "maxWallMs",
@@ -33,7 +39,9 @@
33
39
  min: 1,
34
40
  max: MAX_TIMER_DELAY_MS,
35
41
  label: "\u5355 cell \u6700\u5927\u5899\u949F\u65F6\u95F4 (ms)",
36
- description: "\u5B8C\u6574 cell \u6267\u884C\uFF08\u542B\u5F02\u6B65\u7B49\u5F85\uFF09\u7684\u6700\u957F\u8017\u65F6\u3002"
42
+ labelEn: "Max wall-clock time per cell (ms)",
43
+ description: "\u5B8C\u6574 cell \u6267\u884C\uFF08\u542B\u5F02\u6B65\u7B49\u5F85\uFF09\u7684\u6700\u957F\u8017\u65F6\u3002",
44
+ descriptionEn: "The longest a full cell execution may take, including async waits."
37
45
  },
38
46
  {
39
47
  key: "maxOutputBytes",
@@ -42,7 +50,9 @@
42
50
  min: 1,
43
51
  max: Number.MAX_SAFE_INTEGER,
44
52
  label: "\u6700\u5927\u8F93\u51FA\u5B57\u8282",
45
- description: "\u9650\u5236\u5355\u4E2A cell \u7684\u8F93\u51FA\u548C\u7ED3\u679C\u6570\u636E\u603B\u5927\u5C0F\u3002"
53
+ labelEn: "Max output bytes",
54
+ description: "\u9650\u5236\u5355\u4E2A cell \u7684\u8F93\u51FA\u548C\u7ED3\u679C\u6570\u636E\u603B\u5927\u5C0F\u3002",
55
+ descriptionEn: "Caps the combined size of one cell output and result data."
46
56
  },
47
57
  {
48
58
  key: "maxOldGenerationSizeMb",
@@ -51,7 +61,9 @@
51
61
  min: 1,
52
62
  max: Number.MAX_SAFE_INTEGER,
53
63
  label: "worker \u65E7\u751F\u4EE3\u5185\u5B58\u4E0A\u9650 (MiB)",
54
- description: "\u6BCF\u4E2A worker \u7684 V8 \u65E7\u751F\u4EE3\u4E0A\u9650\uFF1B\u6D3B\u52A8 worker \u5B58\u5728\u65F6\u4FEE\u6539\u4F1A\u88AB\u62D2\u7EDD\u3002"
64
+ labelEn: "Worker old-generation memory cap (MiB)",
65
+ description: "\u6BCF\u4E2A worker \u7684 V8 \u65E7\u751F\u4EE3\u4E0A\u9650\uFF1B\u6D3B\u52A8 worker \u5B58\u5728\u65F6\u4FEE\u6539\u4F1A\u88AB\u62D2\u7EDD\u3002",
66
+ descriptionEn: "Per-worker V8 old-generation limit; changes are rejected while an active worker exists."
55
67
  },
56
68
  {
57
69
  key: "maxValueNodes",
@@ -60,7 +72,9 @@
60
72
  min: 1,
61
73
  max: Number.MAX_SAFE_INTEGER,
62
74
  label: "Value Graph \u6700\u5927\u8282\u70B9\u6570",
63
- description: "\u9650\u5236\u5355\u6B21\u8FD4\u56DE\u503C\u7684\u8282\u70B9\u6570\u3002"
75
+ labelEn: "Max Value Graph nodes",
76
+ description: "\u9650\u5236\u5355\u6B21\u8FD4\u56DE\u503C\u7684\u8282\u70B9\u6570\u3002",
77
+ descriptionEn: "Caps the node count of a single returned value."
64
78
  },
65
79
  {
66
80
  key: "maxValueEdges",
@@ -69,7 +83,9 @@
69
83
  min: 1,
70
84
  max: Number.MAX_SAFE_INTEGER,
71
85
  label: "Value Graph \u6700\u5927\u8FB9\u6570",
72
- description: "\u9650\u5236\u5355\u6B21\u8FD4\u56DE\u503C\u7684\u5F15\u7528\u5173\u7CFB\u6570\u3002"
86
+ labelEn: "Max Value Graph edges",
87
+ description: "\u9650\u5236\u5355\u6B21\u8FD4\u56DE\u503C\u7684\u5F15\u7528\u5173\u7CFB\u6570\u3002",
88
+ descriptionEn: "Caps the reference-edge count of a single returned value."
73
89
  },
74
90
  {
75
91
  key: "maxValueArrayLength",
@@ -78,7 +94,9 @@
78
94
  min: 1,
79
95
  max: Number.MAX_SAFE_INTEGER,
80
96
  label: "\u6570\u7EC4\u6700\u5927\u58F0\u660E\u957F\u5EA6",
81
- description: "\u9650\u5236\u8FD4\u56DE\u6570\u7EC4\u7684\u6700\u5927\u957F\u5EA6\u3002"
97
+ labelEn: "Max declared array length",
98
+ description: "\u9650\u5236\u8FD4\u56DE\u6570\u7EC4\u7684\u6700\u5927\u957F\u5EA6\u3002",
99
+ descriptionEn: "Caps the maximum length of a returned array."
82
100
  },
83
101
  {
84
102
  key: "maxValueBigIntDigits",
@@ -87,7 +105,9 @@
87
105
  min: 1,
88
106
  max: Number.MAX_SAFE_INTEGER,
89
107
  label: "BigInt \u6700\u5927\u5341\u8FDB\u5236\u4F4D\u6570",
90
- description: "\u9650\u5236\u8FD4\u56DE\u503C\u4E2D BigInt \u7684\u5341\u8FDB\u5236\u4F4D\u6570\u3002"
108
+ labelEn: "Max BigInt decimal digits",
109
+ description: "\u9650\u5236\u8FD4\u56DE\u503C\u4E2D BigInt \u7684\u5341\u8FDB\u5236\u4F4D\u6570\u3002",
110
+ descriptionEn: "Caps the decimal digits of BigInt values in a returned value."
91
111
  },
92
112
  {
93
113
  key: "maxNestedRunCodeDepth",
@@ -96,56 +116,72 @@
96
116
  min: 1,
97
117
  max: Number.MAX_SAFE_INTEGER,
98
118
  label: "code.run \u6700\u5927\u9012\u5F52\u6DF1\u5EA6",
99
- description: "\u9650\u5236 code.run \u7684\u5D4C\u5957\u5C42\u6570\u3002"
119
+ labelEn: "Max code.run recursion depth",
120
+ description: "\u9650\u5236 code.run \u7684\u5D4C\u5957\u5C42\u6570\u3002",
121
+ descriptionEn: "Caps how deeply code.run may nest."
100
122
  },
101
123
  {
102
124
  key: "canonicalizeToolCalls",
103
125
  type: "boolean",
104
126
  default: true,
105
127
  label: "\u89C4\u8303\u9876\u5C42 native \u8BEF\u8C03",
106
- description: "\u4FEE\u6B63\u53EF\u4EE5\u660E\u786E\u8BC6\u522B\u7684\u9876\u5C42 native \u8BEF\u8C03\u3002"
128
+ labelEn: "Canonicalize top-level native mis-calls",
129
+ description: "\u4FEE\u6B63\u53EF\u4EE5\u660E\u786E\u8BC6\u522B\u7684\u9876\u5C42 native \u8BEF\u8C03\u3002",
130
+ descriptionEn: "Repairs top-level native mis-calls that can be identified unambiguously."
107
131
  },
108
132
  {
109
133
  key: "looseTopLevelRedeclarations",
110
134
  type: "boolean",
111
135
  default: true,
112
136
  label: "\u5BBD\u677E\u9876\u5C42\u91CD\u58F0\u660E",
113
- description: "\u5141\u8BB8\u9876\u5C42 const/let \u91CD\u58F0\u660E\u5DF2\u6709\u53D8\u91CF\u3002"
137
+ labelEn: "Loose top-level redeclarations",
138
+ description: "\u5141\u8BB8\u9876\u5C42 const/let \u91CD\u58F0\u660E\u5DF2\u6709\u53D8\u91CF\u3002",
139
+ descriptionEn: "Allows top-level const/let to redeclare existing variables."
114
140
  },
115
141
  {
116
142
  key: "durableReplay",
117
143
  type: "boolean",
118
144
  default: true,
119
145
  label: "\u6301\u4E45\u91CD\u653E",
120
- description: "worker \u91CD\u542F\u540E\u6062\u590D\u53EF\u4EE5\u91CD\u5EFA\u7684 REPL \u72B6\u6001\u3002"
146
+ labelEn: "Durable replay",
147
+ description: "worker \u91CD\u542F\u540E\u6062\u590D\u53EF\u4EE5\u91CD\u5EFA\u7684 REPL \u72B6\u6001\u3002",
148
+ descriptionEn: "Rebuilds recoverable REPL state after a worker restart."
121
149
  },
122
150
  {
123
151
  key: "autoRewriteImports",
124
152
  type: "boolean",
125
153
  default: true,
126
154
  label: "\u81EA\u52A8\u6539\u5199 import",
127
- description: "\u5141\u8BB8\u5728 run_code \u4E2D\u4F7F\u7528\u9759\u6001 import\u3002"
155
+ labelEn: "Auto-rewrite import",
156
+ description: "\u5141\u8BB8\u5728 run_code \u4E2D\u4F7F\u7528\u9759\u6001 import\u3002",
157
+ descriptionEn: "Allows static import declarations inside run_code."
128
158
  },
129
159
  {
130
160
  key: "autoStripExports",
131
161
  type: "boolean",
132
162
  default: true,
133
163
  label: "\u81EA\u52A8\u5265\u79BB export",
134
- description: "\u5141\u8BB8\u5728 run_code \u4E2D\u4F7F\u7528\u9876\u5C42 export\u3002"
164
+ labelEn: "Auto-strip export",
165
+ description: "\u5141\u8BB8\u5728 run_code \u4E2D\u4F7F\u7528\u9876\u5C42 export\u3002",
166
+ descriptionEn: "Allows top-level export modifiers inside run_code."
135
167
  },
136
168
  {
137
169
  key: "autoSplitRedeclarations",
138
170
  type: "boolean",
139
171
  default: true,
140
172
  label: "\u81EA\u52A8\u62C6\u5206\u6DF7\u5408\u91CD\u58F0\u660E",
141
- description: "\u5141\u8BB8\u9876\u5C42\u89E3\u6784\u58F0\u660E\u540C\u65F6\u5305\u542B\u65B0\u65E7\u53D8\u91CF\u3002"
173
+ labelEn: "Auto-split mixed redeclarations",
174
+ description: "\u5141\u8BB8\u9876\u5C42\u89E3\u6784\u58F0\u660E\u540C\u65F6\u5305\u542B\u65B0\u65E7\u53D8\u91CF\u3002",
175
+ descriptionEn: "Allows top-level destructuring declarations that mix new and existing variables."
142
176
  },
143
177
  {
144
178
  key: "tipsEnabled",
145
179
  type: "boolean",
146
180
  default: true,
147
181
  label: "\u542F\u7528\u6062\u590D\u63D0\u793A",
148
- description: "\u5728\u7B26\u5408\u6761\u4EF6\u7684\u5931\u8D25\u540E\u663E\u793A\u6062\u590D\u63D0\u793A\u3002"
182
+ labelEn: "Enable recovery tips",
183
+ description: "\u5728\u7B26\u5408\u6761\u4EF6\u7684\u5931\u8D25\u540E\u663E\u793A\u6062\u590D\u63D0\u793A\u3002",
184
+ descriptionEn: "Shows recovery tips after qualifying failures."
149
185
  },
150
186
  {
151
187
  key: "tipCooldownMessages",
@@ -154,7 +190,9 @@
154
190
  min: 1,
155
191
  max: Number.MAX_SAFE_INTEGER,
156
192
  label: "\u6062\u590D\u63D0\u793A\u51B7\u5374\u6B65\u6570",
157
- description: "\u540C\u7C7B\u6062\u590D\u63D0\u793A\u4E4B\u95F4\u7684\u6700\u5C0F\u95F4\u9694\u3002"
193
+ labelEn: "Recovery tip cooldown (messages)",
194
+ description: "\u540C\u7C7B\u6062\u590D\u63D0\u793A\u4E4B\u95F4\u7684\u6700\u5C0F\u95F4\u9694\u3002",
195
+ descriptionEn: "The minimum gap between recovery tips of the same kind."
158
196
  },
159
197
  {
160
198
  key: "tipEscalationFailures",
@@ -163,7 +201,9 @@
163
201
  min: 1,
164
202
  max: Number.MAX_SAFE_INTEGER,
165
203
  label: "\u6062\u590D\u63D0\u793A\u5347\u7EA7\u5931\u8D25\u6B21\u6570",
166
- description: "\u8FDE\u7EED\u5931\u8D25\u8FBE\u5230\u6B64\u6B21\u6570\u540E\u663E\u793A\u66F4\u8BE6\u7EC6\u7684\u6062\u590D\u63D0\u793A\u3002"
204
+ labelEn: "Recovery tip escalation failures",
205
+ description: "\u8FDE\u7EED\u5931\u8D25\u8FBE\u5230\u6B64\u6B21\u6570\u540E\u663E\u793A\u66F4\u8BE6\u7EC6\u7684\u6062\u590D\u63D0\u793A\u3002",
206
+ descriptionEn: "After this many consecutive failures, a more detailed recovery tip is shown."
167
207
  }
168
208
  ]);
169
209
  var CONFIG_DEFAULTS = Object.freeze(
@@ -183,6 +223,55 @@
183
223
  @media(max-width:560px){.ptcPlusHeader{padding:12px}.ptcPlusFields{margin:0 12px}.ptcPlusRow{align-items:flex-start;flex-direction:column;gap:6px;padding:10px 0}.ptcPlusInput{width:100%}.ptcPlusFooter{align-items:stretch;flex-direction:column}.ptcPlusButton{width:100%}}
184
224
  @media(prefers-reduced-motion:reduce){.ptcPlusHeader,.ptcPlusChevron,.ptcPlusBody,.ptcPlusButton{transition:none}}
185
225
  `;
226
+ var LOCALE_NS = "settings.ptcPlus";
227
+ var CHROME_COPY = Object.freeze({
228
+ zh: Object.freeze({
229
+ "card.description": "PTC \u6A21\u5F0F\u7684\u4F1A\u8BDD\u7EA7 TypeScript REPL\u3002",
230
+ "status.enabled": "\u5DF2\u542F\u7528",
231
+ "status.disabled": "\u5DF2\u505C\u7528",
232
+ "action.expand": "\u5C55\u5F00 PTC Plus \u8BBE\u7F6E",
233
+ "action.collapse": "\u6536\u8D77 PTC Plus \u8BBE\u7F6E",
234
+ "state.syncing": "\u6B63\u5728\u540C\u6B65\u8BBE\u7F6E...",
235
+ "state.unavailable": "\u5F53\u524D DSH \u5B9E\u4F8B\u672A\u63D0\u4F9B\u8BBE\u7F6E\u670D\u52A1",
236
+ "footer.live": "\u8BBE\u7F6E\u4F1A\u5728\u4FEE\u6539\u540E\u7ACB\u5373\u751F\u6548",
237
+ "footer.readOnly": "\u5F53\u524D\u8BBE\u7F6E\u4E3A\u53EA\u8BFB",
238
+ "status.applied": "\u8BBE\u7F6E\u5DF2\u7ACB\u5373\u751F\u6548",
239
+ "status.conflict": "\u8BBE\u7F6E\u672A\u751F\u6548\uFF0C\u8BF7\u68C0\u67E5\u8BBE\u7F6E\u51B2\u7A81",
240
+ "status.failed": "\u8BBE\u7F6E\u5931\u8D25\uFF1A{error}",
241
+ "indicator.title": "PTC Plus \u5DF2\u542F\u7528"
242
+ }),
243
+ en: Object.freeze({
244
+ "card.description": "The session-bound TypeScript REPL for PTC mode.",
245
+ "status.enabled": "Enabled",
246
+ "status.disabled": "Disabled",
247
+ "action.expand": "Expand PTC Plus settings",
248
+ "action.collapse": "Collapse PTC Plus settings",
249
+ "state.syncing": "Syncing settings...",
250
+ "state.unavailable": "This DSH instance does not provide a settings service",
251
+ "footer.live": "Changes take effect immediately.",
252
+ "footer.readOnly": "These settings are read-only.",
253
+ "status.applied": "Setting applied immediately.",
254
+ "status.conflict": "The setting did not take effect; check for conflicting settings.",
255
+ "status.failed": "Could not save: {error}",
256
+ "indicator.title": "PTC Plus is active"
257
+ })
258
+ });
259
+ function fieldCopy(field, locale) {
260
+ const copy = { [`${field.key}.label`]: locale === "en" ? field.labelEn : field.label };
261
+ const description = locale === "en" ? field.descriptionEn : field.description;
262
+ if (description !== "") copy[`${field.key}.description`] = description;
263
+ return copy;
264
+ }
265
+ var SETTINGS_COPY = Object.freeze(Object.fromEntries(
266
+ ["zh", "en"].map((locale) => [locale, Object.freeze({
267
+ ...CHROME_COPY[locale],
268
+ ...Object.assign({}, ...CONFIG_FIELDS.map((field) => fieldCopy(field, locale)))
269
+ })])
270
+ ));
271
+ function sessionUsesPtcPreset(session) {
272
+ const preset = session?.projectionValues?.agentPreset ?? session?.agentPreset;
273
+ return preset === "ptc" || preset === "code";
274
+ }
186
275
  window.__ModuleLoader__.load({
187
276
  // Replaced by the bundle entry with the package name from package.json.
188
277
  id: "dsh-ptc-plus",
@@ -190,8 +279,7 @@
190
279
  const React = require2("react");
191
280
  const {
192
281
  IconCheckOutline14,
193
- IconChevronDownOutline14,
194
- IconSettingsOutline16
282
+ IconChevronDownOutline14
195
283
  } = require2("@deepseek-ai/dsh-client-ui-primitives");
196
284
  const module = { exports: {} };
197
285
  const h = React.createElement;
@@ -204,7 +292,7 @@
204
292
  document.head.append(style);
205
293
  return () => style.remove();
206
294
  }
207
- function fieldInput(field, value, disabled, onChange) {
295
+ function fieldInput(field, value, disabled, onChange, label) {
208
296
  if (field.type === "boolean") {
209
297
  return h("input", {
210
298
  type: "checkbox",
@@ -212,7 +300,7 @@
212
300
  className: "ptcPlusCheck",
213
301
  checked: value === true,
214
302
  disabled,
215
- "aria-label": field.label,
303
+ "aria-label": label,
216
304
  onChange: (event) => onChange(field, event.target.checked)
217
305
  });
218
306
  }
@@ -224,7 +312,7 @@
224
312
  max: field.max,
225
313
  step: 1,
226
314
  disabled,
227
- "aria-label": field.label,
315
+ "aria-label": label,
228
316
  onChange: (event) => {
229
317
  const input = event.target.value;
230
318
  const parsed = input === "" ? "" : Number(input);
@@ -234,10 +322,11 @@
234
322
  }
235
323
  function apply(ctx) {
236
324
  const preferenceScope = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
325
+ ctx.effect(() => ctx.locale.register(LOCALE_NS, SETTINGS_COPY), "ptc-plus: settings dictionaries");
237
326
  ctx.effect(installStyles, "ptc-plus: client styles");
238
- function PTCPlusSettingsCard() {
327
+ function PTCPlusSettingsCard({ t }) {
239
328
  const [open, setOpen] = React.useState(false);
240
- const [status, setStatus] = React.useState("");
329
+ const [status, setStatus] = React.useState(null);
241
330
  const [pending, setPending] = React.useState(() => /* @__PURE__ */ new Set());
242
331
  const writeTail = React.useRef(Promise.resolve());
243
332
  const subscribe = React.useCallback((listener) => preferenceScope.subscribe(listener), []);
@@ -254,17 +343,20 @@
254
343
  if (field.key !== "enabled" && before.value?.enabled !== true) return;
255
344
  if (before.value?.[field.key] === nextValue) return;
256
345
  setPending((current) => new Set(current).add(field.key));
257
- setStatus("");
346
+ setStatus(null);
258
347
  try {
259
348
  await preferenceScope.set(field.key, nextValue);
260
349
  const after = preferenceScope.getSnapshot();
261
350
  if (after.status !== "ready" || after.value?.[field.key] !== nextValue) {
262
- setStatus("\u8BBE\u7F6E\u672A\u751F\u6548\uFF0C\u8BF7\u68C0\u67E5\u8BBE\u7F6E\u51B2\u7A81");
351
+ setStatus({ key: "status.conflict" });
263
352
  } else {
264
- setStatus("\u8BBE\u7F6E\u5DF2\u7ACB\u5373\u751F\u6548");
353
+ setStatus({ key: "status.applied" });
265
354
  }
266
355
  } catch (error) {
267
- setStatus("\u8BBE\u7F6E\u5931\u8D25\uFF1A" + (error instanceof Error ? error.message : String(error)));
356
+ setStatus({
357
+ key: "status.failed",
358
+ params: { error: error instanceof Error ? error.message : String(error) }
359
+ });
268
360
  } finally {
269
361
  setPending((current) => {
270
362
  const next = new Set(current);
@@ -286,18 +378,17 @@
286
378
  type: "button",
287
379
  className: "ptcPlusHeader",
288
380
  "aria-expanded": open,
289
- "aria-label": open ? "\u6536\u8D77 PTC Plus \u8BBE\u7F6E" : "\u5C55\u5F00 PTC Plus \u8BBE\u7F6E",
381
+ "aria-label": t(open ? "action.collapse" : "action.expand"),
290
382
  "aria-controls": "ptc-plus-settings-body",
291
383
  onClick: () => setOpen((current) => !current)
292
384
  },
293
- h(IconSettingsOutline16, { size: 16 }),
294
385
  h(
295
386
  "span",
296
387
  { className: "ptcPlusHeadText" },
297
388
  h("span", { className: "ptcPlusName" }, "PTC Plus"),
298
- h("span", { className: "ptcPlusDescription" }, "PTC \u6A21\u5F0F\u7684\u4F1A\u8BDD\u7EA7 TypeScript REPL\u3002")
389
+ h("span", { className: "ptcPlusDescription" }, t("card.description"))
299
390
  ),
300
- h("span", { className: "ptcPlusStatus", "data-enabled": enabled }, enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
391
+ h("span", { className: "ptcPlusStatus", "data-enabled": enabled }, t(enabled ? "status.enabled" : "status.disabled")),
301
392
  h("span", { className: "ptcPlusChevron", "data-open": open, "aria-hidden": true }, h(IconChevronDownOutline14, { size: 14 }))
302
393
  ),
303
394
  h(
@@ -306,22 +397,22 @@
306
397
  h("div", { className: "ptcPlusBodyInner" }, h(
307
398
  "div",
308
399
  { className: "ptcPlusFields" },
309
- snapshot.status === "loading" ? h("p", { className: "ptcPlusMessage" }, "\u6B63\u5728\u540C\u6B65\u8BBE\u7F6E...") : snapshot.status === "unavailable" ? h("p", { className: "ptcPlusMessage" }, "\u5F53\u524D DSH \u5B9E\u4F8B\u672A\u63D0\u4F9B\u8BBE\u7F6E\u670D\u52A1") : [
400
+ snapshot.status === "loading" ? h("p", { className: "ptcPlusMessage" }, t("state.syncing")) : snapshot.status === "unavailable" ? h("p", { className: "ptcPlusMessage" }, t("state.unavailable")) : [
310
401
  ...CONFIG_FIELDS.map((field) => h(
311
402
  "div",
312
403
  { key: field.key, className: "ptcPlusRow" },
313
404
  h(
314
405
  "div",
315
406
  { className: "ptcPlusMain" },
316
- h("div", { className: "ptcPlusLabel" }, field.label),
317
- field.description === "" ? null : h("div", { className: "ptcPlusDetail" }, field.description)
407
+ h("div", { className: "ptcPlusLabel" }, t(`${field.key}.label`)),
408
+ field.description === "" ? null : h("div", { className: "ptcPlusDetail" }, t(`${field.key}.description`))
318
409
  ),
319
- fieldInput(field, value[field.key], fieldDisabled(field), persist)
410
+ fieldInput(field, value[field.key], fieldDisabled(field), persist, t(`${field.key}.label`))
320
411
  )),
321
412
  h(
322
413
  "div",
323
414
  { key: "footer", className: "ptcPlusFooter" },
324
- h("span", { className: "ptcPlusMessage", role: "status" }, status || (snapshot.writable ? "\u8BBE\u7F6E\u4F1A\u5728\u4FEE\u6539\u540E\u7ACB\u5373\u751F\u6548" : "\u5F53\u524D\u8BBE\u7F6E\u4E3A\u53EA\u8BFB"))
415
+ h("span", { className: "ptcPlusMessage", role: "status" }, status === null ? t(snapshot.writable ? "footer.live" : "footer.readOnly") : t(status.key, status.params))
325
416
  )
326
417
  ]
327
418
  ))
@@ -330,10 +421,11 @@
330
421
  }
331
422
  ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
332
423
  name: "settings.plugin.item",
333
- key: SETTINGS_NAMESPACE
424
+ key: SETTINGS_NAMESPACE,
425
+ locale: LOCALE_NS
334
426
  }, PTCPlusSettingsCard));
335
427
  ctx.inject(["slots", "sessions"], (scope) => {
336
- function PTCPlusSessionIndicator({ sessionId }) {
428
+ function PTCPlusSessionIndicator({ sessionId, t }) {
337
429
  const sessions = React.useSyncExternalStore(
338
430
  (listener) => scope.sessions.list.subscribe(listener),
339
431
  () => scope.sessions.list.getSnapshot(),
@@ -344,10 +436,10 @@
344
436
  () => preferenceScope.getSnapshot(),
345
437
  () => preferenceScope.getSnapshot()
346
438
  );
347
- if (sessions.byId?.[sessionId]?.agentPreset !== "code" || settings.status !== "ready" || settings.value?.enabled !== true) return null;
439
+ if (!sessionUsesPtcPreset(sessions.byId?.[sessionId]) || settings.status !== "ready" || settings.value?.enabled !== true) return null;
348
440
  return h(
349
441
  "span",
350
- { className: "ptcPlusActive", title: "PTC Plus \u5DF2\u542F\u7528" },
442
+ { className: "ptcPlusActive", title: t("indicator.title") },
351
443
  h(IconCheckOutline14, { size: 14 }),
352
444
  "PTC Plus"
353
445
  );
@@ -355,11 +447,12 @@
355
447
  scope.slots.inject("conversation.session.header.actions", () => scope.slots.register({
356
448
  name: "conversation.session.header.actions",
357
449
  id: "ptc-plus-active",
358
- order: -9
450
+ order: -9,
451
+ locale: LOCALE_NS
359
452
  }, PTCPlusSessionIndicator));
360
453
  });
361
454
  }
362
- module.exports = { apply, inject: ["settingsScope", "slots", "sessions"] };
455
+ module.exports = { apply, inject: ["settingsScope", "slots", "sessions", "locale"] };
363
456
  return module.exports;
364
457
  }
365
458
  });