dshmarket 1.72.0 → 1.72.1

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.
Files changed (85) hide show
  1. package/lib/profile.js +8 -3
  2. package/lib/routes.js +7 -1
  3. package/package.json +1 -2
  4. package/src/accelerate.ts +0 -222
  5. package/src/agents.ts +0 -43
  6. package/src/backup.ts +0 -631
  7. package/src/catalog-local-match.ts +0 -185
  8. package/src/catalog-npm.ts +0 -152
  9. package/src/changelog.ts +0 -501
  10. package/src/channels.ts +0 -70
  11. package/src/check.ts +0 -1699
  12. package/src/client/CommentsModal.tsx +0 -119
  13. package/src/client/Diagnostics.tsx +0 -987
  14. package/src/client/ErrorBoundary.tsx +0 -111
  15. package/src/client/HostRecoveryBanner.tsx +0 -153
  16. package/src/client/InstallToast.tsx +0 -32
  17. package/src/client/Market.module.css +0 -1189
  18. package/src/client/MarketSection.tsx +0 -8615
  19. package/src/client/OperationsPanel.tsx +0 -416
  20. package/src/client/RecoveryPanel.tsx +0 -280
  21. package/src/client/SearchInput.tsx +0 -119
  22. package/src/client/SettingsCard.tsx +0 -759
  23. package/src/client/comments.ts +0 -54
  24. package/src/client/download-stats.ts +0 -30
  25. package/src/client/globals.d.ts +0 -31
  26. package/src/client/host-navigation.ts +0 -44
  27. package/src/client/icons.ts +0 -132
  28. package/src/client/index.ts +0 -440
  29. package/src/client/locales.ts +0 -2328
  30. package/src/client/market-data.ts +0 -1720
  31. package/src/client/market-element.ts +0 -80
  32. package/src/client/market-mark.ts +0 -60
  33. package/src/client/operations.ts +0 -382
  34. package/src/client/optional-primitives.ts +0 -90
  35. package/src/client/preset-panel.tsx +0 -263
  36. package/src/client/primitives.d.ts +0 -172
  37. package/src/client/section-gate.ts +0 -81
  38. package/src/client/self-check.ts +0 -147
  39. package/src/client/settings-nav-icon.ts +0 -174
  40. package/src/client/sidebar-entry.ts +0 -175
  41. package/src/client/snapshot-panel.tsx +0 -244
  42. package/src/compatibility.ts +0 -280
  43. package/src/diagnostics.ts +0 -84
  44. package/src/discovery-compatibility.ts +0 -444
  45. package/src/dsh-cli.ts +0 -1619
  46. package/src/dsh-install.ts +0 -207
  47. package/src/entry-identity.ts +0 -84
  48. package/src/gist.ts +0 -359
  49. package/src/groups.ts +0 -121
  50. package/src/home-paths.ts +0 -34
  51. package/src/host-recovery.ts +0 -208
  52. package/src/hot.ts +0 -1013
  53. package/src/http.ts +0 -271
  54. package/src/index.ts +0 -406
  55. package/src/install.ts +0 -1111
  56. package/src/lifecycle.ts +0 -35
  57. package/src/log-redaction.ts +0 -24
  58. package/src/log.ts +0 -205
  59. package/src/ndjson.ts +0 -185
  60. package/src/net.ts +0 -153
  61. package/src/official-desktop.ts +0 -624
  62. package/src/order.ts +0 -303
  63. package/src/patch.ts +0 -700
  64. package/src/pending-rows.ts +0 -178
  65. package/src/pending-updates.ts +0 -356
  66. package/src/pnpm-compat.ts +0 -908
  67. package/src/presets.ts +0 -355
  68. package/src/profile.ts +0 -1829
  69. package/src/recovery.ts +0 -1205
  70. package/src/region-probe.ts +0 -97
  71. package/src/regions.ts +0 -367
  72. package/src/registry.ts +0 -532
  73. package/src/release-candidates.ts +0 -115
  74. package/src/restart.ts +0 -723
  75. package/src/routes.ts +0 -7185
  76. package/src/settings.ts +0 -214
  77. package/src/snapshot.ts +0 -532
  78. package/src/source-migration.ts +0 -195
  79. package/src/sources.ts +0 -984
  80. package/src/store.ts +0 -155
  81. package/src/themes.ts +0 -333
  82. package/src/trial.ts +0 -163
  83. package/src/update-api-v1.ts +0 -302
  84. package/src/updates.ts +0 -981
  85. package/src/verify.ts +0 -1009
