dsh-theone 0.3.19 → 0.3.20

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
@@ -18,18 +18,10 @@ How many sessions are sitting in your DSH sidebar? Getting back to last week's w
18
18
 
19
19
  **TheOne takes care of that.** You just talk in one main chat:
20
20
 
21
- ```text
22
- You: FP8 still crashes for Qwen on the 9070 XT
23
- → Qwen / RX 9070 XT
24
- You: also fill in the ablation table in chapter 3 of the paper
25
- → Video Attention Thesis
26
- You: and add the Qwen speed numbers from earlier
27
- → Video Attention Thesis · reference: Qwen / RX 9070 XT
28
- You: wrong topic, that was the GPU one
29
- → Qwen / RX 9070 XT (the previous message is redone there, and remembered)
30
- ```
31
-
32
- <sub>Illustration. By default, a one-line notice appears only when the topic changes.</sub>
21
+ <picture>
22
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/YunongDai2005/dsh-theone/main/docs/images/theone-architecture-en-dark.svg">
23
+ <img alt="How TheOne works: main chat sends each message through the router to its topic session; answers stream back, and the topic directory keeps progress, constraints and links" src="https://raw.githubusercontent.com/YunongDai2005/dsh-theone/main/docs/images/theone-architecture-en-light.svg" width="100%">
24
+ </picture>
33
25
 
34
26
  Each project gets its own background session that reasons, runs tools and compacts on its own. What you see is always one ordinary conversation.
35
27
 
package/README.zh.md CHANGED
@@ -18,18 +18,10 @@
18
18
 
19
19
  **TheOne 把这些都交给它。** 你只管在一个主聊天里说话:
20
20
 
21
- ```text
22
- 你:Qwen 在 9070 XT 上跑 FP8 还是报错
23
- → Qwen / RX 9070 XT
24
- 你:顺便把论文第三章的消融表补上
25
- → 视频注意力论文
26
- 你:把刚才 Qwen 的测速结果也放进去
27
- → 视频注意力论文 · 参考:Qwen / RX 9070 XT
28
- 你:分错了,是显卡那个的
29
- → Qwen / RX 9070 XT (上一条交给它重新处理,以后也记住了)
30
- ```
31
-
32
- <sub>示意。默认只在切换话题时显示一行提示。</sub>
21
+ <picture>
22
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/YunongDai2005/dsh-theone/main/docs/images/theone-architecture-zh-dark.svg">
23
+ <img alt="TheOne 的结构:主聊天把每条消息交给分配话题,送到对应的后台会话,结果实时回到主聊天;话题目录保存进展、约束和关联" src="https://raw.githubusercontent.com/YunongDai2005/dsh-theone/main/docs/images/theone-architecture-zh-light.svg" width="100%">
24
+ </picture>
33
25
 
34
26
  每件事都有自己的后台会话,在里面推理、调用工具、压缩上下文;你看到的始终是一个普通的对话。
35
27
 
