dsh-theone 0.3.14 → 0.3.15

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
@@ -45,7 +45,7 @@ Each project gets its own background session that reasons, runs tools and compac
45
45
 
46
46
  - **Feels native.** Thinking streams in its usual place from the first token, and tool cards, approvals, questions, todo lists, retries and mid-reply steering all work as usual.
47
47
  - **Related work connects; unrelated work stays out.** Related topics share progress automatically and TheOne learns which ones belong together from how you use them. A topic's constraints (say, "budget figures stay out of the paper") are attached verbatim every time, so compaction never drops them.
48
- - **Gets better with use.** Say "wrong topic" or click **Move to…** in the directory, and similar messages go to the right place from then on.
48
+ - **Gets better with use.** Say "wrong topic" or click **Move to…** in the directory, and TheOne learns which terms tie that kind of message to the right topic (one small model call), so similar messages go there from then on. The directory shows how often routing was kept as is.
49
49
  - **Your old sessions become a topic directory.** After install it reads your existing sessions in the background, turns them into topics grouped into workspaces, and you pick up where you left off.
50
50
  - **Nothing extra to configure.** No separate API key: routing and the background sessions use the model you chose in DSH. When TheOne is the selected model, a **Background** button beside the model menu shows which model does the routing and the work, and switches it.
51
51
 
@@ -57,7 +57,7 @@ Each project gets its own background session that reasons, runs tools and compac
57
57
  2. Open **Plugins → Add plugin**, paste `https://github.com/YunongDai2005/dsh-theone`, and install.
58
58
  3. Click **TheOne · Main chat** in the sidebar and start talking.
59
59
 
60
- From the command line: `dsh plugin --profile web add github:YunongDai2005/dsh-theone --ignore-scripts`. Works with DSH `0.2.0-rc.2` and Node.js 24; the interface follows DSH's language (English / Simplified Chinese).
60
+ From the command line: `dsh plugin --profile web add github:YunongDai2005/dsh-theone --ignore-scripts`. Works with DSH `0.2.0-rc.2` and Node.js 24; the interface follows DSH's language (English / Simplified Chinese). Installing `dsh-theone` from npm also works, but DSH's package manager only accepts a version once it has been published for 24 hours, so the GitHub address gets new versions first.
61
61
 
62
62
  > Unofficial community project, maintained independently. It is not affiliated with or endorsed by DeepSeek.
63
63
 
package/README.zh.md CHANGED
@@ -45,7 +45,7 @@
45
45
 
46
46
  - **和原生会话一模一样**:思考从第一个字起就在原位置,工具卡片、授权、提问、待办、重试、回答中途插话,全都照常。
47
47
  - **相关的事会互通,无关的事互不打扰**:相关话题自动共享进展,并从你的使用中学习哪些话题有关联;话题的约束(比如「预算数字不能写进论文」)每次都原样带上,压缩不会把它丢掉。
48
- - **越用越准**:说「分错了」或在目录里点「改到…」,TheOne 会记住,类似的消息以后直接分对。
48
+ - **越用越准**:说「分错了」或在目录里点「改到…」,TheOne 会学到哪些词把这类消息和正确话题联系起来(只需一次很小的模型调用),类似的消息以后直接分对;话题目录里能看到分配的准确率。
49
49
  - **旧会话自动变成话题目录**:装上后它会在后台读取你已有的会话,整理成话题并按工作区分组,直接接着聊。
50
50
  - **零额外配置**:不用另填 API Key,路由和后台都用你在 DSH 里选好的模型。选中 TheOne 时,模型按钮旁边会出现 **后台** 按钮,显示并切换分配话题和干活用的模型。
51
51
 
@@ -57,7 +57,7 @@
57
57
  2. 打开 **插件 → 添加插件**,粘贴 `https://github.com/YunongDai2005/dsh-theone`,点击安装。
58
58
  3. 点击左侧 **TheOne · 主聊天**,开始说话。
59
59
 
60
- 命令行安装:`dsh plugin --profile web add github:YunongDai2005/dsh-theone --ignore-scripts`。兼容 DSH `0.2.0-rc.2` 与 Node.js 24;界面跟随 DSH 的语言(简体中文 / English)。
60
+ 命令行安装:`dsh plugin --profile web add github:YunongDai2005/dsh-theone --ignore-scripts`。兼容 DSH `0.2.0-rc.2` 与 Node.js 24;界面跟随 DSH 的语言(简体中文 / English)。也可以从 npm 安装 `dsh-theone`,但 DSH 的包管理器只接受发布满 24 小时的版本,所以用 GitHub 地址安装能最早拿到新版本。
61
61
 