package/lib/profile.js CHANGED
@@ -1491,6 +1491,11 @@ export function setAllowBuilds(profile, packages, explicitDir) {
1491
1491
  const SEG = '[A-Za-z0-9_-][A-Za-z0-9_.-]*';
1492
1492
  const NAME = '[A-Za-z0-9@/_.-]+';
1493
1493
  const SHA = '[0-9a-f]{40}';
1494
+ // A dependency pnpm resolved from a BRANCH keys its decision by the ref,
1495
+ // not by a commit: `name@https://codeload.github.com/o/r/tar.gz/refs/heads/main`
1496
+ // (#1034). The ref is path segments only — no `.`/`..`, no empty piece —
1497
+ // so it cannot walk out of the URL it is written into.
1498
+ const REF = `refs/(?:heads|tags)/${SEG}(?:/${SEG})*`;
1494
1499
  // pnpm's exact monorepo key includes the selected directory; dropping it
1495
1500
  // makes approve-and-retry write only a bare name that git builds ignore.
1496
1501
  const DIR = '(?!\\.{1,2}(?:/|$))[A-Za-z0-9_.-]+';
@@ -1512,9 +1517,9 @@ export function setAllowBuilds(profile, packages, explicitDir) {
1512
1517
  // gitlab.com and bitbucket.org (#637). Each branch names its host and its
1513
1518
  // exact path shape.
1514
1519
  const ARCHIVE_KEY_RE = new RegExp(`^${NAME}@https://(?:`
1515
- + `codeload\\.github\\.com/${SEG}/${SEG}/tar\\.gz/${SHA}`
1516
- + `|bitbucket\\.org/${SEG}/${SEG}/get/${SHA}\\.tar\\.gz`
1517
- + `|gitlab\\.com/${SEG}(?:/${SEG})+/-/archive/${SHA}/${SEG}-${SHA}\\.tar\\.gz`
1520
+ + `codeload\\.github\\.com/${SEG}/${SEG}/tar\\.gz/(?:${SHA}|${REF})`
1521
+ + `|bitbucket\\.org/${SEG}/${SEG}/get/(?:${SHA}|${REF})\\.tar\\.gz`
1522
+ + `|gitlab\\.com/${SEG}(?:/${SEG})+/-/archive/(?:${SHA}|${REF})/${SEG}-(?:${SHA}|${REF})\\.tar\\.gz`
1518
1523
  + `)(?:#${SUBPATH})?$`);
1519
1524
  for (const pkg of packages) {
1520
1525
  if (/^[A-Za-z0-9@/_.-]+$/.test(pkg) || GIT_KEY_RE.test(pkg) || ARCHIVE_KEY_RE.test(pkg))
package/lib/routes.js CHANGED
@@ -6923,7 +6923,13 @@ export function mountMarketRoutes(host, config, commandRuntime, agentsLookup, ho
6923
6923
  // where the button is not (#314). The panel now carries
6924
6924
  // the action on this very row, so the text can just say
6925
6925
  // what to press.
6926
- ? `构建脚本被 pnpm 默认拦截(${ignoredBuilds.join(', ')}),点击「放行构建脚本并重试」即可放行并重装 / build scripts are blocked by pnpm by default (${ignoredBuilds.join(', ')}); use "Allow build scripts and retry" to approve and reinstall`
6926
+ // #1034: pnpm reports every undecided build in the
6927
+ // workspace, not only the ones this operation needed — an
6928
+ // entry left from an earlier install shows up here too, and
6929
+ // saying "this install needs dsh-purge approved" was wrong
6930
+ // for a plugin that never depended on it. Name them as
6931
+ // decisions, with where the decision is written.
6932
+ ? `pnpm 要求先决定这些依赖能否运行构建脚本(${ignoredBuilds.join(', ')}):有的是这次安装带进来的,也可能是之前留下的未决定条目。点「放行构建脚本并重试」会把它们写进 pnpm-workspace.yaml 的 allowBuilds,然后重新安装 / pnpm wants a decision on these packages before it runs their build scripts (${ignoredBuilds.join(', ')}); some came in with this install, and some may be entries an earlier one left undecided. "Allow build scripts and retry" writes them into allowBuilds in pnpm-workspace.yaml and installs again`
6927
6933
  // Same last resort as the update route (#848), and on THIS
6928
6934
  // route too: a recognized failure like an expired
6929
6935
  // `patchedDependencies` key had no branch here either.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dshmarket",
3
3
  "description": "Visual plugin market inside DeepSeek Harness — browse, search, and one-click install community plugins. · DSH 可视化插件市场:逛一逛,点一下,装好。",
4
- "version": "1.72.0",
4
+ "version": "1.72.1",
5
5
  "icon": "assets/logo.svg",
6
6
  "type": "module",
7
7
  "main": "lib/index.js",
@@ -76,7 +76,6 @@
76
76
  "assets/logo.svg",
77
77
  "locale",
78
78
  "lib",
79
- "src",
80
79
  "client",
81
80
  "UPDATE-API-V1.md",
82
81
  "cordis.patch.yml",
package/src/accelerate.ts DELETED
@@ -1,222 +0,0 @@
1
- /**
2
- * Resolving a GitHub install through a region's proxy without proxying the
3
- * tarball pnpm records.
4
- *
5
- * pnpm does not fetch `github:owner/repo` with `git clone`; it resolves the
6
- * shortcut and downloads a tarball from codeload.github.com. That rules out
7
- * the usual `git config insteadOf` trick — there is no git command to
8
- * redirect.
9
- *
10
- * Prefix-proxying that tarball used to save substantial time, but pnpm 11's
11
- * fail-closed lockfile checks changed the safety boundary. A URL shaped like
12
- * `https://proxy/https://codeload.github.com/.../<commit>` no longer has the
13
- * codeload hostname, so pnpm treats it as an ordinary remote tarball and
14
- * requires an integrity hash that its GitHub resolver does not write. The
15
- * result is ERR_PNPM_MISSING_TARBALL_INTEGRITY on the install itself (#385).
16
- * Disabling that check or minting a checksum from whatever the proxy served
17
- * would weaken pnpm's supply-chain protection, so neither is acceptable.
18
- *
19
- * The safe middle ground is to resolve HEAD through the regional proxy, then
20
- * hand pnpm a commit-pinned `github:owner/repo#<sha>` target. The ref lookup
21
- * still avoids a slow or unreachable GitHub metadata request; pnpm itself
22
- * fetches the canonical codeload URL, records it as `gitHosted: true`, and
23
- * keeps its integrity policy intact.
24
- *
25
- * - **The commit has to be pinned.** The profile reads each plugin's
26
- * installed commit back out of the lockfile by matching a codeload URL
27
- * ending in a 40-character SHA (src/profile.ts). A `HEAD` tarball installs
28
- * perfectly and then reports no version forever. So this resolves the SHA
29
- * first, and a rewrite that cannot get one does not happen.
30
- * - **Build-script approval has to keep matching.** `gitAllowBuildsKey`
31
- * (src/sources.ts) derives its stable key from the repo, and the pinned
32
- * GitHub form preserves that identity.
33
- *
34
- * Catalog subpath entries are left alone: `#path:` identifies a different
35
- * package inside the repo, so the acceleration step never rewrites that
36
- * fragment. Collection roots discovered after install preserve the resolved
37
- * commit and add their subpath as pnpm's second `&path:` selector.
38
- *
39
- * Every SHA-lookup failure falls back to the original target. Acceleration
40
- * is an optimisation, and an optimisation that can fail an install is a bug.
41
- */
42
-
43
- import { logEvent } from './log.ts'
44
- import { marketFetch } from './net.ts'
45
- import {
46
- githubRoutesFor, rememberGithubRoute, routesFor, throughProxy, type GithubRoute, type Region,
47
- } from './regions.ts'
48
-
49
- /** A bare repo shortcut whose HEAD can be replaced by one immutable ref. */
50
- const BARE_GITHUB_RE = /^github:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)$/
51
-
52
- /**
53
- * How long to wait for the SHA before giving up and installing directly.
54
- *
55
- * Short on purpose: this is spent BEFORE the download starts, and the whole
56
- * point is to avoid a slow or unreachable direct metadata lookup. A proxy
57
- * that cannot answer promptly should not delay pnpm's ordinary direct path.
58
- */
59
- const RESOLVE_TIMEOUT_MS = 6000
60
-
61
- /**
62
- * The commit `HEAD` points at, from git's own ref advertisement.
63
- *
64
- * This is the endpoint `git clone` reads before it fetches anything, and it
65
- * is the right one here for two measured reasons. It is not the REST API, so
66
- * it does not consume the 60-requests-per-hour unauthenticated quota that a
67
- * user installing a handful of plugins could plausibly exhaust. And it
68
- * survives the proxy: over five consecutive tries from an unproxied mainland
69
- * connection it answered 200 in ~1.2s every time, while the REST API through
70
- * the same proxy returned 200, 200, then 403 — a proxy that rate-limits the
71
- * API path would silently drop every install back to the slow route.
72
- *
73
- * The response is git's pkt-line format, whose first ref line carries
74
- * `<sha> HEAD\0<capabilities>`. Read with a pattern rather than a parser:
75
- * one 40-character hex string followed by `HEAD` is unambiguous in this
76
- * payload, and a length-prefix reader would be more code to get wrong.
77
- *
78
- * The same advertisement lists every branch and tag, which is what `ref`
79
- * uses. A plugin installed from `github:owner/repo#publish` is not asking
80
- * about the default branch at all, and answering with it made the market
81
- * report an update forever (#446) — the two SHAs simply never match. Both
82
- * namespaces are searched because pnpm accepts a tag there too, branches
83
- * first since that is what the reports are about.
84
- * @param ref - branch or tag to resolve, or undefined for the default branch.
85
- */
86
- export async function headCommit(
87
- repo: string,
88
- proxy: string | null,
89
- signal?: AbortSignal,
90
- ref?: string,
91
- ): Promise<string | null> {
92
- const result = await tryHeadCommit(repo, proxy, signal, ref)
93
- return result.kind === 'valid' ? result.sha : null
94
- }
95
-
96
- type HeadAttempt =
97
- | { kind: 'valid'; sha: string | null }
98
- | { kind: 'failed' }
99
-
100
- /** One route attempt, preserving valid "ref is absent" from invalid payloads. */
101
- async function tryHeadCommit(
102
- repo: string,
103
- proxy: GithubRoute,
104
- signal?: AbortSignal,
105
- ref?: string,
106
- ): Promise<HeadAttempt> {
107
- const base = `https://github.com/${repo}/info/refs?service=git-upload-pack`
108
- try {
109
- const res = await marketFetch(throughProxy(proxy, base), {
110
- signal,
111
- headers: { 'user-agent': 'git/2.40.0' },
112
- })
113
- if (!res.ok) return { kind: 'failed' }
114
- const body = await res.text()
115
- const contentType = (res as Response & { headers?: { get?(name: string): string | null } })
116
- .headers?.get?.('content-type')?.toLowerCase() ?? ''
117
- // Public mirrors often answer a failed upstream request with their own
118
- // branded HTML and status 200. A git advertisement has both its service
119
- // prelude and at least one advertised ref; accepting anything else would
120
- // cache a route that never returned Git data in the first place.
121
- if (contentType.includes('text/html')
122
- || !body.includes('# service=git-upload-pack')
123
- || !/[0-9a-f]{40} (?:HEAD|refs\/(?:heads|tags)\/)/u.test(body)) {
124
- return { kind: 'failed' }
125
- }
126
- if (ref === undefined) {
127
- const found = /([0-9a-f]{40}) HEAD/.exec(body)
128
- return { kind: 'valid', sha: found === null ? null : found[1]! }
129
- }
130
- // Anchored to the ref's full name so `publish` cannot match a branch
131
- // called `publish-old`, and escaped because a ref may contain regex
132
- // metacharacters (`.` is legal in a branch name).
133
- const quoted = ref.replace(/[.*+?^${}()|[\]\\]/gu, String.raw`\$&`)
134
- for (const namespace of ['heads', 'tags']) {
135
- // An annotated tag advertises two refs — the tag object and its
136
- // peeled commit (`refs/tags/<ref>^{}`). pnpm resolves the tag to the
137
- // peeled commit and codeload records that sha in the lockfile, so the
138
- // peeled line is the one that must equal `current`; answering with
139
- // the tag-object sha made annotated-tag installs report an update
140
- // forever (#597). Lightweight tags have no peeled line and fall
141
- // through to the direct one.
142
- const peeled = new RegExp(String.raw`([0-9a-f]{40}) refs/${namespace}/${quoted}\^\{\}(?![^\s])`, 'u').exec(body)
143
- if (peeled !== null) return { kind: 'valid', sha: peeled[1]! }
144
- const found = new RegExp(String.raw`([0-9a-f]{40}) refs/${namespace}/${quoted}(?![^\s])`, 'u').exec(body)
145
- if (found !== null) return { kind: 'valid', sha: found[1]! }
146
- }
147
- // The advertisement is authoritative for this repository. Asking another
148
- // mirror cannot make a branch that is absent here appear.
149
- return { kind: 'valid', sha: null }
150
- } catch {
151
- return { kind: 'failed' }
152
- }
153
- }
154
-
155
- /** Run one candidate under its own budget, optionally linked to a caller signal. */
156
- async function timedHeadCommit(
157
- repo: string,
158
- route: GithubRoute,
159
- ref?: string,
160
- signal?: AbortSignal,
161
- ): Promise<HeadAttempt> {
162
- const controller = new AbortController()
163
- const abort = (): void => { controller.abort() }
164
- if (signal?.aborted === true) controller.abort()
165
- else signal?.addEventListener('abort', abort, { once: true })
166
- const timer = setTimeout(abort, RESOLVE_TIMEOUT_MS)
167
- try {
168
- return await tryHeadCommit(repo, route, controller.signal, ref)
169
- } finally {
170
- clearTimeout(timer)
171
- signal?.removeEventListener('abort', abort)
172
- }
173
- }
174
-
175
- /**
176
- * The current `HEAD` commit for a repo, on whichever route the region uses.
177
- *
178
- * Wraps the timeout so callers outside the install path — the build-script
179
- * approval below, which needs a commit-pinned key — do not each reinvent it.
180
- */
181
- export async function resolveHeadCommit(
182
- repo: string,
183
- region: Region,
184
- env: NodeJS.ProcessEnv = process.env,
185
- ref?: string,
186
- ): Promise<string | null> {
187
- for (const route of githubRoutesFor('git', region, env)) {
188
- const result = await timedHeadCommit(repo, route, ref)
189
- if (result.kind === 'failed') continue
190
- rememberGithubRoute('git', route)
191
- return result.sha
192
- }
193
- return null
194
- }
195
-
196
- /**
197
- * The install target to actually hand pnpm, given the region in force.
198
- *
199
- * @param target - what `installTargetFor` produced.
200
- * @param region - the download region.
201
- * @param env - environment, for the proxy override.
202
- * @returns a commit-pinned GitHub shortcut when one route resolves HEAD,
203
- * otherwise `target` unchanged.
204
- */
205
- export async function acceleratedTarget(
206
- target: string,
207
- region: Region,
208
- env: NodeJS.ProcessEnv = process.env,
209
- ): Promise<string> {
210
- // A plain global install lets pnpm do its ordinary GitHub resolution. A
211
- // custom prefix makes even that region an accelerated one.
212
- if (routesFor(region, env).githubProxy === null) return target
213
- const bare = BARE_GITHUB_RE.exec(target)
214
- if (bare === null) return target
215
- const repo = bare[1]!
216
- const sha = await resolveHeadCommit(repo, region, env)
217
- if (sha === null) {
218
- logEvent('info', 'region', `${repo}: could not resolve a commit through the available routes; installing directly`)
219
- return target
220
- }
221
- return `github:${repo}#${sha}`
222
- }
package/src/agents.ts DELETED
@@ -1,43 +0,0 @@
1
- /**
2
- * Optional host-provided agent inventory: lets the market refuse plugin
3
- * mutations while a live agent is mid-turn. Mutating `node_modules` under a
4
- * running agent replaces files the running plugin modules may still read or
5
- * lazily import — the update "succeeds" while old code and new files mix.
6
- */
7
-
8
- export interface RunningAgentLike {
9
- id?: unknown
10
- status?: unknown
11
- }
12
-
13
- export interface AgentsServiceLike {
14
- list(): RunningAgentLike[]
15
- }
16
-
17
- export type AgentsLookup = () => AgentsServiceLike | undefined
18
-
19
- /**
20
- * Ids of the host's currently running agents, or [] when the host has no
21
- * agents service. Only a positive `status === 'running'` blocks an update —
22
- * unknown statuses are treated as not running, so a future agent
23
- * implementation with different wording fails open (the market stays
24
- * usable) instead of wedging the plugin page.
25
- */
26
- export function runningAgentIds(agents: AgentsServiceLike | undefined): string[] {
27
- if (agents === undefined) return []
28
- let listed: RunningAgentLike[]
29
- try {
30
- listed = agents.list()
31
- } catch {
32
- // A half-disposed registry must never take the market's routes down.
33
- return []
34
- }
35
- if (!Array.isArray(listed)) return []
36
- const ids: string[] = []
37
- for (const agent of listed) {
38
- if (agent === null || typeof agent !== 'object' || agent.status !== 'running') continue
39
- const id = typeof agent.id === 'string' && agent.id !== '' ? agent.id : 'agent'
40
- if (!ids.includes(id)) ids.push(id)
41
- }
42
- return ids
43
- }