dsh-skill-hub 0.3.0 → 0.3.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.
package/lib/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { createRequire } from "node:module";
2
- import { settingsNamespace } from "@deepseek-ai/dsh-settings";
3
2
  import z from "schemastery";
4
3
  import { mkdir, mkdtemp, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
5
4
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -3621,7 +3620,7 @@ const Config = z.object({
3621
3620
  * page edit this namespace through the official settings transport, and the
3622
3621
  * plugin consumes the same resolved value — one source of truth.
3623
3622
  */
3624
- const CONFIG_NAMESPACE = settingsNamespace("dsh-skill-hub");
3623
+ const CONFIG_NAMESPACE = "dsh-skill-hub";
3625
3624
  /** Schema of the hub's settings namespace: the card's fields (booleans + optional dot colors). */
3626
3625
  const HubSettingsSchema = z.object({
3627
3626
  enabled: z.boolean().default(HUB_CONFIG_DEFAULTS.enabled),
@@ -3654,7 +3653,7 @@ function apply(ctx, config) {
3654
3653
  let providerControl;
3655
3654
  let stats;
3656
3655
  const saved = () => {
3657
- return ctx.settings.describe().find((entry) => entry.ns === CONFIG_NAMESPACE)?.user ?? {};
3656
+ return ctx.settings.describe().find((entry) => entry.ns === "dsh-skill-hub")?.user ?? {};
3658
3657
  };
3659
3658
  const updateConfig = async (patch) => {
3660
3659
  const user = { ...saved() };
@@ -6,7 +6,7 @@
6
6
  * namespace, so the plugin shows up in Settings → 插件 on dsh rc.7+.
7
7
  */
8
8
  import { type ReactElement } from 'react';
9
- import type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
9
+ import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
10
10
  import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
11
11
  import { type CardShell, type FieldState, type FormScope } from './settings-form.ts';
12
12
  import { DEFAULT_DOT_MODEL_COLOR, DEFAULT_DOT_USER_COLOR } from './panel/format.ts';
@@ -21,7 +21,12 @@
21
21
  * what cordis loading needs plus types only — all value exports stay
22
22
  * internal.
23
23
  */
24
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
24
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
25
+ declare module '@deepseek-ai/cordis' {
26
+ interface Context {
27
+ slots: any;
28
+ }
29
+ }
25
30
  import { type HubKey } from './locales.ts';
26
31
  declare module '@deepseek-ai/dsh-client-ui-slots' {
27
32
  interface LocaleNamespaceMap {
@@ -72,7 +72,7 @@ export declare class CardForm {
72
72
  /** @param scope - the bound settings scope for this card's namespace. */
73
73
  constructor(scope: FormScope, specs: FieldSpec[]);
74
74
  /** Publish a projection of this form, rebuilt whenever the scope or a draft changes. */
75
- bind<T>(project: () => T): import("@deepseek-ai/dsh-client-runtime/client").SnapshotStore<T>;
75
+ bind<T>(project: () => T): import("@deepseek-ai/dsh-client-store").SnapshotStore<T>;
76
76
  /** Read the card-level state: what the Host serves, and what a save would do. */
77
77
  shell(): CardShell;
78
78
  /** Read one field's state from the effective section and its staged draft. */
@@ -17,7 +17,8 @@
17
17
  * source registry, which the frozen contract exposes only as `registerSource`
18
18
  * / `sessionOf` — the lookup below is defensive: it never throws).
19
19
  */
20
- import type { ClientContext, SettingsScope } from '@deepseek-ai/dsh-client-runtime/client';
20
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
21
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
21
22
  import type { InputTriggerServiceContract, InputTriggerSource } from '@deepseek-ai/dsh-client-ui-input-trigger/client';
22
23
  import type { HubSettingsValue } from '../protocol.ts';
23
24
  import type { SkillHubApi } from './api.ts';
@@ -7,6 +7,7 @@
7
7
  * source changes.
8
8
  */
9
9
  import type { Context } from '@deepseek-ai/cordis';
10
+ import type { SettingsNamespace } from '@deepseek-ai/dsh-settings';
10
11
  import z from 'schemastery';
11
12
  import { type HubSettingsValue } from './protocol.ts';
12
13
  /** Stable cordis plugin name (matches cordis.patch.yml insert id). */
@@ -38,7 +39,7 @@ export declare const Config: z<Config>;
38
39
  * page edit this namespace through the official settings transport, and the
39
40
  * plugin consumes the same resolved value — one source of truth.
40
41
  */
41
- export declare const CONFIG_NAMESPACE: import("@deepseek-ai/dsh-settings").SettingsNamespace;
42
+ export declare const CONFIG_NAMESPACE: SettingsNamespace;
42
43
  /** Schema of the hub's settings namespace: the card's fields (booleans + optional dot colors). */
43
44
  export declare const HubSettingsSchema: z<HubSettingsValue>;
44
45
  /** Model-facing announcement: plugin presence, capabilities, and limits. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-skill-hub",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "In-GUI skill hub for DeepSeek Harness (dsh): browse the full local skill catalog from the official ctx.skills registry (every root + third-party providers), toggle skills on/off, inspect bodies, surface frontmatter diagnostics, and scaffold new skills — plus a codex-style skill market (built-in catalog, upstream update checks, one-click update-all) with tracked source sync. The full manager beyond the read-only dsh-skill-manager browser.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -30,7 +30,6 @@
30
30
  },
31
31
  "client": {
32
32
  "inject": [
33
- "@deepseek-ai/dsh-client-runtime",
34
33
  "@deepseek-ai/dsh-client-connection",
35
34
  "@deepseek-ai/dsh-client-ui-settings"
36
35
  ],
@@ -63,7 +62,8 @@
63
62
  "compatibility": {
64
63
  "dshVersions": [
65
64
  "0.1.0-rc.7",
66
- "0.1.1-rc.2"
65
+ "0.1.1-rc.2",
66
+ "0.1.2-alpha.2"
67
67
  ]
68
68
  },
69
69
  "capability": {
@@ -84,37 +84,46 @@
84
84
  "schemastery": "^3.18.0"
85
85
  },
86
86
  "peerDependencies": {
87
- "@deepseek-ai/cordis": "^4.0.1",
88
- "@deepseek-ai/dsh-client-connection": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
89
- "@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
87
+ "@deepseek-ai/cordis": "^4.0.1 || ^4.0.2",
88
+ "@deepseek-ai/dsh-client-connection": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
89
+ "@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
90
90
  "@deepseek-ai/dsh-client-runtime": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
91
- "@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
92
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
93
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
94
- "@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
95
- "@deepseek-ai/dsh-session": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
96
- "@deepseek-ai/dsh-session-query": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
97
- "@deepseek-ai/dsh-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
98
- "@deepseek-ai/dsh-skill": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
99
- "@deepseek-ai/dsh-system-prompt": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
91
+ "@deepseek-ai/dsh-client-store": ">=0.1.2-alpha.2 <0.2.0-0",
92
+ "@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
93
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
94
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
95
+ "@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
96
+ "@deepseek-ai/dsh-session": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
97
+ "@deepseek-ai/dsh-session-query": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
98
+ "@deepseek-ai/dsh-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
99
+ "@deepseek-ai/dsh-skill": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
100
+ "@deepseek-ai/dsh-system-prompt": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0",
100
101
  "react": "^18.2.0",
101
102
  "react-dom": "^18.2.0"
102
103
  },
104
+ "peerDependenciesMeta": {
105
+ "@deepseek-ai/dsh-client-runtime": {
106
+ "optional": true
107
+ },
108
+ "@deepseek-ai/dsh-client-store": {
109
+ "optional": true
110
+ }
111
+ },
103
112
  "devDependencies": {
104
- "@deepseek-ai/cordis": "^4.0.1",
105
- "@deepseek-ai/dsh-client-connection": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
106
- "@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
107
- "@deepseek-ai/dsh-client-runtime": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
108
- "@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
109
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
110
- "@deepseek-ai/dsh-client-ui-settings-plugins": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
111
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
112
- "@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
113
- "@deepseek-ai/dsh-session": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
114
- "@deepseek-ai/dsh-session-query": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
115
- "@deepseek-ai/dsh-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
116
- "@deepseek-ai/dsh-skill": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
117
- "@deepseek-ai/dsh-system-prompt": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0",
113
+ "@deepseek-ai/cordis": "^4.0.2",
114
+ "@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.2",
115
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.2",
116
+ "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.2",
117
+ "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.2-alpha.2",
118
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.2",
119
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.2-alpha.2",
120
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.2",
121
+ "@deepseek-ai/dsh-host-webserver": "^0.1.2-alpha.2",
122
+ "@deepseek-ai/dsh-session": "^0.1.2-alpha.2",
123
+ "@deepseek-ai/dsh-session-query": "^0.1.2-alpha.2",
124
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.2",
125
+ "@deepseek-ai/dsh-skill": "^0.1.2-alpha.2",
126
+ "@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.2",
118
127
  "@types/js-yaml": "^4.0.9",
119
128
  "@types/node": "^22.20.0",
120
129
  "@types/react": "~18.3.1",
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { useEffect, useState, type ReactElement } from 'react'
10
- import type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'
10
+ import type { SnapshotStore } from '@deepseek-ai/dsh-client-store'
11
11
  import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
12
12
  import { SkillHubApi } from './api.ts'
13
13
  import { ColorField, NumberField, PluginSettingsCard, SwitchField } from './settings-card.tsx'
@@ -22,7 +22,7 @@
22
22
  * internal.
23
23
  */
24
24
 
25
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'
25
+ import type { Context as ClientContext } from '@deepseek-ai/cordis'
26
26
  // Type-only: pulls the locale plugin's Context merge (ctx.locale).
27
27
  import type {} from '@deepseek-ai/dsh-client-locale/client'
28
28
  // Type-only: pulls the settings-scope service merge and the settings.section slot.
@@ -33,6 +33,15 @@ import type {} from '@deepseek-ai/dsh-client-ui-slots'
33
33
  import type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'
34
34
  // Type-only: pulls the Context merge for ctx.inputTriggers (slash-dots wiring).
35
35
  import type {} from '@deepseek-ai/dsh-client-ui-input-trigger/client'
36
+ // Type-only: pulls the connection/reset event.
37
+ import type {} from '@deepseek-ai/dsh-client-connection/client'
38
+
39
+ // 0.1.2-alpha.2: slots service moved to ui-renderer; provide local augmentation for build.
40
+ declare module '@deepseek-ai/cordis' {
41
+ interface Context {
42
+ slots: any
43
+ }
44
+ }
36
45
  import type { HubSettingsValue } from '../protocol.ts'
37
46
  import { SkillHubApi } from './api.ts'
38
47
  import { en, zh, type HubKey } from './locales.ts'
@@ -9,7 +9,8 @@
9
9
  * land keeps its drafts, so the user can correct them instead of retyping.
10
10
  */
11
11
 
12
- import { createSnapshotStore, type SettingsScope } from '@deepseek-ai/dsh-client-runtime/client'
12
+ import { createSnapshotStore } from '@deepseek-ai/dsh-client-store'
13
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'
13
14
 
14
15
  /** One staged field: its draft text plus the clear/reset marker. */
15
16
  interface StagedEdit {
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { beforeEach, describe, expect, it } from 'vitest'
9
- import type { SettingsScope } from '@deepseek-ai/dsh-client-runtime/client'
9
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'
10
10
  import type { InputTriggerCandidate, InputTriggerServiceContract, InputTriggerSource } from '@deepseek-ai/dsh-client-ui-input-trigger/client'
11
11
  import type { HubSettingsValue } from '../protocol.ts'
12
12
  import type { SkillHubApi } from './api.ts'
@@ -39,7 +39,8 @@ function scopeWith(value: HubSettingsValue): SettingsScope<HubSettingsValue> {
39
39
  subscribe: () => () => {},
40
40
  set: async () => {},
41
41
  unset: async () => {},
42
- } as SettingsScope<HubSettingsValue>
42
+ mutate: async () => {},
43
+ } as unknown as SettingsScope<HubSettingsValue>
43
44
  }
44
45
 
45
46
  /** Fake hub api whose catalog lists the given skills. */
@@ -84,7 +85,7 @@ describe('findSkillSource', () => {
84
85
  })
85
86
 
86
87
  describe('wrapSkillSource', () => {
87
- it('adds a model-colored dot to model-callable skills and a user-colored dot to user-only ones', async () => {
88
+ it('adds a model-colored dot to model-callable skills and a user-colored dot to user-only ones (old host, no drilled)', async () => {
88
89
  const source = skillSource(async () => [
89
90
  { name: 'code-review', description: 'review code' },
90
91
  { name: 'personal-note', description: 'only me' },
@@ -98,7 +99,8 @@ describe('wrapSkillSource', () => {
98
99
 
99
100
  const restore = wrapSkillSource(source, api, scope)
100
101
  try {
101
- const rows = await source.candidates({ sessionId: 's1' as never }, { query: '', position: 'leading', signal: new AbortController().signal })
102
+ // Old host: CandidateRequest 无 drilled 字段,注入彩色点
103
+ const rows = await source.candidates({ sessionId: 's1' as never }, { query: '', position: 'leading', signal: new AbortController().signal } as unknown as import('@deepseek-ai/dsh-client-ui-input-trigger/client').CandidateRequest)
102
104
 
103
105
  expect(rows).toHaveLength(3)
104
106
  // Model-callable → model color.
@@ -115,14 +117,14 @@ describe('wrapSkillSource', () => {
115
117
  }
116
118
  })
117
119
 
118
- it('falls back to the default colors when settings omit them and catalog fails', async () => {
120
+ it('falls back to the default colors when settings omit them and catalog fails (old host)', async () => {
119
121
  const source = skillSource(async () => [{ name: 'lonely', description: '' }])
120
122
  const api = { catalog: async () => { throw new Error('route down') } } as unknown as SkillHubApi
121
123
  const scope = scopeWith({ enabled: true, announceToAgent: true, showUseCount: true, showUseTime: true, showGroupSummary: true })
122
124
 
123
125
  const restore = wrapSkillSource(source, api, scope)
124
126
  try {
125
- const rows = await source.candidates({ sessionId: 's1' as never }, { query: '', position: 'leading', signal: new AbortController().signal })
127
+ const rows = await source.candidates({ sessionId: 's1' as never }, { query: '', position: 'leading', signal: new AbortController().signal } as unknown as import('@deepseek-ai/dsh-client-ui-input-trigger/client').CandidateRequest)
126
128
  // Catalog failed → unknown name → model default dot still renders.
127
129
  expect(rows[0].icon).toBeDefined()
128
130
  expect((rows[0].icon as unknown as { props: { style: { background: string } } }).props.style.background).toBe('#2f81f7')
@@ -131,6 +133,22 @@ describe('wrapSkillSource', () => {
131
133
  }
132
134
  })
133
135
 
136
+ it('skips dot injection on new host (alpha.2, drilled present) for ReferenceIcon compat', async () => {
137
+ const source = skillSource(async () => [{ name: 'code-review', description: 'review code' }])
138
+ const api = apiWith([{ name: 'code-review', modelInvocable: true }])
139
+ const scope = scopeWith({ enabled: true, announceToAgent: true, showUseCount: true, showUseTime: true, showGroupSummary: true, dotModelColor: '#112233', dotUserColor: '#445566' })
140
+
141
+ const restore = wrapSkillSource(source, api, scope)
142
+ try {
143
+ const rows = await source.candidates({ sessionId: 's1' as never }, { query: '', position: 'leading', drilled: false, signal: new AbortController().signal })
144
+ expect(rows).toHaveLength(1)
145
+ expect(rows[0].icon).toBeUndefined()
146
+ expect(rows[0].name).toBe('code-review')
147
+ } finally {
148
+ restore()
149
+ }
150
+ })
151
+
134
152
  it('restores the original candidates on dispose', async () => {
135
153
  const originalCandidates = async (): Promise<InputTriggerCandidate[]> => [{ name: 'plain', description: '' }]
136
154
  const source = skillSource(originalCandidates)
@@ -18,9 +18,12 @@
18
18
  * / `sessionOf` — the lookup below is defensive: it never throws).
19
19
  */
20
20
 
21
- import type { ClientContext, SettingsScope } from '@deepseek-ai/dsh-client-runtime/client'
21
+ import type { Context as ClientContext } from '@deepseek-ai/cordis'
22
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'
22
23
  // Type-only: pulls the Context merge for ctx.inputTriggers.
23
24
  import type {} from '@deepseek-ai/dsh-client-ui-input-trigger/client'
25
+ // Type-only: pulls the connection/reset event.
26
+ import type {} from '@deepseek-ai/dsh-client-connection/client'
24
27
  import type { InputTriggerCandidate, InputTriggerServiceContract, InputTriggerSource } from '@deepseek-ai/dsh-client-ui-input-trigger/client'
25
28
  import { createElement } from 'react'
26
29
  import type { HubSettingsValue } from '../protocol.ts'
@@ -121,6 +124,12 @@ export function wrapSkillSource(source: InputTriggerSource, api: SkillHubApi, sc
121
124
  source.candidates = async (session, req) => {
122
125
  const items = await original(session, req)
123
126
  if (req.signal.aborted) return items
127
+ // Dual-compat: 0.1.2-alpha.2 的 MenuView 将 icon 收窄为 'file'|'folder'|'session'
128
+ // 并通过 ReferenceIcon 渲染,旧版的自定义 ReactElement 点已无法展示。
129
+ // 以 `drilled` 是否存在探测新版(alpha.2 必有,rc 无),新版直接透传不注入
130
+ // icon,旧版保持彩色点,避免新版传入非法 icon 导致渲染异常。
131
+ const isNewHost = req !== null && typeof req === 'object' && 'drilled' in (req as unknown as Record<string, unknown>)
132
+ if (isNewHost) return items
124
133
  const modelByName = await modelInvocableMap(api)
125
134
  if (req.signal.aborted) return items
126
135
  const snapshot = scope.getSnapshot()
package/src/index.ts CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  import type { Context } from '@deepseek-ai/cordis'
11
11
  import type { SkillProviderControl } from '@deepseek-ai/dsh-skill'
12
- import { settingsNamespace } from '@deepseek-ai/dsh-settings'
12
+ import type { SettingsNamespace } from '@deepseek-ai/dsh-settings'
13
13
  import z from 'schemastery'
14
14
  import type {} from '@deepseek-ai/dsh-host-webserver'
15
15
  import type {} from '@deepseek-ai/dsh-skill'
@@ -67,7 +67,7 @@ export const Config: z<Config> = z.object({
67
67
  * page edit this namespace through the official settings transport, and the
68
68
  * plugin consumes the same resolved value — one source of truth.
69
69
  */
70
- export const CONFIG_NAMESPACE = settingsNamespace('dsh-skill-hub')
70
+ export const CONFIG_NAMESPACE = 'dsh-skill-hub' as SettingsNamespace
71
71
 
72
72
  /** Schema of the hub's settings namespace: the card's fields (booleans + optional dot colors). */
73
73
  export const HubSettingsSchema: z<HubSettingsValue> = z.object({