dsh-code-server-app 0.3.19 → 0.3.21

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.en.md CHANGED
@@ -206,9 +206,13 @@ only the editor knows, and lets editor gestures drive the current session.
206
206
  - **Ask panel** (extension 0.2.0): the context-menu command no longer pops a one-line input box but opens a panel —
207
207
  transcript on top, input at the bottom. The selection is captured **at send time** (so you can change it while the
208
208
  panel stays open), and the reply refreshes with the same polling round trip: no need to switch back to the DSH UI.
209
+ The two commands **remember their intent** (0.3.21): "ask about selection" carries a **line range + selection text**
210
+ only when something is actually selected, while "ask about file" **never carries line numbers or a selection** — the
211
+ cursor line is irrelevant to the question and only misleads the agent. With no selection, the selection command also
212
+ degrades to the plain file.
209
213
  - The question enters the DSH session as a **plain user message** (`source: { kind: 'user' }`, host 0.3.19): earlier
210
214
  versions used `{kind:'plugin'}`, which DSH renders as a *context update* — it did not look like something the user
211
- said. Provenance stays in the first line of the text: `From the editor: <file>:<line>`.
215
+ said. Provenance stays in the first line of the text: `From the editor: <file>[:<line>]`.
212
216
  - **Everything is read-only**: the bridge never writes files, applies edits, or runs commands. The agent's writes
213
217
  still go through its own `fs` tools; the bridge only *knows about* them.
214
218
  - Status bar shows `$(plug) DSH` while connected (click it for the log in the "DSH Editor Bridge" output channel).
package/README.md CHANGED
@@ -200,9 +200,12 @@ DSH 用**资源地址**命名文件,`openFile` 只负责把地址交给右侧栏
200
200
  - 工具只在桥就绪时注册(IDE 没起来时模型看不到"有个用不了的工具");提示词段落也只在桥存活时渲染。
201
201
  - **提问面板**(扩展 0.2.0 起):右键命令不再弹一行输入框,而是一个面板 —— 上面是问答记录、下面是输入框;
202
202
  发送时**现取当前选区**(可以在面板开着的同时改选区再问);回答跟着轮询一起刷新,不用切回 DSH 界面。
203
+ 两个命令的**意图分开记**(0.3.21):「针对选中内容提问」只有真的选了内容才带**行区间 + 选区正文**;
204
+ 「针对当前文件提问」**永远不带行号、不带选区** —— 光标停在哪一行跟问题无关,行号只会误导 agent;
205
+ 没选区时用选中命令提问也会退化成纯文件。
203
206
  - 提问进 DSH 会话时是**普通用户消息**(`source: { kind: 'user' }`,host 0.3.19 修正):早期版本用
204
207
  `{kind:'plugin'}` 会被 DSH 渲染成"上下文更新",看起来不像自己说的话;来源信息靠正文首行
205
- `From the editor: <file>:<行>` 保留。
208
+ `From the editor: <file>[:<行>]` 保留。
206
209
  - **全部只读**:桥不写文件、不改文档、不执行命令。agent 的写操作仍然全部走它自己的 `fs` 工具,
207
210
  桥只是"知道它写了什么"。
208
211
  - 编辑器侧的入口还有状态栏的 `$(plug) DSH`(连通时显示,点击打开日志),日志在输出面板