@@ -39,6 +39,8 @@ export declare const zh: {
39
39
  readonly 'update.busy': "有回复正在进行,等它结束后再点更新。";
40
40
  readonly 'update.tooNew': "DSH 的安全策略只允许安装发布满 24 小时的版本,这一版还太新。过一阵再点一次即可。";
41
41
  readonly 'update.network': "连不上下载源,请检查网络后点击重试。";
42
+ readonly 'update.otherAge': "pnpm 拒绝安装:{names} 也是发布不满 24 小时的版本,不归 TheOne 放行。等它满 24 小时后再点一次。";
43
+ readonly 'update.ageStill': "已为 TheOne 放行,pnpm 仍然拒绝:{detail}。完整日志在 DSH 配置目录的 .plugin-manager/logs 里。";
42
44
  readonly 'update.failed': "更新失败";
43
45
  readonly 'update.hint': "当前 {current},可更新到 {latest}。点击一键更新,不用重启 DSH。";
44
46
  readonly 'update.manualHint': "当前 {current},最新 {latest}。这份插件不是从 GitHub 或 npm 安装的,请在「插件」页面重新安装。";
@@ -39,6 +39,8 @@ export const zh = {
39
39
  'update.busy': '有回复正在进行,等它结束后再点更新。',
40
40
  'update.tooNew': 'DSH 的安全策略只允许安装发布满 24 小时的版本,这一版还太新。过一阵再点一次即可。',
41
41
  'update.network': '连不上下载源,请检查网络后点击重试。',
42
+ 'update.otherAge': 'pnpm 拒绝安装:{names} 也是发布不满 24 小时的版本,不归 TheOne 放行。等它满 24 小时后再点一次。',
43
+ 'update.ageStill': '已为 TheOne 放行,pnpm 仍然拒绝:{detail}。完整日志在 DSH 配置目录的 .plugin-manager/logs 里。',
42
44
  'update.failed': '更新失败',
43
45
  'update.hint': '当前 {current},可更新到 {latest}。点击一键更新,不用重启 DSH。',
44
46
  'update.manualHint': '当前 {current},最新 {latest}。这份插件不是从 GitHub 或 npm 安装的,请在「插件」页面重新安装。',
@@ -248,6 +250,8 @@ export const en = {
248
250
  'update.busy': 'A reply is in progress. Update once it finishes.',
249
251
  'update.tooNew': 'DSH only installs versions published at least 24 hours ago, as a safety policy, and this one is newer. Try again later.',
250
252
  'update.network': 'Could not reach the download source. Check the network and click to retry.',
253
+ 'update.otherAge': 'pnpm refused: {names} is also less than 24 hours old, and only TheOne is exempted. Try again once it is a day old.',
254
+ 'update.ageStill': 'TheOne is exempted, but pnpm still refused: {detail}. The full log is in .plugin-manager/logs in the DSH profile folder.',
251
255
  'update.failed': 'Update failed',
252
256
  'update.hint': 'You have {current}; {latest} is available. Click to update without restarting DSH.',
253
257
  '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
@@ -123,6 +123,8 @@ var zh = {
123
123
  "update.busy": "\u6709\u56DE\u590D\u6B63\u5728\u8FDB\u884C\uFF0C\u7B49\u5B83\u7ED3\u675F\u540E\u518D\u70B9\u66F4\u65B0\u3002",
124
124
  "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",
125
125
  "update.network": "\u8FDE\u4E0D\u4E0A\u4E0B\u8F7D\u6E90\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u70B9\u51FB\u91CD\u8BD5\u3002",
126
+ "update.otherAge": "pnpm \u62D2\u7EDD\u5B89\u88C5\uFF1A{names} \u4E5F\u662F\u53D1\u5E03\u4E0D\u6EE1 24 \u5C0F\u65F6\u7684\u7248\u672C\uFF0C\u4E0D\u5F52 TheOne \u653E\u884C\u3002\u7B49\u5B83\u6EE1 24 \u5C0F\u65F6\u540E\u518D\u70B9\u4E00\u6B21\u3002",
127
+ "update.ageStill": "\u5DF2\u4E3A TheOne \u653E\u884C\uFF0Cpnpm \u4ECD\u7136\u62D2\u7EDD\uFF1A{detail}\u3002\u5B8C\u6574\u65E5\u5FD7\u5728 DSH \u914D\u7F6E\u76EE\u5F55\u7684 .plugin-manager/logs \u91CC\u3002",
126
128
  "update.failed": "\u66F4\u65B0\u5931\u8D25",
127
129
  "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",
128
130
  "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",
@@ -332,6 +334,8 @@ var en = {
332
334
  "update.busy": "A reply is in progress. Update once it finishes.",
333
335
  "update.tooNew": "DSH only installs versions published at least 24 hours ago, as a safety policy, and this one is newer. Try again later.",
334
336
  "update.network": "Could not reach the download source. Check the network and click to retry.",
337
+ "update.otherAge": "pnpm refused: {names} is also less than 24 hours old, and only TheOne is exempted. Try again once it is a day old.",
338
+ "update.ageStill": "TheOne is exempted, but pnpm still refused: {detail}. The full log is in .plugin-manager/logs in the DSH profile folder.",
335
339
  "update.failed": "Update failed",
336
340
  "update.hint": "You have {current}; {latest} is available. Click to update without restarting DSH.",
337
341
  "update.manualHint": "You have {current}; {latest} is available. This copy was not installed from GitHub or npm, so reinstall it from the Plugins page.",
@@ -598,7 +602,7 @@ function apply(ctx) {
598
602
  cache: "no-store",
599
603
  ...body ? { headers: { "content-type": "application/json" }, body: JSON.stringify(body) } : {}
600
604
  });
601
- if (response.ok || response.status === 409) setUpdate(await response.json());
605
+ if (response.ok || response.status === 409 || response.status === 400) setUpdate(await response.json());
602
606
  if (update?.state === "reloading") void awaitReload(update.current);
603
607
  } catch {
604
608
  }
@@ -715,13 +719,13 @@ function apply(ctx) {
715
719
  const waiting = !!status?.waiting && !status.available && !status.state;
716
720
  if (!status || !status.available && !status.state && !waiting) return null;
717
721
  const label = waiting ? t2("update.waiting") : 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");
718
- const hint = waiting ? t2("update.waitingHint", { latest: status.waiting.version }) : 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 ?? "" });
722
+ const hint = waiting ? t2("update.waitingHint", { latest: status.waiting.version }) : status.error === "GATEWAY_BUSY" ? t2("update.busy") : status.state === "reloading" ? t2("update.reloadingHint") : status.state === "restart" ? t2("update.restartHint") : status.state === "failed" ? status.error === "OTHER_RELEASE_AGE" ? t2("update.otherAge", { names: status.detail ?? "" }) : status.error === "MINIMUM_RELEASE_AGE" ? status.exempt ? t2("update.ageStill", { detail: status.detail ?? "" }) : t2("update.tooNew") : status.error === "NETWORK" ? t2("update.network") : t2("update.failedHint", { error: status.detail ?? status.error ?? "" }) : status.installable ? t2("update.hint", { current: status.current, latest: status.latest ?? "" }) : t2("update.manualHint", { current: status.current, latest: status.latest ?? "" });
719
723
  const title = `${label} \xB7 ${hint}`;
720
724
  const act = (event) => {
721
725
  event.preventDefault();
722
726
  event.stopPropagation();
723
727
  if (status.state === "installing" || status.state === "reloading" || status.state === "restart") return;
724
- if (waiting || status.state === "failed" && status.error === "MINIMUM_RELEASE_AGE") {
728
+ if (!status.exempt && (waiting || status.state === "failed" && status.error === "MINIMUM_RELEASE_AGE")) {
725
729
  openReleaseAgeDialog(status);
726
730
  return;
727
731
  }
package/dist/update.d.ts CHANGED
@@ -12,8 +12,10 @@ 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
+ /** Why it failed: MINIMUM_RELEASE_AGE, OTHER_RELEASE_AGE (another package is too new), NETWORK, or the plugin manager's own code. */
16
16
  error?: string;
17
+ /** pnpm's own words about the failure, or the packages it refused. */
18
+ detail?: string;
17
19
  /** A newer npm version that pnpm will accept only once it is a day old, and when that is. */
18
20
  waiting?: {
19
21
  version: string;
@@ -31,6 +33,11 @@ export declare function releaseAgeExemptions(text: string): string[];
31
33
  * kept as it was. Throws for a layout it does not recognise rather than guess.
32
34
  */
33
35
  export declare function withReleaseAgeExemption(text: string, name?: string): string;
36
+ /**
37
+ * The packages pnpm refused for being too new, as `name@version`, read from its output
38
+ * ("dsh-theone@0.3.13 was published at …").
39
+ */
40
+ export declare function releaseAgeViolations(output: string): string[];
34
41
  /**
35
42
  * pnpm, which DSH installs plugins with, refuses npm versions published less than a day ago
36
43
  * (minimumReleaseAge, a supply-chain safeguard). Updates from npm wait until then.
@@ -66,6 +73,7 @@ export declare class Updater {
66
73
  private checked?;
67
74
  private state?;
68
75
  private error?;
76
+ private detail?;
69
77
  private pending?;
70
78
  /**
71
79
  * @param workspace - this DSH profile's pnpm-workspace.yaml, where pnpm reads the release-age
@@ -76,6 +84,8 @@ export declare class Updater {
76
84
  get exempt(): boolean;
77
85
  /** Exempt TheOne, and only TheOne, from pnpm's release-age rule in this profile. */
78
86
  allowFresh(): void;
87
+ /** Add exact `name@version` exemptions too, the form pnpm writes itself; returns whether the file changed. */
88
+ private exemptExact;
79
89
  get source(): UpdateSource;
80
90
  /** The latest known status; checks again at most every six hours (or now, when forced). */
81
91
  status(force?: boolean): Promise<UpdateStatus>;
package/dist/update.js CHANGED
@@ -43,6 +43,13 @@ export function withReleaseAgeExemption(text, name = PACKAGE_NAME) {
43
43
  lines.splice(end, 0, `${indent}- ${name}`);
44
44
  return lines.join(newline);
45
45
  }
46
+ /**
47
+ * The packages pnpm refused for being too new, as `name@version`, read from its output
48
+ * ("dsh-theone@0.3.13 was published at …").
49
+ */
50
+ export function releaseAgeViolations(output) {
51
+ return [...new Set([...output.matchAll(/^\s*((?:@[\w.-]+\/)?[\w.-]+@\d[\w.+-]*) was published at/gm)].map(match => match[1]))];
52
+ }
46
53
  /**
47
54
  * pnpm, which DSH installs plugins with, refuses npm versions published less than a day ago
48
55
  * (minimumReleaseAge, a supply-chain safeguard). Updates from npm wait until then.
@@ -75,6 +82,8 @@ export function installSource(spec) {
75
82
  return 'other';
76
83
  }
77
84
  const HOUR = 3600000;
85
+ const installed = (result) => result.application === 'applied' || result.application === 'restart-required';
86
+ const outputOf = (result) => `${result.packageResult?.output ?? ''}\n${result.error?.message ?? ''}`;
78
87
  /** Checks for a newer TheOne and installs it through DSH's own plugin manager. */
79
88
  export class Updater {
80
89
  current;
@@ -85,6 +94,7 @@ export class Updater {
85
94
  checked;
86
95
  state;
87
96
  error;
97
+ detail;
88
98
  pending;
89
99
  /**
90
100
  * @param workspace - this DSH profile's pnpm-workspace.yaml, where pnpm reads the release-age
@@ -130,6 +140,25 @@ export class Updater {
130
140
  if (this.state === 'failed') {
131
141
  this.state = undefined;
132
142
  this.error = undefined;
143
+ this.detail = undefined;
144
+ }
145
+ }
146
+ /** Add exact `name@version` exemptions too, the form pnpm writes itself; returns whether the file changed. */
147
+ exemptExact(entries) {
148
+ const file = this.workspace();
149
+ if (!file)
150
+ return false;
151
+ try {
152
+ const text = readFileSync(file, 'utf8');
153
+ const next = entries.reduce((current, entry) => withReleaseAgeExemption(current, entry), text);
154
+ if (next === text)
155
+ return false;
156
+ writeFileSync(`${file}.theone-tmp`, next, { mode: 0o600 });
157
+ renameSync(`${file}.theone-tmp`, file);
158
+ return true;
159
+ }
160
+ catch {
161
+ return false;
133
162
  }
134
163
  }
135
164
  get source() { return installSource(this.spec()); }
@@ -155,9 +184,19 @@ export class Updater {
155
184
  const spec = this.source === 'github' ? `github:${REPOSITORY}#${this.checked.sha}` : `${PACKAGE_NAME}@${status.latest}`;
156
185
  this.state = 'installing';
157
186
  this.error = undefined;
187
+ this.detail = undefined;
158
188
  try {
159
- const result = await installer.installBundle(spec, { enabled: true });
160
- if (result.application === 'applied' || result.application === 'restart-required') {
189
+ let result = await installer.installBundle(spec, { enabled: true });
190
+ let output = outputOf(result);
191
+ // pnpm also checks the lockfile, where the installed TheOne may itself be under a day old. If an
192
+ // exempt TheOne is still refused, exempt the exact versions involved, as pnpm does, and try once more.
193
+ const refused = /MINIMUM_RELEASE_AGE/.test(output) ? releaseAgeViolations(output) : [];
194
+ if (!installed(result) && this.source === 'npm' && this.exempt && refused.length && refused.every(entry => entry.startsWith(`${PACKAGE_NAME}@`))
195
+ && this.exemptExact([...refused, `${PACKAGE_NAME}@${this.current}`, `${PACKAGE_NAME}@${status.latest}`])) {
196
+ result = await installer.installBundle(spec, { enabled: true });
197
+ output = outputOf(result);
198
+ }
199
+ if (installed(result)) {
161
200
  this.state = reload ? 'reloading' : 'restart';
162
201
  reload?.(result.bundle ?? PACKAGE_NAME);
163
202
  }
@@ -165,10 +204,12 @@ export class Updater {
165
204
  this.state = 'failed';
166
205
  const error = result.error;
167
206
  // pnpm's own reasons are clearer than the plugin manager's generic failure.
168
- const output = `${result.packageResult?.output ?? ''}\n${error?.message ?? ''}`;
169
- this.error = /MINIMUM_RELEASE_AGE/.test(output) ? 'MINIMUM_RELEASE_AGE'
207
+ const violations = /MINIMUM_RELEASE_AGE/.test(output) ? releaseAgeViolations(output) : [];
208
+ const others = violations.filter(entry => !entry.startsWith(`${PACKAGE_NAME}@`));
209
+ this.error = others.length ? 'OTHER_RELEASE_AGE' : /MINIMUM_RELEASE_AGE/.test(output) ? 'MINIMUM_RELEASE_AGE'
170
210
  : /UND_ERR|ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|ERR_PNPM_META_FETCH_FAIL|network/i.test(output) ? 'NETWORK'
171
211
  : String(error?.code ?? error?.message ?? result.application).slice(0, 120);
212
+ this.detail = (others.length ? others.join(', ') : output.match(/ERR_PNPM_\w+[^\n]*(?:\n[^\n]+)?/)?.[0] ?? '').trim().slice(0, 300) || undefined;
172
213
  }
173
214
  }
174
215
  catch (error) {
@@ -188,7 +229,8 @@ export class Updater {
188
229
  return { current: this.current, ...(latest ? { latest } : {}), available, source, ...waiting,
189
230
  ...(source === 'npm' ? { exempt, canExempt: !!this.workspace() } : {}),
190
231
  installable: available && (source === 'npm' || (source === 'github' && !!this.checked?.sha)),
191
- ...(this.state ? { state: this.state } : {}), ...(this.error ?? this.checked?.error ? { error: this.error ?? this.checked?.error } : {}) };
232
+ ...(this.state ? { state: this.state } : {}), ...(this.error ?? this.checked?.error ? { error: this.error ?? this.checked?.error } : {}),
233
+ ...(this.detail ? { detail: this.detail } : {}) };
192
234
  }
193
235
  async check() {
194
236
  const signal = AbortSignal.timeout(10000);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-theone",
3
- "version": "0.3.19",
3
+ "version": "0.3.20",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Automatic context routing for DeepSeek Harness",