62
62
  > 非官方社区项目,由社区成员独立维护,与 DeepSeek 不存在隶属或背书关系。
63
63
 
@@ -20,6 +20,8 @@ export declare const zh: {
20
20
  readonly 'update.reloading': "正在重新加载…";
21
21
  readonly 'update.reloadingHint': "TheOne 正在用新版本重新加载,DSH 不需要重启;完成后页面会自动刷新。";
22
22
  readonly 'update.busy': "有回复正在进行,等它结束后再点更新。";
23
+ readonly 'update.tooNew': "DSH 的安全策略只允许安装发布满 24 小时的版本,这一版还太新。过一阵再点一次即可。";
24
+ readonly 'update.network': "连不上下载源,请检查网络后点击重试。";
23
25
  readonly 'update.failed': "更新失败";
24
26
  readonly 'update.hint': "当前 {current},可更新到 {latest}。点击一键更新,不用重启 DSH。";
25
27
  readonly 'update.manualHint': "当前 {current},最新 {latest}。这份插件不是从 GitHub 或 npm 安装的,请在「插件」页面重新安装。";
@@ -20,6 +20,8 @@ export const zh = {
20
20
  'update.reloading': '正在重新加载…',
21
21
  'update.reloadingHint': 'TheOne 正在用新版本重新加载,DSH 不需要重启;完成后页面会自动刷新。',
22
22
  'update.busy': '有回复正在进行,等它结束后再点更新。',
23
+ 'update.tooNew': 'DSH 的安全策略只允许安装发布满 24 小时的版本,这一版还太新。过一阵再点一次即可。',
24
+ 'update.network': '连不上下载源,请检查网络后点击重试。',
23
25
  'update.failed': '更新失败',
24
26
  'update.hint': '当前 {current},可更新到 {latest}。点击一键更新,不用重启 DSH。',
25
27
  'update.manualHint': '当前 {current},最新 {latest}。这份插件不是从 GitHub 或 npm 安装的,请在「插件」页面重新安装。',
@@ -210,6 +212,8 @@ export const en = {
210
212
  'update.reloading': 'Reloading…',
211
213
  'update.reloadingHint': 'TheOne is reloading with the new version; DSH keeps running, and the page refreshes when it is done.',
212
214
  'update.busy': 'A reply is in progress. Update once it finishes.',
215
+ 'update.tooNew': 'DSH only installs versions published at least 24 hours ago, as a safety policy, and this one is newer. Try again later.',
216
+ 'update.network': 'Could not reach the download source. Check the network and click to retry.',
213
217
  'update.failed': 'Update failed',
214
218
  'update.hint': 'You have {current}; {latest} is available. Click to update without restarting DSH.',
215
219
  'update.manualHint': 'You have {current}; {latest} is available. This copy was not installed from GitHub or npm, so reinstall it from the Plugins page.',
package/dist/client.js CHANGED
@@ -103,6 +103,8 @@ var zh = {
103
103
  "update.reloading": "\u6B63\u5728\u91CD\u65B0\u52A0\u8F7D\u2026",
104
104
  "update.reloadingHint": "TheOne \u6B63\u5728\u7528\u65B0\u7248\u672C\u91CD\u65B0\u52A0\u8F7D\uFF0CDSH \u4E0D\u9700\u8981\u91CD\u542F\uFF1B\u5B8C\u6210\u540E\u9875\u9762\u4F1A\u81EA\u52A8\u5237\u65B0\u3002",
105
105
  "update.busy": "\u6709\u56DE\u590D\u6B63\u5728\u8FDB\u884C\uFF0C\u7B49\u5B83\u7ED3\u675F\u540E\u518D\u70B9\u66F4\u65B0\u3002",
106
+ "update.tooNew": "DSH \u7684\u5B89\u5168\u7B56\u7565\u53EA\u5141\u8BB8\u5B89\u88C5\u53D1\u5E03\u6EE1 24 \u5C0F\u65F6\u7684\u7248\u672C\uFF0C\u8FD9\u4E00\u7248\u8FD8\u592A\u65B0\u3002\u8FC7\u4E00\u9635\u518D\u70B9\u4E00\u6B21\u5373\u53EF\u3002",
107
+ "update.network": "\u8FDE\u4E0D\u4E0A\u4E0B\u8F7D\u6E90\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u70B9\u51FB\u91CD\u8BD5\u3002",
106
108
  "update.failed": "\u66F4\u65B0\u5931\u8D25",
107
109
  "update.hint": "\u5F53\u524D {current}\uFF0C\u53EF\u66F4\u65B0\u5230 {latest}\u3002\u70B9\u51FB\u4E00\u952E\u66F4\u65B0\uFF0C\u4E0D\u7528\u91CD\u542F DSH\u3002",
108
110
  "update.manualHint": "\u5F53\u524D {current}\uFF0C\u6700\u65B0 {latest}\u3002\u8FD9\u4EFD\u63D2\u4EF6\u4E0D\u662F\u4ECE GitHub \u6216 npm \u5B89\u88C5\u7684\uFF0C\u8BF7\u5728\u300C\u63D2\u4EF6\u300D\u9875\u9762\u91CD\u65B0\u5B89\u88C5\u3002",
@@ -293,6 +295,8 @@ var en = {
293
295
  "update.reloading": "Reloading\u2026",
294
296
  "update.reloadingHint": "TheOne is reloading with the new version; DSH keeps running, and the page refreshes when it is done.",
295
297
  "update.busy": "A reply is in progress. Update once it finishes.",
298
+ "update.tooNew": "DSH only installs versions published at least 24 hours ago, as a safety policy, and this one is newer. Try again later.",
299
+ "update.network": "Could not reach the download source. Check the network and click to retry.",
296
300
  "update.failed": "Update failed",
297
301
  "update.hint": "You have {current}; {latest} is available. Click to update without restarting DSH.",
298
302
  "update.manualHint": "You have {current}; {latest} is available. This copy was not installed from GitHub or npm, so reinstall it from the Plugins page.",
@@ -585,7 +589,7 @@ function apply(ctx) {
585
589
  const status = (0, import_react.useSyncExternalStore)(subscribeUpdate, () => update);
586
590
  if (!status || !status.available && !status.state) return null;
587
591
  const label = status.state === "installing" ? t2("update.installing") : status.state === "reloading" ? t2("update.reloading") : status.state === "restart" ? t2("update.restart") : status.state === "failed" ? t2("update.failed") : t2("update.available");
588
- const title = status.error === "GATEWAY_BUSY" ? t2("update.busy") : status.state === "reloading" ? t2("update.reloadingHint") : status.state === "restart" ? t2("update.restartHint") : status.state === "failed" ? t2("update.failedHint", { error: status.error ?? "" }) : status.installable ? t2("update.hint", { current: status.current, latest: status.latest ?? "" }) : t2("update.manualHint", { current: status.current, latest: status.latest ?? "" });
592
+ const title = status.error === "GATEWAY_BUSY" ? t2("update.busy") : status.state === "reloading" ? t2("update.reloadingHint") : status.state === "restart" ? t2("update.restartHint") : status.state === "failed" ? status.error === "MINIMUM_RELEASE_AGE" ? t2("update.tooNew") : status.error === "NETWORK" ? t2("update.network") : t2("update.failedHint", { error: status.error ?? "" }) : status.installable ? t2("update.hint", { current: status.current, latest: status.latest ?? "" }) : t2("update.manualHint", { current: status.current, latest: status.latest ?? "" });
589
593
  const act = (event) => {
590
594
  event.preventDefault();
591
595
  event.stopPropagation();
package/dist/update.d.ts CHANGED
@@ -12,8 +12,19 @@ export interface UpdateStatus {
12
12
  source: UpdateSource;
13
13
  /** installing → reloading (TheOne restarts itself; DSH keeps running), restart (applies after DSH restarts) or failed. */
14
14
  state?: 'installing' | 'reloading' | 'restart' | 'failed';
15
+ /** Why it failed: MINIMUM_RELEASE_AGE, NETWORK, or the plugin manager's own code. */
15
16
  error?: string;
17
+ /** A newer npm version that pnpm will accept only once it is a day old, and when that is. */
18
+ waiting?: {
19
+ version: string;
20
+ readyAt: number;
21
+ };
16
22
  }
23
+ /**
24
+ * pnpm, which DSH installs plugins with, refuses npm versions published less than a day ago
25
+ * (minimumReleaseAge, a supply-chain safeguard). Updates from npm wait until then.
26
+ */
27
+ export declare const RELEASE_AGE_MS: number;
17
28
  /** The DSH plugin manager's install call, as TheOne uses it. */
18
29
  export interface PluginInstaller {
19
30
  installBundle(spec: string, options?: {
@@ -25,6 +36,9 @@ export interface PluginInstaller {
25
36
  code?: string;
26
37
  message?: string;
27
38
  } | unknown;
39
+ packageResult?: {
40
+ output?: string;
41
+ };
28
42
  }>;
29
43
  }
30
44
  /** Compare dotted versions numerically; a pre-release sorts before its release. */
package/dist/update.js CHANGED
@@ -1,5 +1,10 @@
1
1
  export const REPOSITORY = 'YunongDai2005/dsh-theone';
2
2
  export const PACKAGE_NAME = 'dsh-theone';
3
+ /**
4
+ * pnpm, which DSH installs plugins with, refuses npm versions published less than a day ago
5
+ * (minimumReleaseAge, a supply-chain safeguard). Updates from npm wait until then.
6
+ */
7
+ export const RELEASE_AGE_MS = 24 * 3600000;
3
8
  /** Compare dotted versions numerically; a pre-release sorts before its release. */
4
9
  export function compareVersions(a, b) {
5
10
  const parse = (value) => {
@@ -47,7 +52,9 @@ export class Updater {
47
52
  /** The latest known status; checks again at most every six hours (or now, when forced). */
48
53
  async status(force = false) {
49
54
  const age = this.checked ? this.now() - this.checked.at : Infinity;
50
- if (this.state !== 'installing' && (force || age > (this.checked?.error ? HOUR / 2 : 6 * HOUR))) {
55
+ // A version waiting out pnpm's release age is looked at again as soon as it qualifies.
56
+ const due = !!this.checked?.waiting && this.now() >= this.checked.waiting.readyAt;
57
+ if (this.state !== 'installing' && (force || due || age > (this.checked?.error ? HOUR / 2 : 6 * HOUR))) {
51
58
  this.pending ??= this.check().finally(() => { this.pending = undefined; });
52
59
  await this.pending;
53
60
  }
@@ -73,7 +80,11 @@ export class Updater {
73
80
  else {
74
81
  this.state = 'failed';
75
82
  const error = result.error;
76
- this.error = String(error?.code ?? error?.message ?? result.application).slice(0, 120);
83
+ // pnpm's own reasons are clearer than the plugin manager's generic failure.
84
+ const output = `${result.packageResult?.output ?? ''}\n${error?.message ?? ''}`;
85
+ this.error = /MINIMUM_RELEASE_AGE/.test(output) ? 'MINIMUM_RELEASE_AGE'
86
+ : /UND_ERR|ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|ERR_PNPM_META_FETCH_FAIL|network/i.test(output) ? 'NETWORK'
87
+ : String(error?.code ?? error?.message ?? result.application).slice(0, 120);
77
88
  }
78
89
  }
79
90
  catch (error) {
@@ -86,7 +97,8 @@ export class Updater {
86
97
  const latest = this.checked?.latest;
87
98
  const source = this.source;
88
99
  const available = !!latest && compareVersions(latest, this.current) > 0;
89
- return { current: this.current, ...(latest ? { latest } : {}), available, source,
100
+ const waiting = this.checked?.waiting && compareVersions(this.checked.waiting.version, this.current) > 0 ? { waiting: this.checked.waiting } : {};
101
+ return { current: this.current, ...(latest ? { latest } : {}), available, source, ...waiting,
90
102
  installable: available && (source === 'npm' || (source === 'github' && !!this.checked?.sha)),
91
103
  ...(this.state ? { state: this.state } : {}), ...(this.error ?? this.checked?.error ? { error: this.error ?? this.checked?.error } : {}) };
92
104
  }
@@ -94,10 +106,19 @@ export class Updater {
94
106
  const signal = AbortSignal.timeout(10000);
95
107
  try {
96
108
  if (this.source === 'npm') {
97
- const response = await this.fetcher(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, { signal });
109
+ const response = await this.fetcher(`https://registry.npmjs.org/${PACKAGE_NAME}`, { signal });
98
110
  if (!response.ok)
99
111
  throw new Error(`npm ${response.status}`);
100
- this.checked = { at: this.now(), latest: String((await response.json()).version ?? '') || undefined };
112
+ const packument = await response.json();
113
+ // Offer the newest release pnpm will accept now; a newer one waits until it is a day old.
114
+ const now = this.now();
115
+ const releases = Object.keys(packument.versions ?? {}).filter(version => /^\d+\.\d+\.\d+$/.test(version))
116
+ .map(version => ({ version, at: Date.parse(packument.time?.[version] ?? '') }))
117
+ .filter(release => Number.isFinite(release.at)).sort((a, b) => compareVersions(b.version, a.version));
118
+ const ready = releases.find(release => now - release.at >= RELEASE_AGE_MS);
119
+ const newest = releases[0];
120
+ this.checked = { at: now, ...(ready ? { latest: ready.version } : {}),
121
+ ...(newest && newest !== ready ? { waiting: { version: newest.version, readyAt: newest.at + RELEASE_AGE_MS } } : {}) };
101
122
  return;
102
123
  }
103
124
  // A GitHub install updates to the exact commit whose version was read.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-theone",
3
- "version": "0.3.14",
3
+ "version": "0.3.15",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Automatic context routing for DeepSeek Harness",