dsh-update-status 0.1.6 → 0.1.8

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.d.ts CHANGED
@@ -22,6 +22,23 @@ type ReleaseCompatibility = 'verified' | 'unverified' | 'incompatible';
22
22
  */
23
23
  type UpdateWarningKind = 'failure' | 'notice';
24
24
  type InstallKind = 'npm-global' | 'pnpm-global' | 'source-checkout' | 'unknown';
25
+ /** Language-neutral warning facts; the browser renders them in its own locale. */
26
+ type UpdateWarning = {
27
+ code: 'registry-unavailable';
28
+ detail: string;
29
+ } | {
30
+ code: 'channel-unavailable';
31
+ channel: ReleaseChannel;
32
+ } | {
33
+ code: 'version-incomparable';
34
+ currentVersion: string;
35
+ channel: ReleaseChannel;
36
+ selectedVersion: string;
37
+ } | {
38
+ code: 'preview-unverified';
39
+ channel: ReleaseChannel;
40
+ version: string;
41
+ };
25
42
  interface ChannelRelease {
26
43
  channel: ReleaseChannel;
27
44
  version: string | null;
@@ -39,9 +56,12 @@ interface UpdateStatus {
39
56
  hasUpdate: boolean;
40
57
  cached: boolean;
41
58
  checkedAt: string | null;
59
+ /** English fallback for older clients; current clients localize `warnings`. */
42
60
  warning: string | null;
43
61
  /** Severity of `warning`; absent from a Host older than the field. */
44
62
  warningKind?: UpdateWarningKind | null;
63
+ /** Structured warning facts; absent from a Host older than this field. */
64
+ warnings?: UpdateWarning[];
45
65
  installKind: InstallKind;
46
66
  upgradeCommand: string;
47
67
  releaseUrl: string;
@@ -80,7 +100,7 @@ interface UpdateStatusConfig {
80
100
  * input side takes, so the inferred schema type cannot be named by the emitted
81
101
  * `.d.ts` (TS2883) without stating the input side here.
82
102
  */
83
- declare const Config: z<UpdateStatusConfig, Record<string, unknown>>;
103
+ export declare const Config: z<UpdateStatusConfig, Record<string, unknown>>;
84
104
  //#endregion
85
105
  //#region src/host/installation.d.ts
86
106
  interface InstallationInfo {
@@ -104,7 +124,7 @@ interface UpdateStatusServiceOptions {
104
124
  ttlMs?: number;
105
125
  releaseUrl?: string;
106
126
  }
107
- declare class UpdateStatusService {
127
+ export declare class UpdateStatusService {
108
128
  private readonly installation;
109
129
  private readonly fetchLatest;
110
130
  private readonly now;
@@ -119,15 +139,14 @@ declare class UpdateStatusService {
119
139
  private refreshRelease;
120
140
  private statusAfterFailure;
121
141
  private statusFromCache;
122
- /** No remote data at all: the registry read itself failed, never a notice. */
123
142
  private statusWithoutRemoteRelease;
124
143
  }
125
144
  //#endregion
126
145
  //#region src/index.d.ts
127
- declare const name = "dsh-update-status";
146
+ export declare const name = "dsh-update-status";
128
147
  /** Connection supplies the authenticated transport; settings remains optional. */
129
- declare const inject: string[];
130
- type Config = UpdateStatusConfig;
131
- declare function apply(ctx: Context, config?: Config): void;
148
+ export declare const inject: string[];
149
+ export type Config = UpdateStatusConfig;
150
+ export declare function apply(ctx: Context, config?: Config): void;
132
151
  //#endregion
133
- export { Config, type InstallKind, type UpdateStatus, UpdateStatusService, apply, inject, name };
152
+ export type { InstallKind, UpdateStatus };
package/lib/index.js CHANGED
@@ -12,7 +12,11 @@ const UPDATE_STATUS_CHANNEL = "/api";
12
12
  * release the registry reports stays `unverified` — the plugin never claims a
13
13
  * compatibility nobody checked.
14
14
  */
15
- const VERIFIED_DSH_VERSIONS = ["0.1.7-alpha.2", "0.1.7-rc.1"];
15
+ const VERIFIED_DSH_VERSIONS = [
16
+ "0.1.7-alpha.2",
17
+ "0.1.7-rc.1",
18
+ "0.1.7-rc.2"
19
+ ];
16
20
  const RELEASE_CHANNELS = [
17
21
  "latest",
18
22
  "next",
@@ -124,8 +128,8 @@ function upgradeCommandFor(installKind, packageName = PACKAGE_NAME, channel = "l
124
128
  switch (installKind) {
125
129
  case "npm-global": return `npm install -g ${specifier}`;
126
130
  case "pnpm-global": return `pnpm add -g ${specifier}`;
127
- case "source-checkout": return "在 DSH checkout 中拉取代码、安装依赖并重新构建;插件不会从 GUI 原地替换";
128
- default: return "请确认 dsh 安装方式后再升级;当前插件不会代为执行";
131
+ case "source-checkout": return "Update the DSH source checkout, install its dependencies, and rebuild it; this plugin cannot replace it in place from the GUI";
132
+ default: return "Confirm how DSH was installed before upgrading; this plugin cannot perform the upgrade for you";
129
133
  }
130
134
  }
131
135
  /**
@@ -313,10 +317,20 @@ function boundedMessage(error) {
313
317
  const trimmed = (error instanceof Error ? error.message : String(error)).replace(/\s+/g, " ").trim();
314
318
  return trimmed === "" ? "unknown error" : trimmed.slice(0, 220);
315
319
  }
316
- function warningWith(base, addition) {
317
- if (base === null || base === "") return addition;
318
- if (addition === null || addition === "") return base;
319
- return `${base} ${addition}`;
320
+ function warningText(warning) {
321
+ switch (warning.code) {
322
+ case "registry-unavailable": return `Unable to check the npm registry: ${warning.detail}`;
323
+ case "channel-unavailable": return `The npm registry does not publish a ${warning.channel} channel.`;
324
+ case "version-incomparable": return `Unable to compare the current version ${warning.currentVersion} with ${warning.channel} channel version ${warning.selectedVersion} using SemVer.`;
325
+ case "preview-unverified": return `${warning.channel} is a preview channel; version ${warning.version} has not been verified as compatible with this plugin.`;
326
+ }
327
+ }
328
+ function warningFallback(warnings) {
329
+ return warnings.length === 0 ? null : warnings.map(warningText).join(" ");
330
+ }
331
+ function warningKindOf(warnings) {
332
+ if (warnings.length === 0) return null;
333
+ return warnings.every((warning) => warning.code === "preview-unverified") ? "notice" : "failure";
320
334
  }
321
335
  function dateOrNull(value) {
322
336
  if (typeof value !== "string" || value === "") return null;
@@ -401,16 +415,16 @@ var UpdateStatusService = class {
401
415
  async check(force = false, channel = "latest", cacheTtlMinutes) {
402
416
  const ttlMs = isCacheTtlMinutes(cacheTtlMinutes) ? cacheTtlMinutes * 60 * 1e3 : this.ttlMs;
403
417
  const cached = this.cache;
404
- if (!force && cached !== void 0 && this.now() - cached.checkedAtMs < ttlMs) return this.statusFromCache(cached, channel, true, null);
418
+ if (!force && cached !== void 0 && this.now() - cached.checkedAtMs < ttlMs) return this.statusFromCache(cached, channel, true, []);
405
419
  if (this.inFlight !== void 0) try {
406
- return this.statusFromCache(await this.inFlight, channel, false, null);
420
+ return this.statusFromCache(await this.inFlight, channel, false, []);
407
421
  } catch (error) {
408
422
  return this.statusAfterFailure(channel, error);
409
423
  }
410
424
  const run = this.refreshRelease();
411
425
  this.inFlight = run;
412
426
  try {
413
- return this.statusFromCache(await run, channel, false, null);
427
+ return this.statusFromCache(await run, channel, false, []);
414
428
  } catch (error) {
415
429
  return this.statusAfterFailure(channel, error);
416
430
  } finally {
@@ -426,10 +440,13 @@ var UpdateStatusService = class {
426
440
  return cache;
427
441
  }
428
442
  statusAfterFailure(channel, error) {
429
- const warning = `无法检查 npm registry:${boundedMessage(error)}`;
430
- return this.cache === void 0 ? this.statusWithoutRemoteRelease(channel, warning) : this.statusFromCache(this.cache, channel, true, warning);
443
+ const warnings = [{
444
+ code: "registry-unavailable",
445
+ detail: boundedMessage(error)
446
+ }];
447
+ return this.cache === void 0 ? this.statusWithoutRemoteRelease(channel, warnings) : this.statusFromCache(this.cache, channel, true, warnings);
431
448
  }
432
- statusFromCache(cache, channel, cached, initialWarning) {
449
+ statusFromCache(cache, channel, cached, initialWarnings) {
433
450
  const selected = cache.release.channels.find((release) => release.channel === channel) ?? {
434
451
  channel,
435
452
  version: null,
@@ -437,19 +454,31 @@ var UpdateStatusService = class {
437
454
  compatibility: "unverified"
438
455
  };
439
456
  const comparison = selected.version === null ? void 0 : compareSemver(this.installation.currentVersion, selected.version);
440
- const missingWarning = selected.version === null ? `npm registry 未发布 ${channel} 通道。` : null;
441
- const comparisonWarning = selected.version !== null && comparison === void 0 ? `无法按 SemVer 比较当前版本 ${this.installation.currentVersion} 与 ${channel} 通道版本 ${selected.version}。` : null;
442
- const previewWarning = channel !== "latest" && selected.version !== null && selected.compatibility !== "verified" ? `${channel} 是预览通道,版本 ${selected.version} 尚未验证与本插件兼容。` : null;
443
- const failureWarning = warningWith(warningWith(initialWarning, missingWarning), comparisonWarning);
444
- const warning = warningWith(failureWarning, previewWarning);
457
+ const warnings = [...initialWarnings];
458
+ if (selected.version === null) warnings.push({
459
+ code: "channel-unavailable",
460
+ channel
461
+ });
462
+ if (selected.version !== null && comparison === void 0) warnings.push({
463
+ code: "version-incomparable",
464
+ currentVersion: this.installation.currentVersion,
465
+ channel,
466
+ selectedVersion: selected.version
467
+ });
468
+ if (channel !== "latest" && selected.version !== null && selected.compatibility !== "verified") warnings.push({
469
+ code: "preview-unverified",
470
+ channel,
471
+ version: selected.version
472
+ });
445
473
  return {
446
474
  currentVersion: this.installation.currentVersion,
447
475
  latestVersion: selected.version,
448
476
  hasUpdate: comparison !== void 0 && comparison < 0,
449
477
  cached,
450
478
  checkedAt: new Date(cache.checkedAtMs).toISOString(),
451
- warning,
452
- warningKind: warning === null ? null : failureWarning === null ? "notice" : "failure",
479
+ warning: warningFallback(warnings),
480
+ warningKind: warningKindOf(warnings),
481
+ warnings,
453
482
  installKind: this.installation.installKind,
454
483
  upgradeCommand: upgradeCommandFor(this.installation.installKind, this.installation.packageName || "@deepseek-ai/dsh", channel),
455
484
  releaseUrl: this.releaseUrl,
@@ -461,16 +490,16 @@ var UpdateStatusService = class {
461
490
  canApplyInPlace: false
462
491
  };
463
492
  }
464
- /** No remote data at all: the registry read itself failed, never a notice. */
465
- statusWithoutRemoteRelease(channel, warning) {
493
+ statusWithoutRemoteRelease(channel, warnings) {
466
494
  return {
467
495
  currentVersion: this.installation.currentVersion,
468
496
  latestVersion: null,
469
497
  hasUpdate: false,
470
498
  cached: false,
471
499
  checkedAt: null,
472
- warning,
473
- warningKind: "failure",
500
+ warning: warningFallback(warnings),
501
+ warningKind: warningKindOf(warnings),
502
+ warnings,
474
503
  installKind: this.installation.installKind,
475
504
  upgradeCommand: upgradeCommandFor(this.installation.installKind, this.installation.packageName || "@deepseek-ai/dsh", channel),
476
505
  releaseUrl: this.releaseUrl,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-update-status",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Read-only DeepSeek Harness Web plugin that shows the running DSH version, discovers latest/next/alpha releases, warns about compatibility, and generates copy-only upgrade commands.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -63,7 +63,8 @@
63
63
  "compatibility": {
64
64
  "dshReleases": {
65
65
  "0.1.7-alpha.2": "compatible",
66
- "0.1.7-rc.1": "compatible"
66
+ "0.1.7-rc.1": "compatible",
67
+ "0.1.7-rc.2": "compatible"
67
68
  }
68
69
  }
69
70
  },
@@ -88,9 +89,9 @@
88
89
  "@types/node": "^26.2.0",
89
90
  "@types/react": "^18.3.31",
90
91
  "react": "^18.3.1",
91
- "tsdown": "^0.22.14",
92
+ "tsdown": "^0.23.0",
92
93
  "typescript": "^7.0.2",
93
- "vitest": "^4.1.11"
94
+ "vitest": "^5.0.1"
94
95
  },
95
96
  "scripts": {
96
97
  "build": "tsdown",