@xiaoso/dsh-tool-plus 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.mjs CHANGED
@@ -3,7 +3,7 @@ __installBunShim();
3
3
  import { n as fs_promises_shim_exports, t as exists } from "./fs-promises-shim-Bx0fpxuk.mjs";
4
4
  import { i as setRuntimeLogger, n as systemChromiumCandidatesForTest, r as runtimeLogger } from "./launch-BmgEUycu.mjs";
5
5
  import { $ as peekFile, A as formatAge, C as error, F as $envpos, I as $flag, M as formatCount, P as $env, Q as isProbablyBinary, S as debug, T as warn, U as getAutoQaDbPath, V as VERSION, X as getRemoteDir, Y as getPuppeteerDir, b as isEnotdir, c as combineSignals, d as $which, j as formatBytes$1, k as installBunShim, l as exec, p as readImageMetadata, q as getInstallId, tt as untilAborted, u as render, v as hasFsCode, y as isEnoent } from "./src-BcD0_rQR.mjs";
6
- import { C as truncateToWidth$1, S as replaceTabs, _ as formatCodeFrameLine, a as fetchBinary, b as LRUCache, c as getParallelExtractContent, d as convertFileWithMarkit, f as Settings, g as capParseErrors, h as OMP_DEFAULTS, i as convertWithMarkit, l as ensureTool, m as settings, o as extractWithParallel, p as isSettingsInitialized, s as findParallelApiKey, u as CONVERTIBLE_EXTENSIONS, v as formatParseErrors, x as padding, y as shortenPath } from "./utils-DeT1yYiQ.mjs";
6
+ import { C as truncateToWidth$1, S as replaceTabs, _ as formatCodeFrameLine, a as fetchBinary, b as LRUCache, c as getParallelExtractContent, d as convertFileWithMarkit, f as Settings, g as capParseErrors, h as OMP_DEFAULTS, i as convertWithMarkit, l as ensureTool, m as settings, o as extractWithParallel, p as isSettingsInitialized, s as findParallelApiKey, u as CONVERTIBLE_EXTENSIONS, v as formatParseErrors, x as padding, y as shortenPath } from "./utils-APrc-TBB.mjs";
7
7
  import { t as sanitizeText } from "./sanitize-text-CfcXzw5X.mjs";
8
8
  import { n as isRecord$2 } from "./type-guards-B9VVjRDK.mjs";
9
9
  import { n as ToolError, r as throwIfAborted, t as ToolAbortError } from "./tool-errors-DoyxivAR.mjs";
@@ -14858,7 +14858,7 @@ let specialHandlersPromise;
14858
14858
  * requires a special handler, so we keep them out of the cold-startup graph.
14859
14859
  */
14860
14860
  function loadSpecialHandlers() {
14861
- specialHandlersPromise ??= import("./scrapers-D145Jmdq.mjs").then((m) => m.specialHandlers);
14861
+ specialHandlersPromise ??= import("./scrapers-CE_qK1yk.mjs").then((m) => m.specialHandlers);
14862
14862
  return specialHandlersPromise;
14863
14863
  }
