dshmarket 1.29.0 → 1.29.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.
@@ -33,11 +33,6 @@ export interface ActivationResult {
33
33
  /** True when the package is live in the running composition. */
34
34
  hot: boolean;
35
35
  }
36
- /**
37
- * Verify the activation state of one installed package.
38
- * @param live - names live in the current composition; defaults to the
39
- * market's hot-mount table (injectable for tests).
40
- */
41
36
  export declare function verifyActivation(profile: string, name: string, live?: ReadonlySet<string>, explicitDir?: string, isDisabled?: boolean): ActivationResult;
42
37
  /**
43
38
  * Correct a post-UPDATE verdict for a plugin that was already running.
package/lib/verify.js CHANGED
@@ -27,6 +27,7 @@ import { readFileSync } from 'node:fs';
27
27
  import { Script } from 'node:vm';
28
28
  import { join } from 'node:path';
29
29
  import { listHotMounts, parseSimplePatch } from './hot.js';
30
+ import { userPatchPackageReferences } from './patch.js';
30
31
  import { bundlePatchInsertedIds, hasDshManifest, hasLoadableEntry, profileDir, readInstalled } from './profile.js';
31
32
  /** The profile manifest's `dsh.profile.bundles` — what the CLI reconciled. */
32
33
  function readBundles(profile, explicitDir) {
@@ -103,6 +104,24 @@ function patchTextOf(profile, name, explicitDir) {
103
104
  * @param live - names live in the current composition; defaults to the
104
105
  * market's hot-mount table (injectable for tests).
105
106
  */
107
+ /**
108
+ * Whether the profile's OWN `cordis.patch.yml` inserts this package by name.
109
+ *
110
+ * A third evidence source beside the loader inventory and the package's own
111
+ * manifest, and the one that was missing (#165): a plugin the user wired up
112
+ * themselves declares nothing, is not hot-mounted until the next boot, and so
113
+ * fell through to `broken` — the market told them the install had failed
114
+ * verification while the plugin was, in fact, working.
115
+ *
116
+ * Read with the same parser the uninstall guard uses. Unreadable returns
117
+ * null, which is treated here as NO evidence rather than as evidence: this
118
+ * only ever upgrades a verdict away from `broken`, so being unsure has to
119
+ * leave the stricter answer standing.
120
+ */
121
+ function patchLoads(activeProfileDir, name) {
122
+ const references = userPatchPackageReferences(join(activeProfileDir, 'cordis.patch.yml'), name);
123
+ return references !== null && references.length > 0;
124
+ }
106
125
  export function verifyActivation(profile, name, live = new Set(listHotMounts()), explicitDir, isDisabled = false) {
107
126
  const activeProfileDir = profileDir(profile, explicitDir);
108
127
  const bundles = readBundles(profile, activeProfileDir);
@@ -142,12 +161,20 @@ export function verifyActivation(profile, name, live = new Set(listHotMounts()),
142
161
  // Not live and no dsh surface: for a package the profile lists as a
143
162
  // BUNDLE this is a real defect; for a plain dependency it is normal —
144
163
  // most dependencies are libraries, not plugins (#135).
145
- return inBundles
146
- ? {
164
+ if (inBundles && !patchLoads(activeProfileDir, name)) {
165
+ return {
147
166
  state: 'broken',
148
167
  reasons: ['已列入 profile bundle 层但未声明 dsh 元数据,加载会失败 / listed in the profile bundle layer but declares no dsh metadata — loading it fails'],
149
168
  bundle: true,
150
169
  hot: false,
170
+ };
171
+ }
172
+ return inBundles
173
+ ? {
174
+ state: 'restart',
175
+ reasons: ['由你自己的 cordis.patch.yml 按名加载,重启后生效 / loaded by name from your own cordis.patch.yml — live after a restart'],
176
+ bundle: true,
177
+ hot: false,
151
178
  }
152
179
  : {
153
180
  state: 'inert',
@@ -159,7 +186,7 @@ export function verifyActivation(profile, name, live = new Set(listHotMounts()),
159
186
  // Carrier bundles (#103) ship no entry of their own — what they mount is
160
187
  // the point — so judge by "is anything loadable", not by this package's
161
188
  // own artifact.
162
- if (!loaderLive && !hasLoadableEntry(activeProfileDir, name)) {
189
+ if (!loaderLive && !hasLoadableEntry(activeProfileDir, name) && !patchLoads(activeProfileDir, name)) {
163
190
  return {
164
191
  state: 'broken',
165
192
  reasons: [
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.29.0",
4
+ "version": "1.29.1",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/types/index.d.ts",
package/src/verify.ts CHANGED
@@ -28,6 +28,7 @@ import { readFileSync } from 'node:fs'
28
28
  import { Script } from 'node:vm'
29
29
  import { join } from 'node:path'
30
30
  import { listHotMounts, parseSimplePatch } from './hot.ts'
31
+ import { userPatchPackageReferences } from './patch.ts'
31
32
  import { bundlePatchInsertedIds, hasDshManifest, hasLoadableEntry, profileDir, readInstalled } from './profile.ts'
32
33
 
33
34
  export type ActivationState = 'live' | 'restart' | 'inert' | 'broken' | 'missing' | 'disabled'
@@ -124,6 +125,25 @@ function patchTextOf(profile: string, name: string, explicitDir?: string): strin
124
125
  * @param live - names live in the current composition; defaults to the
125
126
  * market's hot-mount table (injectable for tests).
126
127
  */
128
+ /**
129
+ * Whether the profile's OWN `cordis.patch.yml` inserts this package by name.
130
+ *
131
+ * A third evidence source beside the loader inventory and the package's own
132
+ * manifest, and the one that was missing (#165): a plugin the user wired up
133
+ * themselves declares nothing, is not hot-mounted until the next boot, and so
134
+ * fell through to `broken` — the market told them the install had failed
135
+ * verification while the plugin was, in fact, working.
136
+ *
137
+ * Read with the same parser the uninstall guard uses. Unreadable returns
138
+ * null, which is treated here as NO evidence rather than as evidence: this
139
+ * only ever upgrades a verdict away from `broken`, so being unsure has to
140
+ * leave the stricter answer standing.
141
+ */
142
+ function patchLoads(activeProfileDir: string, name: string): boolean {
143
+ const references = userPatchPackageReferences(join(activeProfileDir, 'cordis.patch.yml'), name)
144
+ return references !== null && references.length > 0
145
+ }
146
+
127
147
  export function verifyActivation(
128
148
  profile: string,
129
149
  name: string,
@@ -172,10 +192,18 @@ export function verifyActivation(
172
192
  // Not live and no dsh surface: for a package the profile lists as a
173
193
  // BUNDLE this is a real defect; for a plain dependency it is normal —
174
194
  // most dependencies are libraries, not plugins (#135).
195
+ if (inBundles && !patchLoads(activeProfileDir, name)) {
196
+ return {
197
+ state: 'broken',
198
+ reasons: ['已列入 profile bundle 层但未声明 dsh 元数据,加载会失败 / listed in the profile bundle layer but declares no dsh metadata — loading it fails'],
199
+ bundle: true,
200
+ hot: false,
201
+ }
202
+ }
175
203
  return inBundles
176
204
  ? {
177
- state: 'broken',
178
- reasons: ['已列入 profile bundle 层但未声明 dsh 元数据,加载会失败 / listed in the profile bundle layer but declares no dsh metadata — loading it fails'],
205
+ state: 'restart',
206
+ reasons: ['由你自己的 cordis.patch.yml 按名加载,重启后生效 / loaded by name from your own cordis.patch.yml live after a restart'],
179
207
  bundle: true,
180
208
  hot: false,
181
209
  }
@@ -189,7 +217,7 @@ export function verifyActivation(
189
217
  // Carrier bundles (#103) ship no entry of their own — what they mount is
190
218
  // the point — so judge by "is anything loadable", not by this package's
191
219
  // own artifact.
192
- if (!loaderLive && !hasLoadableEntry(activeProfileDir, name)) {
220
+ if (!loaderLive && !hasLoadableEntry(activeProfileDir, name) && !patchLoads(activeProfileDir, name)) {
193
221
  return {
194
222
  state: 'broken',
195
223
  reasons: [