@@ -34,6 +34,7 @@ const { createDiffCache, describeChange } = require('./lib/diff-model.js');
34
34
  const {
35
35
  applyAnswers,
36
36
  createPanelState,
37
+ currentTurn,
37
38
  describeContext,
38
39
  panelPayload,
39
40
  pushQuestion,
@@ -379,8 +380,17 @@ async function pollOnce() {
379
380
  if ((result.events ?? []).length > 0) client.persist();
380
381
  // 回答同步:host 把 agent 的正文放在 answers 里(见 lib/bridge-answer.mjs),
381
382
  // 面板每趟轮询刷新一次 —— 不需要第二个定时器,也不需要流式协议。
382
- if (askPanel !== null && result.answers !== undefined) {
383
- if (applyAnswers(askPanel.state, result.answers, askPanel.state.sessionId)) refreshAskPanel();
383
+ if (askPanel !== null) {
384
+ if (result.answers === undefined) {
385
+ // 旧版 host(≤0.3.18)没有这个字段:此时面板会永远停在"正在回答…",必须说出原因。
386
+ askPanel.stalePolls = (askPanel.stalePolls ?? 0) + 1;
387
+ if (askPanel.stalePolls === 15 && askPanel.state.sessionId !== null && askPanel.state.status === 'thinking') {
388
+ failAskPanel('宿主没有回复同步能力(插件版本过旧?):请重启 dsh web 让 host 侧升级到 0.3.19 以上');
389
+ }
390
+ } else {
391
+ askPanel.stalePolls = 0;
392
+ if (applyAnswers(askPanel.state, result.answers, askPanel.state.sessionId)) refreshAskPanel();
393
+ }
384
394
  }
385
395
  }
386
396
 
@@ -409,19 +419,25 @@ function updateStatusBar() {
409
419
 
410
420
  // ---------------------------------------------------------------- 命令 / 提问面板
411
421
 
412
- /** 当前编辑器上下文(发送时现取一次:用户可以在面板开着的同时换选区)。 */
413
- function captureAskContext() {
422
+ /**
423
+ * 当前编辑器上下文(发送时现取一次:用户可以在面板开着的同时换选区)
424
+ *
425
+ * @param {'selection'|'file'} mode 提问意图:
426
+ * - `selection`(「针对选中内容提问」):有选区就带上**行区间 + 选区正文**;
427
+ * 没有选区时退化成**纯文件**(不带行号 —— 光标停在哪一行跟问题无关,行号只会误导 agent);
428
+ * - `file`(「针对当前文件提问」):**永远不带行号、不带选区**,只给文件路径。
429
+ */
430
+ function captureAskContext(mode) {
414
431
  const editor = vscode.window.activeTextEditor;
415
432
  if (editor === undefined || editor === null) return null;
416
433
  const doc = editor.document;
417
434
  const selection = editor.selection;
418
- const hasSelection = selection !== undefined && selection !== null && selection.isEmpty === false;
435
+ const hasSelection = mode === 'selection'
436
+ && selection !== undefined && selection !== null && selection.isEmpty === false;
419
437
  const selectedText = hasSelection ? doc.getText(selection) : '';
420
438
  return {
421
439
  file: doc.uri.scheme === 'file' ? doc.uri.fsPath : null,
422
- lineStart: hasSelection
423
- ? selection.start.line + 1
424
- : (doc.isDirty ? null : selection.active.line + 1),
440
+ lineStart: hasSelection ? selection.start.line + 1 : null,
425
441
  lineEnd: hasSelection ? selection.end.line + 1 : null,
426
442
  selection: selectedText === '' ? null : selectedText,
427
443
  languageId: doc.languageId ?? null,
@@ -441,10 +457,22 @@ function refreshAskPanel() {
441
457
  void askPanel.panel.webview.postMessage(payload);
442
458
  }
443
459
 
460
+ /** 面板进入错误态:状态行 + 当前轮都标上原因(绝不静默)。 */
461
+ function failAskPanel(message) {
462
+ if (askPanel === null) return;
463
+ askPanel.state.status = 'error';
464
+ askPanel.state.error = message;
465
+ const turn = currentTurn(askPanel.state);
466
+ if (turn !== null) turn.error = message;
467
+ log(message);
468
+ refreshAskPanel();
469
+ }
470
+
444
471
  /** 面板收到一条提问:投递到 DSH,并把这一轮放进状态里等回答。 */
445
472
  async function sendAskFromPanel(text) {
446
473
  if (askPanel === null || client === null) return;
447
- const context = captureAskContext() ?? askPanel.state.context;
474
+ // 用面板自己的意图(selection / file)取上下文:文件级提问永远不带行号。
475
+ const context = captureAskContext(askPanel.mode) ?? askPanel.state.context;
448
476
  const turn = pushQuestion(askPanel.state, text, context);
449
477
  refreshAskPanel();
450
478
  try {
@@ -480,9 +508,12 @@ async function sendAskFromPanel(text) {
480
508
  refreshAskPanel();
481
509
  }
482
510
 
483
- /** 打开(或聚焦)「问 DSH」面板。上下文只用来显示;真正的上下文在发送时现取。 */
484
- function openAskPanel(context) {
485
- const contextInfo = context ?? captureAskContext();
511
+ /**
512
+ * 打开(或聚焦)「问 DSH」面板。
513
+ * @param {'selection'|'file'} mode 提问意图(决定发送时带不带行号/选区),见 captureAskContext。
514
+ */
515
+ function openAskPanel(mode = 'selection') {
516
+ const contextInfo = captureAskContext(mode);
486
517
  if (askPanel === null) {
487
518
  const panel = vscode.window.createWebviewPanel(
488
519
  'dshAsk',
@@ -490,7 +521,7 @@ function openAskPanel(context) {
490
521
  { viewColumn: vscode.ViewColumn.Beside, preserveFocus: false },
491
522
  { enableScripts: true, retainContextWhenHidden: true },
492
523
  );
493
- askPanel = { panel, state: createPanelState() };
524
+ askPanel = { panel, state: createPanelState(), mode };
494
525
  panel.webview.html = renderPanelHtml({
495
526
  cspSource: panel.webview.cspSource,
496
527
  nonce: crypto.randomBytes(16).toString('base64url'),
@@ -511,22 +542,32 @@ function openAskPanel(context) {
511
542
  });
512
543
  }
513
544
  askPanel.state.context = contextInfo;
545
+ askPanel.mode = mode;
514
546
  askPanel.panel.reveal(vscode.ViewColumn.Beside, false);
515
547
  refreshAskPanel();
516
548
  }
517
549
 
518
550
  /** 选中内容 → DSH(编辑器→DSH 的主入口):打开面板并带上当前上下文。 */
519
551
  async function askAboutSelection() {
552
+ await openAskPanelFor('selection');
553
+ }
554
+
555
+ /** 整个文件 → DSH(不带选中、**不带行号**)。 */
556
+ async function askAboutFile() {
557
+ await openAskPanelFor('file');
558
+ }
559
+
560
+ /** 两个命令的公共前置检查(桥可用 + 有活动编辑器)。 */
561
+ async function openAskPanelFor(mode) {
520
562
  if (client === null || client.isDormant()) {
521
563
  vscode.window.showInformationMessage('编辑器桥未启用:请在 DSH 里打开 Code Server 标签后重试。');
522
564
  return;
523
565
  }
524
- openAskPanel(captureAskContext());
525
- }
526
-
527
- /** 整个文件 → DSH(不需要选中)。 */
528
- async function askAboutFile() {
529
- await askAboutSelection();
566
+ if (captureAskContext(mode) === null) {
567
+ vscode.window.showInformationMessage('没有活动的编辑器:请先打开一个文件。');
568
+ return;
569
+ }
570
+ openAskPanel(mode);
530
571
  }
531
572
 
532
573
  function showBridgeLog() {
@@ -2,7 +2,7 @@
2
2
  "name": "dshcs-editor-bridge",
3
3
  "displayName": "DSH Editor Bridge",
4
4
  "description": "只读地把编辑器状态(未保存缓冲区、诊断、活动选区)提供给 DSH,并让编辑器里的动作驱动 DSH 会话。由 dsh-code-server-app 插件安装,可禁用。",
5
- "version": "0.2.0",
5
+ "version": "0.2.2",
6
6
  "publisher": "dsh-code-server-app",
7
7
  "license": "MIT",
8
8
  "private": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-code-server-app",
3
- "version": "0.3.19",
3
+ "version": "0.3.21",
4
4
  "description": "VS Code (from a code-server release) inside DSH: a right-sidebar tab driven by the plugin's own launcher over the in-process VS Code server (lib/launcher.mjs). Since 0.3.0 the bundle also ships an editor bridge (assets/extensions/dshcs-editor-bridge): a read-only channel between the in-tree VS Code extension host and DSH, giving the agent what only the editor knows (unsaved buffers, language-server diagnostics, the active selection) and letting editor gestures drive the session. The tab claims DSH file addresses (dsh-resource://file/**) by file type (setting claimExtensions), so the product's own produced-file chips, delivered-file previews and inline prose mentions open in the workbench. The IDE is a resident surface moved with Element.moveBefore instead of being remounted, so switching sidebar tabs no longer reloads it. Opening the tab switches the right sidebar to fullscreen by default (setting fullscreenOnOpen). Following a workspace switch is lightweight: the workbench re-navigates with the new ?folder= and the IDE process is not restarted (since 0.2.12). Requires a DSH with the right-sidebar services (sidebarRightTabs/sidebarRight, >= 0.1.5-alpha.1); older DSH versions get a single upgrade notice on the settings page and no other UI. Two serving modes: loopback port (default) or same-origin mount on DSH's own webServer (/code-server, protected by ctx.connection.requestRejection). No code-server Node layer, no argon2, no C++ toolchain.",
5
5
  "homepage": "https://github.com/jinsiyu/dsh-code-server-app",
6
6
  "repository": {
@@ -3,7 +3,7 @@
3
3
  "vscodeVersion": "1.137.0",
4
4
  "productPath": "stable-b11dabdaca0d3369986975be285db92c8795cea5",
5
5
  "layout": "vscode-only",
6
- "preparedAt": "2026-09-13T06:39:47.464Z",
6
+ "preparedAt": "2026-09-13T07:25:18.352Z",
7
7
  "source": "registry",
8
8
  "node": "v24.21.0",
9
9
  "platform": "win32",