14864
14864
  /**
@@ -3,7 +3,7 @@ __installBunShim();
3
3
  import { n as fs_promises_shim_exports } from "./fs-promises-shim-Bx0fpxuk.mjs";
4
4
  import { B as USER_AGENT, G as getDocsRsCacheDir, N as formatNumber, P as $env, T as warn, c as combineSignals, j as formatBytes, l as exec, s as Snowflake, x as parseFrontmatter, y as isEnoent } from "./src-BcD0_rQR.mjs";
5
5
  import { V as tryParseJson } from "./utils-Cp2Mxf_U.mjs";
6
- import { a as fetchBinary, c as getParallelExtractContent, i as convertWithMarkit, l as ensureTool, m as settings, n as asRecord, o as extractWithParallel, r as asString, s as findParallelApiKey, t as asNumber } from "./utils-DeT1yYiQ.mjs";
6
+ import { a as fetchBinary, c as getParallelExtractContent, i as convertWithMarkit, l as ensureTool, m as settings, n as asRecord, o as extractWithParallel, r as asString, s as findParallelApiKey, t as asNumber } from "./utils-APrc-TBB.mjs";
7
7
  import { n as isRecord } from "./type-guards-B9VVjRDK.mjs";
8
8
  import { r as throwIfAborted, t as ToolAbortError } from "./tool-errors-DoyxivAR.mjs";
9
9
  import { c as getLocalizedText, d as looksLikeHtml, i as decodeHtmlEntities, l as htmlToBasicMarkdown, o as formatIsoDate, r as buildResult, s as formatMediaDuration, u as loadPage } from "./types-DX_bvuus.mjs";
package/lib/trash-cli.mjs CHANGED
@@ -1,5 +1,20 @@
1
1
  import * as fs from "node:fs";
2
2
  //#region src/tools/bash/trash-cli.ts
3
+ /**
4
+ * rmSafe: rm 命令的回收站重定义核心。
5
+ *
6
+ * 参数解析与行为语义对齐 GNU coreutils rm(tests/rm/ 用例移植),差异:
7
+ * - 删除目标 = 系统回收站(trash 包),非永久删除;
8
+ * - `-i`/`-I`/`--interactive[=WHEN]` 接受但忽略交互(直接进回收站);
9
+ * - verbose 只输出顶层项(trash 是原子移动,不递归输出子项)。
10
+ *
11
+ * 保护语义(r-root / r-4 移植):默认 --preserve-root 拒绝 `/` 及其同义词
12
+ * (`//`、`///`、realpath 后是根目录的路径);拒绝 `.` / `..` 结尾的路径。
13
+ *
14
+ * 本模块零外部依赖(trash 包在 trash-cli-main.ts 入口动态加载),
15
+ * 便于单测注入 fake trash。
16
+ * @module @xiaoso/dsh-tool-plus/bash/trash-cli
17
+ */
3
18
  const SHORT_OPTIONS = {
4
19
  r: "recursive",
5
20
  R: "recursive",
@@ -195,6 +210,42 @@ async function isRootPath(p, deps) {
195
210
  const root = await deps.stat("/");
196
211
  return root !== null && st.dev === root.dev && st.ino === root.ino;
197
212
  }
213
+ /** 探测目标名后缀(rename 探测临时名)。 */
214
+ const PROBE_SUFFIX = ".dsh-trash-probe";
215
+ /** 从 unknown 错误里取 errno 码(边界解析)。 */
216
+ function errnoCode(err) {
217
+ if (typeof err !== "object" || err === null) return void 0;
218
+ const code = err.code;
219
+ return typeof code === "string" ? code : void 0;
220
+ }
221
+ /** rename 探测:移到同目录临时名再改回;不改内容,返回 errno 码或 null(可移动)。 */
222
+ async function defaultProbeRename(from, to) {
223
+ try {
224
+ await fs.promises.rename(from, to);
225
+ } catch (err) {
226
+ return errnoCode(err) ?? "UNKNOWN";
227
+ }
228
+ try {
229
+ await fs.promises.rename(to, from);
230
+ return null;
231
+ } catch {
232
+ return "PROBE_STUCK";
233
+ }
234
+ }
235
+ /**
236
+ * rename 探测结果 → 可读原因(null = 无结论)。
237
+ *
238
+ * trash 的 windows-trash.exe 失败时把原因吞成 0x8000FFFF、stderr 为空,
239
+ * 所以这里靠 rename 探测拿文件系统的真实回答;不同 errno 必须分开报,
240
+ * 权限不足不是“被占用”。
241
+ */
242
+ function describeProbeCode(code) {
243
+ if (code === null) return null;
244
+ if (code === "ENOENT" || code === "ENOTDIR") return "no longer exists (removed by another process?)";
245
+ if (code === "EBUSY" || code === "ENOTEMPTY" || code === "PROBE_STUCK") return "file is locked or cannot be moved by this process (close programs using it and retry)";
246
+ if (code === "EPERM" || code === "EACCES") return "permission denied (read-only file or restricted directory)";
247
+ return null;
248
+ }
198
249
  /**
199
250
  * 执行一次 rm 语义的回收站删除。
200
251
  *
@@ -256,8 +307,18 @@ async function runTrashCli(argv, deps) {
256
307
  if (items.length > 0) try {
257
308
  await deps.trash(items.map((item) => item.path));
258
309
  } catch (err) {
259
- deps.stderr(`rm: cannot remove '${items[0].authored}': ${errorMessage(err)}`);
260
- failed = true;
310
+ if (process.platform !== "win32") {
311
+ deps.stderr(`rm: cannot remove '${items[0].authored}': ${errorMessage(err)}`);
312
+ failed = true;
313
+ } else {
314
+ const probe = deps.probeRename ?? defaultProbeRename;
315
+ for (const item of items) {
316
+ const code = await probe(item.path, `${item.path}${PROBE_SUFFIX}`);
317
+ if (code === "ENOENT" || code === "ENOTDIR") continue;
318
+ deps.stderr(`rm: cannot remove '${item.authored}': ${describeProbeCode(code) ?? errorMessage(err)}`);
319
+ failed = true;
320
+ }
321
+ }
261
322
  }
262
323
  if (verbose && !failed) for (const { authored, isDir } of items) deps.stdout(isDir ? `removed directory '${normalizeTrailingSlash(authored)}'` : `removed '${authored}'`);
263
324
  deps.exit(failed ? 1 : 0);
@@ -7202,7 +7202,7 @@ const settings = {
7202
7202
  };
7203
7203
  //#endregion
7204
7204
  //#region package.json
7205
- var version = "0.1.4";
7205
+ var version = "0.1.5";
7206
7206
  /** `.tmp` files older than this are treated as orphaned writes and swept. */
7207
7207
  const TMP_ORPHAN_MAX_AGE_MS = 3e5;
7208
7208
  function markitConversionCacheKey(bytes, extension) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xiaoso/dsh-tool-plus",
3
3
  "description": "Oh My Pi bash runtime ported as a deepseek-harness tool plugin: persistent shell session, output minimizer, managed background jobs, command interception",
4
- "version": "0.1.4",
4
+ "version": "0.1.5",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "deepseek-harness",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiaoso/dsh-tool-plus-presets",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Agent-preset installer for dsh-tool-plus: installs the standard / PTC enhanced preset templates into a DeepSeek Harness home.",
5
5
  "license": "MIT",
6
6
  "keywords": [