dsh-rewind-plugin 0.19.0 → 0.19.2

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/client.js CHANGED
@@ -1576,11 +1576,54 @@ async function candidatesOverRpc(connection, sessionId) {
1576
1576
  }
1577
1577
 
1578
1578
  // src/client/build-info.ts
1579
- var PLUGIN_VERSION = true ? "0.19.0" : "dev";
1579
+ var PLUGIN_VERSION = true ? "0.19.2" : "dev";
1580
1580
  var PLUGIN_PACKAGE = "dsh-rewind-plugin";
1581
- var BUILD_HASH = true ? "bccc8c9b" : "dev";
1581
+ var BUILD_HASH = true ? "cc2bb5b8" : "dev";
1582
1582
 
1583
1583
  // src/client/locales.ts
1584
+ var en = {
1585
+ "button.aria": "Rewind to this message",
1586
+ "button.title": "Rewind",
1587
+ "button.retract.aria": "Rewind to this pending message",
1588
+ "button.retract.title": "Rewind",
1589
+ "popover.title": "Rewind to this message",
1590
+ "popover.noText": "(no text)",
1591
+ "popover.retract.title": "Rewind to this pending message",
1592
+ "popover.retract.target": "Pending \xB7 {preview}",
1593
+ "popover.retract.hint": "Retracts this pending message and the ones after it, without interrupting the run",
1594
+ "popover.retract.confirm": "Confirm rewind",
1595
+ "popover.chat": "Rewind conversation only",
1596
+ "popover.chat.hint": "Context only; workspace untouched",
1597
+ "popover.both": "Rewind conversation and files",
1598
+ "popover.both.hint": "Context and restore workspace files",
1599
+ "popover.checking": "Checking for file changes\u2026",
1600
+ "popover.noChanges": "No restorable file changes",
1601
+ "popover.backupDisabled": "Snapshots off; the restore may be incomplete",
1602
+ "popover.cancel": "Cancel",
1603
+ "popover.impact.loading": "Fetching impact list\u2026",
1604
+ "popover.impact.failed": "Could not fetch the impact list: {message}",
1605
+ "popover.impact.none": "No tracked file changes after the target; nothing to restore.",
1606
+ "popover.impact.restore": "Restore {path}",
1607
+ "popover.impact.delete": "Delete {path}",
1608
+ "popover.confirm": "Confirm rewind",
1609
+ "popover.back": "Back",
1610
+ "backup.title": "Snapshot backups",
1611
+ "backup.on": "When on, file snapshots are created automatically for file restore.",
1612
+ "backup.off": "When off, no file snapshots are created; file changes made while off cannot be restored.",
1613
+ "cleanup.auto": "Auto cleanup",
1614
+ "cleanup.auto.on": "When enabled, session snapshots idle past the cutoff are cleaned automatically.",
1615
+ "cleanup.auto.off": "When off, snapshots are not cleaned automatically.",
1616
+ "cleanup.maxAge": "Idle time (days)",
1617
+ "cleanup.maxAge.hint": "Snapshot backups of sessions idle longer than this many days are cleaned.",
1618
+ "cleanup.invalid": "Enter a positive integer, or leave blank to use the default",
1619
+ "cleanup.overridden": "Overridden",
1620
+ "cleanup.reset": "Reset to default",
1621
+ "cleanup.save": "Save",
1622
+ "cleanup.saving": "Saving\u2026",
1623
+ "cleanup.saveFailed": "The deployment did not accept these values; they were left for you to correct",
1624
+ "cleanup.readonly": "This deployment stores settings read-only",
1625
+ "cleanup.unavailable": "This plugin is not loaded, so it cannot be configured right now"
1626
+ };
1584
1627
  var zh = {
1585
1628
  "button.aria": "\u56DE\u9000\u5230\u6B64\u6D88\u606F",
1586
1629
  "button.title": "\u56DE\u9000",
@@ -1624,49 +1667,50 @@ var zh = {
1624
1667
  "cleanup.readonly": "\u672C\u90E8\u7F72\u7684\u8BBE\u7F6E\u4E3A\u53EA\u8BFB",
1625
1668
  "cleanup.unavailable": "\u8BE5\u63D2\u4EF6\u5F53\u524D\u672A\u52A0\u8F7D\uFF0C\u6682\u65F6\u65E0\u6CD5\u914D\u7F6E"
1626
1669
  };
1627
- var en = {
1628
- "button.aria": "Rewind to this message",
1629
- "button.title": "Rewind",
1630
- "button.retract.aria": "Rewind to this pending message",
1631
- "button.retract.title": "Rewind",
1632
- "popover.title": "Rewind to this message",
1633
- "popover.noText": "(no text)",
1634
- "popover.retract.title": "Rewind to this pending message",
1635
- "popover.retract.target": "Pending \xB7 {preview}",
1636
- "popover.retract.hint": "Retracts this pending message and the ones after it, without interrupting the run",
1637
- "popover.retract.confirm": "Confirm rewind",
1638
- "popover.chat": "Rewind conversation only",
1639
- "popover.chat.hint": "Context only; workspace untouched",
1640
- "popover.both": "Rewind conversation and files",
1641
- "popover.both.hint": "Context and restore workspace files",
1642
- "popover.checking": "Checking for file changes\u2026",
1643
- "popover.noChanges": "No restorable file changes",
1644
- "popover.backupDisabled": "Snapshots off; the restore may be incomplete",
1645
- "popover.cancel": "Cancel",
1646
- "popover.impact.loading": "Fetching impact list\u2026",
1647
- "popover.impact.failed": "Could not fetch the impact list: {message}",
1648
- "popover.impact.none": "No tracked file changes after the target; nothing to restore.",
1649
- "popover.impact.restore": "Restore {path}",
1650
- "popover.impact.delete": "Delete {path}",
1651
- "popover.confirm": "Confirm rewind",
1652
- "popover.back": "Back",
1653
- "backup.title": "Snapshot backups",
1654
- "backup.on": "When on, file snapshots are created automatically for file restore.",
1655
- "backup.off": "When off, no file snapshots are created; file changes made while off cannot be restored.",
1656
- "cleanup.auto": "Auto cleanup",
1657
- "cleanup.auto.on": "When enabled, session snapshots idle past the cutoff are cleaned automatically.",
1658
- "cleanup.auto.off": "When off, snapshots are not cleaned automatically.",
1659
- "cleanup.maxAge": "Idle time (days)",
1660
- "cleanup.maxAge.hint": "Snapshot backups of sessions idle longer than this many days are cleaned.",
1661
- "cleanup.invalid": "Enter a positive integer, or leave blank to use the default",
1662
- "cleanup.overridden": "Overridden",
1663
- "cleanup.reset": "Reset to default",
1664
- "cleanup.save": "Save",
1665
- "cleanup.saving": "Saving\u2026",
1666
- "cleanup.saveFailed": "The deployment did not accept these values; they were left for you to correct",
1667
- "cleanup.readonly": "This deployment stores settings read-only",
1668
- "cleanup.unavailable": "This plugin is not loaded, so it cannot be configured right now"
1670
+ var ja = {
1671
+ "button.aria": "\u3053\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u307E\u3067\u5DFB\u304D\u623B\u3059",
1672
+ "button.title": "\u5DFB\u304D\u623B\u3057",
1673
+ "button.retract.aria": "\u3053\u306E\u4FDD\u7559\u4E2D\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u307E\u3067\u5DFB\u304D\u623B\u3059",
1674
+ "button.retract.title": "\u5DFB\u304D\u623B\u3057",
1675
+ "popover.title": "\u3053\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u307E\u3067\u5DFB\u304D\u623B\u3059",
1676
+ "popover.noText": "\uFF08\u30C6\u30AD\u30B9\u30C8\u306A\u3057\uFF09",
1677
+ "popover.retract.title": "\u3053\u306E\u4FDD\u7559\u4E2D\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u307E\u3067\u5DFB\u304D\u623B\u3059",
1678
+ "popover.retract.target": "\u4FDD\u7559\u4E2D \xB7 {preview}",
1679
+ "popover.retract.hint": "\u3053\u306E\u4FDD\u7559\u4E2D\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u3068\u305D\u308C\u4EE5\u964D\u3092\u64A4\u56DE\u3057\u307E\u3059\u3002\u73FE\u5728\u306E\u751F\u6210\u306F\u4E2D\u65AD\u3057\u307E\u305B\u3093",
1680
+ "popover.retract.confirm": "\u5DFB\u304D\u623B\u3057\u3092\u5B9F\u884C",
1681
+ "popover.chat": "\u4F1A\u8A71\u306E\u307F\u5DFB\u304D\u623B\u3059",
1682
+ "popover.chat.hint": "\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306E\u307F\u5BFE\u8C61\u3067\u3001\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306F\u5909\u66F4\u3057\u307E\u305B\u3093",
1683
+ "popover.both": "\u4F1A\u8A71\u3068\u30D5\u30A1\u30A4\u30EB\u3092\u5DFB\u304D\u623B\u3059",
1684
+ "popover.both.hint": "\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3092\u5DFB\u304D\u623B\u3057\u3001\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u5FA9\u5143\u3057\u307E\u3059",
1685
+ "popover.checking": "\u30D5\u30A1\u30A4\u30EB\u306E\u5909\u66F4\u3092\u78BA\u8A8D\u4E2D\u2026",
1686
+ "popover.noChanges": "\u5FA9\u5143\u3067\u304D\u308B\u30D5\u30A1\u30A4\u30EB\u306E\u5909\u66F4\u306F\u3042\u308A\u307E\u305B\u3093",
1687
+ "popover.backupDisabled": "\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u304C\u7121\u52B9\u306A\u305F\u3081\u3001\u5FA9\u5143\u304C\u4E0D\u5B8C\u5168\u306B\u306A\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059",
1688
+ "popover.cancel": "\u30AD\u30E3\u30F3\u30BB\u30EB",
1689
+ "popover.impact.loading": "\u5F71\u97FF\u30EA\u30B9\u30C8\u3092\u53D6\u5F97\u4E2D\u2026",
1690
+ "popover.impact.failed": "\u5F71\u97FF\u30EA\u30B9\u30C8\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{message}",
1691
+ "popover.impact.none": "\u5BFE\u8C61\u3088\u308A\u5F8C\u306B\u8FFD\u8DE1\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u5909\u66F4\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u5FA9\u5143\u3059\u308B\u3082\u306E\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
1692
+ "popover.impact.restore": "{path} \u3092\u5FA9\u5143",
1693
+ "popover.impact.delete": "{path} \u3092\u524A\u9664",
1694
+ "popover.confirm": "\u5DFB\u304D\u623B\u3057\u3092\u5B9F\u884C",
1695
+ "popover.back": "\u623B\u308B",
1696
+ "backup.title": "\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306E\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7",
1697
+ "backup.on": "\u6709\u52B9\u306B\u3059\u308B\u3068\u3001\u30D5\u30A1\u30A4\u30EB\u5FA9\u5143\u7528\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u304C\u81EA\u52D5\u3067\u4F5C\u6210\u3055\u308C\u307E\u3059\u3002",
1698
+ "backup.off": "\u7121\u52B9\u306B\u3059\u308B\u3068\u3001\u30D5\u30A1\u30A4\u30EB\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306F\u4F5C\u6210\u3055\u308C\u307E\u305B\u3093\u3002\u7121\u52B9\u306A\u9593\u306E\u30D5\u30A1\u30A4\u30EB\u5909\u66F4\u306F\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093\u3002",
1699
+ "cleanup.auto": "\u81EA\u52D5\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7",
1700
+ "cleanup.auto.on": "\u6709\u52B9\u306B\u3059\u308B\u3068\u3001\u3057\u304D\u3044\u5024\u3092\u8D85\u3048\u3066\u30A2\u30A4\u30C9\u30EB\u72B6\u614B\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u304C\u81EA\u52D5\u3067\u524A\u9664\u3055\u308C\u307E\u3059\u3002",
1701
+ "cleanup.auto.off": "\u7121\u52B9\u306B\u3059\u308B\u3068\u3001\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306F\u81EA\u52D5\u3067\u524A\u9664\u3055\u308C\u307E\u305B\u3093\u3002",
1702
+ "cleanup.maxAge": "\u30A2\u30A4\u30C9\u30EB\u6642\u9593\uFF08\u65E5\uFF09",
1703
+ "cleanup.maxAge.hint": "\u3053\u306E\u65E5\u6570\u3092\u8D85\u3048\u3066\u30A2\u30A4\u30C9\u30EB\u72B6\u614B\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u304C\u524A\u9664\u3055\u308C\u307E\u3059\u3002",
1704
+ "cleanup.invalid": "\u6B63\u306E\u6574\u6570\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u7A7A\u6B04\u306E\u5834\u5408\u306F\u65E2\u5B9A\u5024\u3092\u4F7F\u3044\u307E\u3059",
1705
+ "cleanup.overridden": "\u4E0A\u66F8\u304D\u6E08\u307F",
1706
+ "cleanup.reset": "\u65E2\u5B9A\u5024\u306B\u623B\u3059",
1707
+ "cleanup.save": "\u4FDD\u5B58",
1708
+ "cleanup.saving": "\u4FDD\u5B58\u4E2D\u2026",
1709
+ "cleanup.saveFailed": "\u3053\u306E\u30C7\u30D7\u30ED\u30A4\u30E1\u30F3\u30C8\u3067\u306F\u5024\u304C\u53D7\u3051\u4ED8\u3051\u3089\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u4FEE\u6B63\u3067\u304D\u308B\u3088\u3046\u5165\u529B\u306F\u4FDD\u6301\u3055\u308C\u3066\u3044\u307E\u3059",
1710
+ "cleanup.readonly": "\u3053\u306E\u30C7\u30D7\u30ED\u30A4\u30E1\u30F3\u30C8\u3067\u306F\u8A2D\u5B9A\u304C\u8AAD\u307F\u53D6\u308A\u5C02\u7528\u3067\u3059",
1711
+ "cleanup.unavailable": "\u3053\u306E\u30D7\u30E9\u30B0\u30A4\u30F3\u306F\u73FE\u5728\u8AAD\u307F\u8FBC\u307E\u308C\u3066\u3044\u306A\u3044\u305F\u3081\u3001\u8A2D\u5B9A\u3067\u304D\u307E\u305B\u3093"
1669
1712
  };
1713
+ var CLIENT_DICTS = { en, zh, ja };
1670
1714
 
1671
1715
  // src/client/settings-card.tsx
1672
1716
  var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
@@ -1797,7 +1841,7 @@ var COMPOSER_EDITABLE_SELECTOR2 = "[data-composer-input]";
1797
1841
  function apply(ctx) {
1798
1842
  rewindLog.info("boot", `loaded v${PLUGIN_VERSION} (build ${BUILD_HASH})`);
1799
1843
  ctx.effect(function* () {
1800
- yield ctx.locale.register(NS2, { zh, en });
1844
+ yield ctx.locale.register(NS2, CLIENT_DICTS);
1801
1845
  const t = ctx.locale.bind(NS2);
1802
1846
  const connection = ctx.get("connection");
1803
1847
  registerPreviewCall((sessionId, seq) => previewOverRpc(connection, sessionId, seq));
package/lib/index.js CHANGED
@@ -4,10 +4,6 @@ import { copyFile as copyFile2, rm as rm2, stat as stat2, unlink } from "node:fs
4
4
  import z from "@deepseek-ai/schemastery";
5
5
 
6
6
  // src/locales.ts
7
- function preferredLocale(preference) {
8
- if (typeof preference !== "string") return "en";
9
- return preference.toLowerCase().split("-")[0] === "zh" ? "zh" : "en";
10
- }
11
7
  var en = {
12
8
  "plan.skip": " not restored: {path} ({reason})",
13
9
  "skipReason.oversized": "over the {limit} backup limit, so the recorded state predates untracked edits",
@@ -100,7 +96,64 @@ var zh = {
100
96
  "cleanup.clearFailed": "\u65E0\u6CD5\u6E05\u9664\u4F1A\u8BDD {sessionId}\uFF1A{detail}\u3002",
101
97
  "cleanup.usage": "\u7528\u6CD5\uFF1A\n /snapshot-auto-cleanup \u67E5\u770B\u72B6\u6001\n /snapshot-auto-cleanup on|off \u5F00\u542F/\u5173\u95ED\u81EA\u52A8\u6E05\u7406\n /snapshot-auto-cleanup max-age <\u5929\u6570> \u8BBE\u7F6E\u5931\u6D3B\u9608\u503C\uFF08\u5929\uFF09\n /snapshot-auto-cleanup run [--apply] \u9884\u6F14\uFF0C\u6216\u52A0 --apply \u6267\u884C\n /snapshot-auto-cleanup run --current [--apply] \u9884\u6F14/\u6E05\u9664\u672C\u4F1A\u8BDD\u5FEB\u7167"
102
98
  };
103
- var HOST_DICTS = { en, zh };
99
+ var ja = {
100
+ "plan.skip": " \u5FA9\u5143\u5BFE\u8C61\u5916\uFF1A{path}\uFF08{reason}\uFF09",
101
+ "skipReason.oversized": "{limit} \u306E\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u4E0A\u9650\u3092\u8D85\u3048\u3066\u3044\u308B\u305F\u3081\u3001\u8A18\u9332\u3055\u308C\u305F\u72B6\u614B\u306F\u672A\u8FFD\u8DE1\u306E\u7DE8\u96C6\u3088\u308A\u524D\u306E\u3082\u306E\u3067\u3059",
102
+ "error.invalidTarget": '\u5BFE\u8C61 "{raw}" \u3092\u89E3\u6790\u3067\u304D\u307E\u305B\u3093\uFF08<index> \u307E\u305F\u306F @<seq> \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF09',
103
+ "sep.list": "\u3001",
104
+ "sep.clause": "\uFF1B",
105
+ "failures.suffix": "\uFF1B{count} \u4EF6\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{list}",
106
+ "failures.item": "{path}\uFF08{message}\uFF09",
107
+ "inflight": "\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u3067\u306F\u65E2\u306B\u5DFB\u304D\u623B\u3057\u304C\u5B9F\u884C\u4E2D\u3067\u3059\u3002\u304A\u5F85\u3061\u304F\u3060\u3055\u3044\u3002",
108
+ "stopFailed": "\u5B9F\u884C\u4E2D\u306E\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u3092\u505C\u6B62\u3067\u304D\u306A\u304B\u3063\u305F\u305F\u3081\u3001\u5DFB\u304D\u623B\u3057\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",
109
+ "cancelled": "\u5DFB\u304D\u623B\u3057\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F\u3002",
110
+ "failed": "\u5DFB\u304D\u623B\u3057\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF1A{error}\u3002\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u5909\u66F4\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",
111
+ "restore.count": "{count} \u4EF6\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u5FA9\u5143\u3057\u307E\u3057\u305F",
112
+ "delete.count": "{count} \u4EF6\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3057\u307E\u3057\u305F",
113
+ "skip.count": "{count} \u4EF6\u306E\u30D1\u30B9\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F",
114
+ "noRestorable": "\uFF1B\u5BFE\u8C61\u3088\u308A\u5F8C\u306B\u5FA9\u5143\u3067\u304D\u308B\u66F8\u8FBC\u307F\u7CFB\u306E\u5909\u66F4\u306F\u3042\u308A\u307E\u305B\u3093",
115
+ "backupOff": "\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306E\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u304C\u7121\u52B9\u306A\u305F\u3081\u3001\u5FA9\u5143\u304C\u4E0D\u5B8C\u5168\u306B\u306A\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059",
116
+ "storeUnsupported": "\u30D5\u30A1\u30A4\u30EB\u3092\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093\uFF1A\u3053\u308C\u3089\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306F\u3001\u3053\u306E\u30D7\u30E9\u30B0\u30A4\u30F3\u304C\u7406\u89E3\u3067\u304D\u308B\u5F62\u5F0F\u3088\u308A\u65B0\u3057\u3044\u4FDD\u5B58\u5F62\u5F0F\uFF08v{version}\uFF09\u3092\u4F7F\u3063\u3066\u3044\u307E\u3059\u3002\u4F55\u3082\u5909\u66F4\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30D7\u30E9\u30B0\u30A4\u30F3\u3092\u66F4\u65B0\u3059\u308B\u304B\u3001\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u3092\u6D88\u53BB\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
117
+ "success": "seq {targetSeq} \u3068\u305D\u308C\u4EE5\u964D\u3092\u64A4\u56DE\u3057\u307E\u3057\u305F\uFF08\u4F1A\u8A71\u306F\u4EE5\u524D\u306E\u72B6\u614B\u306B\u623B\u308A\u307E\u3057\u305F\uFF09{restore}\u3002",
118
+ "noUserMessages": "\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306B\u306F\u307E\u3060\u5DFB\u304D\u623B\u3057\u3067\u304D\u308B\u30E6\u30FC\u30B6\u30FC\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u3042\u308A\u307E\u305B\u3093\u3002",
119
+ "command.description": "\u4F1A\u8A71\u3084\u30D5\u30A1\u30A4\u30EB\u3092\u4EE5\u524D\u306E\u6642\u70B9\u307E\u3067\u5DFB\u304D\u623B\u3057\u307E\u3059",
120
+ "command.undoDescription": "/rewind \u306E\u30A8\u30A4\u30EA\u30A2\u30B9",
121
+ "engine.description": "dsh-rewind \u306E\u5185\u90E8\u30B3\u30DE\u30F3\u30C9",
122
+ "engine.rejected": "\u5185\u90E8\u30B3\u30DE\u30F3\u30C9\u3067\u3059\u3002/rewind \u307E\u305F\u306F /undo \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002",
123
+ "engine.inputHint": "@<seq> chat|both",
124
+ "cleanup.description": "\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u306E\u81EA\u52D5\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u3092\u7BA1\u7406\u3057\u307E\u3059",
125
+ "cleanup.inputHint": "on | off | max-age <\u65E5\u6570> | run [--apply] [--current]",
126
+ "cleanup.status": "\u81EA\u52D5\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\uFF1A{state}\u3002\u6700\u5927\u4FDD\u6301\u671F\u9593\uFF1A{days} \u65E5\u3002",
127
+ "cleanup.enabled": "\u6709\u52B9",
128
+ "cleanup.disabled": "\u7121\u52B9",
129
+ "cleanup.onOk": "\u81EA\u52D5\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u3092\u6709\u52B9\u306B\u3057\u307E\u3057\u305F\u3002",
130
+ "cleanup.offOk": "\u81EA\u52D5\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u3092\u7121\u52B9\u306B\u3057\u307E\u3057\u305F \u2014 \u3059\u3079\u3066\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u304C\u4FDD\u6301\u3055\u308C\u307E\u3059\u3002",
131
+ "cleanup.maxAgeOk": "\u81EA\u52D5\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306E\u6700\u5927\u4FDD\u6301\u671F\u9593\u3092 {days} \u65E5\u306B\u8A2D\u5B9A\u3057\u307E\u3057\u305F\u3002",
132
+ "cleanup.cfgInvalid": '\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u8A2D\u5B9A\u304C\u7121\u52B9\u3067\u3059\uFF1A{detail}\u3002\u4F55\u3082\u5B9F\u884C\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"on|off|max-age" \u3067\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8\u3057\u3066\u304F\u3060\u3055\u3044\u3002',
133
+ "cleanup.saveFailed": "\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{detail}\u3002",
134
+ "cleanup.runDry": "\u30C9\u30E9\u30A4\u30E9\u30F3\uFF1A{deleted} \u4EF6\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u3092\u524A\u9664\u3057\u3001{freed} \u30D0\u30A4\u30C8\u3092\u89E3\u653E\u3057\u307E\u3059\u3002\u5B9F\u969B\u306B\u524A\u9664\u3059\u308B\u306B\u306F --apply \u3092\u4ED8\u3051\u3066\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
135
+ "cleanup.runApply": "{deleted} \u4EF6\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u3092\u524A\u9664\u3057\u3001{freed} \u30D0\u30A4\u30C8\u3092\u89E3\u653E\u3057\u307E\u3057\u305F\u3002{kept} \u4EF6\u3092\u4FDD\u6301\u3057\u3001\u6B8B\u308A\u306F {remaining} \u30D0\u30A4\u30C8\u3067\u3059\u3002",
136
+ "cleanup.runFailed": "\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF1A{detail}\u3002",
137
+ "cleanup.skipped": "\uFF08\u30A2\u30AF\u30C6\u30A3\u30D6\u306A\u30BB\u30C3\u30B7\u30E7\u30F3 {skipped} \u4EF6\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F\u3002\uFF09",
138
+ "cleanup.clearDry": "\u30C9\u30E9\u30A4\u30E9\u30F3\uFF1A\u73FE\u5728\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8 {entries} \u4EF6\u3092\u6D88\u53BB\u3057\u3001{bytes} \u30D0\u30A4\u30C8\u3092\u89E3\u653E\u3057\u307E\u3059\u3002\u5B9F\u969B\u306B\u524A\u9664\u3059\u308B\u306B\u306F --apply \u3092\u4ED8\u3051\u3066\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
139
+ "cleanup.clearApply": "\u73FE\u5728\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8 {entries} \u4EF6\u3092\u6D88\u53BB\u3057\u3001{bytes} \u30D0\u30A4\u30C8\u3092\u89E3\u653E\u3057\u307E\u3057\u305F\u3002\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u73FE\u5728\u306E\u72B6\u614B\u304B\u3089\u65B0\u3057\u304F\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u3092\u8A18\u9332\u3057\u307E\u3059\u3002",
140
+ "cleanup.clearActive": "\u30BB\u30C3\u30B7\u30E7\u30F3 {sessionId} \u3092\u6D88\u53BB\u3067\u304D\u307E\u305B\u3093\uFF1A\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u307E\u3060\u5B9F\u884C\u4E2D\u3067\u3001\u505C\u6B62\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30A2\u30A4\u30C9\u30EB\u72B6\u614B\u306B\u306A\u3063\u3066\u304B\u3089\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",
141
+ "cleanup.clearCancelled": "\u6D88\u53BB\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F\u3002",
142
+ "cleanup.clearFailed": "\u30BB\u30C3\u30B7\u30E7\u30F3 {sessionId} \u3092\u6D88\u53BB\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{detail}\u3002",
143
+ "cleanup.usage": "\u4F7F\u3044\u65B9\uFF1A\n /snapshot-auto-cleanup \u72B6\u614B\u3092\u8868\u793A\n /snapshot-auto-cleanup on|off \u81EA\u52D5\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306E\u6709\u52B9/\u7121\u52B9\n /snapshot-auto-cleanup max-age <\u65E5\u6570> \u30A2\u30A4\u30C9\u30EB\u3057\u304D\u3044\u5024\u3092\u8A2D\u5B9A\n /snapshot-auto-cleanup run [--apply] \u30C9\u30E9\u30A4\u30E9\u30F3\u3001\u307E\u305F\u306F --apply \u3067\u5B9F\u884C\n /snapshot-auto-cleanup run --current [--apply] \u30C9\u30E9\u30A4\u30E9\u30F3\uFF0F\u73FE\u5728\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u3092\u6D88\u53BB"
144
+ };
145
+ var HOST_DICTS = { en, zh, ja };
146
+ var DEFAULT_HOST_LOCALE = "en";
147
+ function isHostLocale(tag) {
148
+ return Object.hasOwn(HOST_DICTS, tag);
149
+ }
150
+ function preferredLocale(preference) {
151
+ if (typeof preference !== "string") return DEFAULT_HOST_LOCALE;
152
+ const tag = preference.toLowerCase();
153
+ if (isHostLocale(tag)) return tag;
154
+ const primary = tag.split("-")[0];
155
+ return primary !== void 0 && isHostLocale(primary) ? primary : DEFAULT_HOST_LOCALE;
156
+ }
104
157
  function translate(lang, key, params = {}) {
105
158
  const dict = HOST_DICTS[lang] ?? en;
106
159
  let text = dict[key] ?? key;
@@ -367,10 +420,13 @@ function refToSource(raw, sessionDir) {
367
420
  if (typeof ref.text === "string") return textSourceOf(ref.text);
368
421
  return void 0;
369
422
  }
423
+ function sessionRelativeRef(sessionDir, file) {
424
+ return relative(sessionDir, file).split(sep).join("/");
425
+ }
370
426
  function sourceToRef(source, sessionDir, entryPath) {
371
427
  if (source === null) return null;
372
428
  if (source.kind === "blob") {
373
- const blob = relative(sessionDir, source.path);
429
+ const blob = sessionRelativeRef(sessionDir, source.path);
374
430
  if (!isSafeBackupRef(blob)) throw new Error(`unsafe backup ref ${blob} for ${entryPath}`);
375
431
  return { blob };
376
432
  }
@@ -713,7 +769,7 @@ var SnapshotStore = class _SnapshotStore {
713
769
  * the call id would produce a dangling reference.
714
770
  */
715
771
  refOfRead(sessionId, entry) {
716
- if (entry.file !== void 0) return relative(this.sessionDir(sessionId), entry.file);
772
+ if (entry.file !== void 0) return sessionRelativeRef(this.sessionDir(sessionId), entry.file);
717
773
  return this.entryRefOf(sessionId, entry.callId, entry.anchorSeq);
718
774
  }
719
775
  /** Drop every in-memory trace of one session (its directory is gone). */
@@ -1781,7 +1837,7 @@ var SnapshotStore = class _SnapshotStore {
1781
1837
  for (const action of journal.actions) {
1782
1838
  const source = action.before;
1783
1839
  if (source === null || source.kind !== "blob") continue;
1784
- const ref = relative(sessionDir, source.path);
1840
+ const ref = sessionRelativeRef(sessionDir, source.path);
1785
1841
  if (!isSafeBackupRef(ref)) continue;
1786
1842
  const anchor = refAnchorOf(ref);
1787
1843
  if (Number.isSafeInteger(anchor)) pinned.add(anchor);
@@ -1,6 +1,6 @@
1
1
  /** `rewind` namespace dictionaries for the client plugin. */
2
- /** Simplified Chinese dictionary (the key-set source of truth). */
3
- export declare const zh: {
2
+ /** English dictionary — the canonical key set (the harness fallback language). */
3
+ export declare const en: {
4
4
  'button.aria': string;
5
5
  'button.title': string;
6
6
  'button.retract.aria': string;
@@ -44,54 +44,66 @@ export declare const zh: {
44
44
  'cleanup.unavailable': string;
45
45
  };
46
46
  /** The rewind namespace key union. */
47
- export type RewindKey = keyof typeof zh;
47
+ export type RewindKey = keyof typeof en;
48
48
  declare module '@deepseek-ai/dsh-client-ui-slots' {
49
49
  interface LocaleNamespaceMap {
50
50
  /** The in-place rewind controls' copy. */
51
51
  rewind: RewindKey;
52
52
  }
53
53
  }
54
- /** English dictionary, checked complete against the zh key set. */
55
- export declare const en: {
56
- 'button.aria': string;
57
- 'button.title': string;
58
- 'button.retract.aria': string;
59
- 'button.retract.title': string;
60
- 'popover.title': string;
61
- 'popover.noText': string;
62
- 'popover.retract.title': string;
63
- 'popover.retract.target': string;
64
- 'popover.retract.hint': string;
65
- 'popover.retract.confirm': string;
66
- 'popover.chat': string;
67
- 'popover.chat.hint': string;
68
- 'popover.both': string;
69
- 'popover.both.hint': string;
70
- 'popover.checking': string;
71
- 'popover.noChanges': string;
72
- 'popover.backupDisabled': string;
73
- 'popover.cancel': string;
74
- 'popover.impact.loading': string;
75
- 'popover.impact.failed': string;
76
- 'popover.impact.none': string;
77
- 'popover.impact.restore': string;
78
- 'popover.impact.delete': string;
79
- 'popover.confirm': string;
80
- 'popover.back': string;
81
- 'backup.title': string;
82
- 'backup.on': string;
83
- 'backup.off': string;
84
- 'cleanup.auto': string;
85
- 'cleanup.auto.on': string;
86
- 'cleanup.auto.off': string;
87
- 'cleanup.maxAge': string;
88
- 'cleanup.maxAge.hint': string;
89
- 'cleanup.invalid': string;
90
- 'cleanup.overridden': string;
91
- 'cleanup.reset': string;
92
- 'cleanup.save': string;
93
- 'cleanup.saving': string;
94
- 'cleanup.saveFailed': string;
95
- 'cleanup.readonly': string;
96
- 'cleanup.unavailable': string;
54
+ /** Chinese dictionary, checked complete against the en key set. */
55
+ export declare const zh: Record<RewindKey, string>;
56
+ /** Japanese dictionary, checked complete against the en key set. */
57
+ export declare const ja: Record<RewindKey, string>;
58
+ /**
59
+ * Every dictionary this plugin ships, canonical first. Registration takes this
60
+ * map as a whole, so shipping another language is one dictionary above plus one
61
+ * entry here — no wiring change in `index.ts`.
62
+ */
63
+ export declare const CLIENT_DICTS: {
64
+ en: {
65
+ 'button.aria': string;
66
+ 'button.title': string;
67
+ 'button.retract.aria': string;
68
+ 'button.retract.title': string;
69
+ 'popover.title': string;
70
+ 'popover.noText': string;
71
+ 'popover.retract.title': string;
72
+ 'popover.retract.target': string;
73
+ 'popover.retract.hint': string;
74
+ 'popover.retract.confirm': string;
75
+ 'popover.chat': string;
76
+ 'popover.chat.hint': string;
77
+ 'popover.both': string;
78
+ 'popover.both.hint': string;
79
+ 'popover.checking': string;
80
+ 'popover.noChanges': string;
81
+ 'popover.backupDisabled': string;
82
+ 'popover.cancel': string;
83
+ 'popover.impact.loading': string;
84
+ 'popover.impact.failed': string;
85
+ 'popover.impact.none': string;
86
+ 'popover.impact.restore': string;
87
+ 'popover.impact.delete': string;
88
+ 'popover.confirm': string;
89
+ 'popover.back': string;
90
+ 'backup.title': string;
91
+ 'backup.on': string;
92
+ 'backup.off': string;
93
+ 'cleanup.auto': string;
94
+ 'cleanup.auto.on': string;
95
+ 'cleanup.auto.off': string;
96
+ 'cleanup.maxAge': string;
97
+ 'cleanup.maxAge.hint': string;
98
+ 'cleanup.invalid': string;
99
+ 'cleanup.overridden': string;
100
+ 'cleanup.reset': string;
101
+ 'cleanup.save': string;
102
+ 'cleanup.saving': string;
103
+ 'cleanup.saveFailed': string;
104
+ 'cleanup.readonly': string;
105
+ 'cleanup.unavailable': string;
106
+ };
107
+ zh: Record<"backup.off" | "backup.on" | "backup.title" | "button.aria" | "button.retract.aria" | "button.retract.title" | "button.title" | "cleanup.auto" | "cleanup.auto.off" | "cleanup.auto.on" | "cleanup.invalid" | "cleanup.maxAge" | "cleanup.maxAge.hint" | "cleanup.overridden" | "cleanup.readonly" | "cleanup.reset" | "cleanup.save" | "cleanup.saveFailed" | "cleanup.saving" | "cleanup.unavailable" | "popover.back" | "popover.backupDisabled" | "popover.both" | "popover.both.hint" | "popover.cancel" | "popover.chat" | "popover.chat.hint" | "popover.checking" | "popover.confirm" | "popover.impact.delete" | "popover.impact.failed" | "popover.impact.loading" | "popover.impact.none" | "popover.impact.restore" | "popover.noChanges" | "popover.noText" | "popover.retract.confirm" | "popover.retract.hint" | "popover.retract.target" | "popover.retract.title" | "popover.title", string>;
108
+ ja: Record<"backup.off" | "backup.on" | "backup.title" | "button.aria" | "button.retract.aria" | "button.retract.title" | "button.title" | "cleanup.auto" | "cleanup.auto.off" | "cleanup.auto.on" | "cleanup.invalid" | "cleanup.maxAge" | "cleanup.maxAge.hint" | "cleanup.overridden" | "cleanup.readonly" | "cleanup.reset" | "cleanup.save" | "cleanup.saveFailed" | "cleanup.saving" | "cleanup.unavailable" | "popover.back" | "popover.backupDisabled" | "popover.both" | "popover.both.hint" | "popover.cancel" | "popover.chat" | "popover.chat.hint" | "popover.checking" | "popover.confirm" | "popover.impact.delete" | "popover.impact.failed" | "popover.impact.loading" | "popover.impact.none" | "popover.impact.restore" | "popover.noChanges" | "popover.noText" | "popover.retract.confirm" | "popover.retract.hint" | "popover.retract.target" | "popover.retract.title" | "popover.title", string>;
97
109
  };
@@ -23,26 +23,13 @@
23
23
  * not in that channel (see docs/compat/audit.md, RU-I18N), and no host command
24
24
  * OUTPUT is localized for anyone, so this dictionary is what carries it.
25
25
  *
26
- * English is the key-set source of truth; zh is checked complete against it.
26
+ * English is the canonical key set: every other dictionary is typed complete
27
+ * against it, and the tests compare every dictionary's template placeholders
28
+ * with it. Adding a language is one dictionary plus one entry in `HOST_DICTS`.
27
29
  *
28
30
  * @module dsh-rewind/locales
29
31
  */
30
- /** Host-side supported locale ids, mirroring the harness's shipped locales. */
31
- export type HostLocaleId = 'zh' | 'en';
32
- /**
33
- * The locale a durable preference selects from this plugin's dictionaries.
34
- *
35
- * The harness accepts any BCP 47-style id while this plugin ships only `zh` and
36
- * `en`, so the PRIMARY subtag decides (`zh-CN` → zh) and everything else — an
37
- * unset preference, an unsupported language, a non-string value — is English.
38
- * The client's own selection tries the full tag before the primary subtag; over
39
- * these two dictionaries the outcome is the same.
40
- *
41
- * @param preference - the raw `locale.preference` value.
42
- * @returns the dictionary this plugin renders its host copy in.
43
- */
44
- export declare function preferredLocale(preference: unknown): HostLocaleId;
45
- /** English dictionary — the key-set source of truth (neutral default). */
32
+ /** English dictionary — the canonical key set (neutral default). */
46
33
  export declare const en: {
47
34
  'plan.skip': string;
48
35
  'skipReason.oversized': string;
@@ -93,13 +80,86 @@ export declare const en: {
93
80
  export type HostKey = keyof typeof en;
94
81
  /** Chinese dictionary, checked complete against the en key set. */
95
82
  export declare const zh: Record<HostKey, string>;
96
- /** The host dictionaries keyed by locale id. */
97
- export declare const HOST_DICTS: Record<HostLocaleId, Record<HostKey, string>>;
83
+ /** Japanese dictionary, checked complete against the en key set. */
84
+ export declare const ja: Record<HostKey, string>;
85
+ /**
86
+ * Every language this plugin ships a host dictionary for. English is first as
87
+ * the canonical dictionary; the rest follow the harness's language order.
88
+ * Adding a language is one dictionary above plus one entry here — the locale-id
89
+ * type, the preference resolver, and the tests all derive from this map.
90
+ */
91
+ export declare const HOST_DICTS: {
92
+ en: {
93
+ 'plan.skip': string;
94
+ 'skipReason.oversized': string;
95
+ 'error.invalidTarget': string;
96
+ 'sep.list': string;
97
+ 'sep.clause': string;
98
+ 'failures.suffix': string;
99
+ 'failures.item': string;
100
+ inflight: string;
101
+ stopFailed: string;
102
+ cancelled: string;
103
+ failed: string;
104
+ 'restore.count': string;
105
+ 'delete.count': string;
106
+ 'skip.count': string;
107
+ noRestorable: string;
108
+ backupOff: string;
109
+ storeUnsupported: string;
110
+ success: string;
111
+ noUserMessages: string;
112
+ 'command.description': string;
113
+ 'command.undoDescription': string;
114
+ 'engine.description': string;
115
+ 'engine.rejected': string;
116
+ 'engine.inputHint': string;
117
+ 'cleanup.description': string;
118
+ 'cleanup.inputHint': string;
119
+ 'cleanup.status': string;
120
+ 'cleanup.enabled': string;
121
+ 'cleanup.disabled': string;
122
+ 'cleanup.onOk': string;
123
+ 'cleanup.offOk': string;
124
+ 'cleanup.maxAgeOk': string;
125
+ 'cleanup.cfgInvalid': string;
126
+ 'cleanup.saveFailed': string;
127
+ 'cleanup.runDry': string;
128
+ 'cleanup.runApply': string;
129
+ 'cleanup.runFailed': string;
130
+ 'cleanup.skipped': string;
131
+ 'cleanup.clearDry': string;
132
+ 'cleanup.clearApply': string;
133
+ 'cleanup.clearActive': string;
134
+ 'cleanup.clearCancelled': string;
135
+ 'cleanup.clearFailed': string;
136
+ 'cleanup.usage': string;
137
+ };
138
+ zh: Record<"backupOff" | "cancelled" | "cleanup.cfgInvalid" | "cleanup.clearActive" | "cleanup.clearApply" | "cleanup.clearCancelled" | "cleanup.clearDry" | "cleanup.clearFailed" | "cleanup.description" | "cleanup.disabled" | "cleanup.enabled" | "cleanup.inputHint" | "cleanup.maxAgeOk" | "cleanup.offOk" | "cleanup.onOk" | "cleanup.runApply" | "cleanup.runDry" | "cleanup.runFailed" | "cleanup.saveFailed" | "cleanup.skipped" | "cleanup.status" | "cleanup.usage" | "command.description" | "command.undoDescription" | "delete.count" | "engine.description" | "engine.inputHint" | "engine.rejected" | "error.invalidTarget" | "failed" | "failures.item" | "failures.suffix" | "inflight" | "noRestorable" | "noUserMessages" | "plan.skip" | "restore.count" | "sep.clause" | "sep.list" | "skip.count" | "skipReason.oversized" | "stopFailed" | "storeUnsupported" | "success", string>;
139
+ ja: Record<"backupOff" | "cancelled" | "cleanup.cfgInvalid" | "cleanup.clearActive" | "cleanup.clearApply" | "cleanup.clearCancelled" | "cleanup.clearDry" | "cleanup.clearFailed" | "cleanup.description" | "cleanup.disabled" | "cleanup.enabled" | "cleanup.inputHint" | "cleanup.maxAgeOk" | "cleanup.offOk" | "cleanup.onOk" | "cleanup.runApply" | "cleanup.runDry" | "cleanup.runFailed" | "cleanup.saveFailed" | "cleanup.skipped" | "cleanup.status" | "cleanup.usage" | "command.description" | "command.undoDescription" | "delete.count" | "engine.description" | "engine.inputHint" | "engine.rejected" | "error.invalidTarget" | "failed" | "failures.item" | "failures.suffix" | "inflight" | "noRestorable" | "noUserMessages" | "plan.skip" | "restore.count" | "sep.clause" | "sep.list" | "skip.count" | "skipReason.oversized" | "stopFailed" | "storeUnsupported" | "success", string>;
140
+ };
141
+ /** Host-side supported locale ids (the registry keys). */
142
+ export type HostLocaleId = keyof typeof HOST_DICTS;
143
+ /** Neutral default, matching the harness's `FALLBACK_LOCALE`. */
144
+ export declare const DEFAULT_HOST_LOCALE: "en";
145
+ /**
146
+ * The locale a durable preference selects from this plugin's dictionaries.
147
+ *
148
+ * The harness accepts any BCP 47-style id while this plugin ships a fixed set,
149
+ * so the preference is matched against the registry: the full tag first
150
+ * (case-insensitively), then its primary subtag (`xx-YY` → `xx`), mirroring the
151
+ * client runtime. Anything else — an unset preference, an unsupported language,
152
+ * a non-string value — is the neutral default.
153
+ *
154
+ * @param preference - the raw `locale.preference` value.
155
+ * @returns the dictionary this plugin renders its host copy in.
156
+ */
157
+ export declare function preferredLocale(preference: unknown): HostLocaleId;
98
158
  /**
99
159
  * Render one dictionary key with `{name}` template interpolation. Unknown
100
160
  * params are ignored; a missing key falls back to the raw key so a dictionary
101
161
  * gap is visible instead of blank.
102
- * @param lang - the active locale.
162
+ * @param lang - the active locale id.
103
163
  * @param key - the dictionary key.
104
164
  * @param params - `{name}` substitution values.
105
165
  */
package/locale/ja.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "会話の巻き戻し",
4
+ "description": "以前のメッセージまで巻き戻します。ワークスペースのファイルもあわせて復元できます。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-rewind-plugin",
3
- "version": "0.19.0",
3
+ "version": "0.19.2",
4
4
  "description": "In-window conversation rewind with workspace file restore · 同窗口内对话回退并可还原工作区文件",
5
5
  "icon": "./assets/icon.svg",
6
6
  "keywords": [