dsh-skill-importer 0.2.4 → 0.2.6

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
@@ -11,7 +11,7 @@
11
11
 
12
12
  [![npm](https://img.shields.io/npm/v/dsh-skill-importer?style=flat-square&color=5dd8bd&label=npm)](https://www.npmjs.com/package/dsh-skill-importer)
13
13
  [![downloads](https://img.shields.io/npm/dm/dsh-skill-importer?style=flat-square&color=6da8ff)](https://www.npmjs.com/package/dsh-skill-importer)
14
- [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek_Harness-%E2%89%A50.1.0--rc.6-5965f2?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
14
+ [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek_Harness-%E2%89%A50.2.0--rc.2-5965f2?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
15
15
  [![license](https://img.shields.io/badge/license-MIT-a786ff?style=flat-square)](LICENSE)
16
16
 
17
17
  <br />
@@ -118,7 +118,7 @@ Replace both `X.Y.Z` placeholders with the same target version. This opts that v
118
118
 
119
119
  Open **Settings → Skills**. Import a Markdown file or URL, or choose **Batch import** to migrate another agent's complete skills directory. Choose a target and the imported skills will appear as soon as the filesystem watcher discovers them.
120
120
 
121
- > Requires DeepSeek Harness `>= 0.1.0-rc.6`.
121
+ > Requires DeepSeek Harness `>= 0.2.0-rc.2`.
122
122
 
123
123
  ### Duplicate plugin after upgrading
124
124
 
package/README.zh.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  [![npm](https://img.shields.io/npm/v/dsh-skill-importer?style=flat-square&color=5dd8bd&label=npm)](https://www.npmjs.com/package/dsh-skill-importer)
13
13
  [![downloads](https://img.shields.io/npm/dm/dsh-skill-importer?style=flat-square&color=6da8ff)](https://www.npmjs.com/package/dsh-skill-importer)
14
- [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek_Harness-%E2%89%A50.1.0--rc.6-5965f2?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
14
+ [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek_Harness-%E2%89%A50.2.0--rc.2-5965f2?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
15
15
  [![license](https://img.shields.io/badge/license-MIT-a786ff?style=flat-square)](LICENSE)
16
16
 
17
17
  <br />
@@ -118,7 +118,7 @@ minimumReleaseAgeExclude:
118
118
 
119
119
  打开 **设置 → 技能**,选择 Markdown 文件、粘贴 URL,或通过「批量导入」迁移其他 Agent 的完整技能目录,再选择目标范围。文件系统 watcher 发现后,技能会立即出现。
120
120
 
121
- > 需要 DeepSeek Harness `>= 0.1.0-rc.6`。
121
+ > 需要 DeepSeek Harness `>= 0.2.0-rc.2`。
122
122
 
123
123
  ### 旧配置导致重复插件
124
124
 
package/lib/client.js CHANGED
@@ -229,15 +229,11 @@ window.__ModuleLoader__.load({
229
229
  const skills = useSkills((value) => value);
230
230
  const skillIssues = useSkillIssues((value) => value);
231
231
  const workspaces = useWorkspaces((value) => value);
232
- const [selectedWorkspaceId, setSelectedWorkspaceId] = (0, react.useState)(() => workspaces.recentWorkspaceId ?? workspaces.items[0]?.workspaceId);
232
+ const [selectedWorkspaceId, setSelectedWorkspaceId] = (0, react.useState)(() => workspaces.items[0]?.workspaceId);
233
233
  (0, react.useEffect)(() => {
234
234
  if (selectedWorkspaceId !== void 0 && workspaces.items.some((item) => item.workspaceId === selectedWorkspaceId)) return;
235
- setSelectedWorkspaceId(workspaces.recentWorkspaceId ?? workspaces.items[0]?.workspaceId);
236
- }, [
237
- selectedWorkspaceId,
238
- workspaces.items,
239
- workspaces.recentWorkspaceId
240
- ]);
235
+ setSelectedWorkspaceId(workspaces.items[0]?.workspaceId);
236
+ }, [selectedWorkspaceId, workspaces.items]);
241
237
  const workspace = (0, react.useMemo)(() => workspaces.items.find((item) => item.workspaceId === selectedWorkspaceId), [selectedWorkspaceId, workspaces.items]);
242
238
  const [listState, setListState] = (0, react.useState)("idle");
243
239
  const [listError, setListError] = (0, react.useState)();
@@ -2085,13 +2081,6 @@ window.__ModuleLoader__.load({
2085
2081
  if (direction === "right" && caret >= 0 && caret < token.boundaryEnd) return token.boundaryEnd;
2086
2082
  }
2087
2083
  //#endregion
2088
- //#region src/client/composerFocus.ts
2089
- const COMPOSER_FOCUS_EVENT = "dsh-skill-importer/composer-focus";
2090
- /** Ask the mounted picker in one session to restore its composer focus. */
2091
- function requestComposerFocus(request) {
2092
- window.dispatchEvent(new CustomEvent(COMPOSER_FOCUS_EVENT, { detail: request }));
2093
- }
2094
- //#endregion
2095
2084
  //#region src/client/SkillsPicker.tsx
2096
2085
  /**
2097
2086
  * Composer skill picker: a compact pill trigger in the composer's tool row
@@ -2102,15 +2091,70 @@ window.__ModuleLoader__.load({
2102
2091
  * with `/name ` — the native text gesture — highlighted via the plugin's
2103
2092
  * lexicon contribution.
2104
2093
  */
2105
- /** Find the one composer textarea owned by the picker nearest in the slot tree. */
2106
- function composerTextareaFor(root) {
2094
+ /** Find the one legacy textarea or Lexical contenteditable owned by this picker. */
2095
+ function composerInputFor(root) {
2107
2096
  let node = root?.parentElement;
2108
2097
  while (node !== null && node !== void 0) {
2109
- const textareas = node.querySelectorAll("textarea");
2110
- if (textareas.length > 0) return textareas.length === 1 ? textareas[0] : void 0;
2098
+ const inputs = node.querySelectorAll("textarea, [data-composer-input]");
2099
+ if (inputs.length > 0) return inputs.length === 1 ? inputs[0] : void 0;
2111
2100
  node = node.parentElement;
2112
2101
  }
2113
2102
  }
2103
+ function composerText(input) {
2104
+ return input instanceof HTMLTextAreaElement ? input.value : input.textContent ?? "";
2105
+ }
2106
+ function composerCaret(input) {
2107
+ if (input instanceof HTMLTextAreaElement) {
2108
+ if (input.selectionStart === null || input.selectionEnd === null) return void 0;
2109
+ return {
2110
+ start: input.selectionStart,
2111
+ end: input.selectionEnd
2112
+ };
2113
+ }
2114
+ const selection = window.getSelection();
2115
+ if (selection === null || selection.rangeCount !== 1) return void 0;
2116
+ const range = selection.getRangeAt(0);
2117
+ if (!input.contains(range.startContainer) || !input.contains(range.endContainer)) return void 0;
2118
+ const offsetOf = (container, offset) => {
2119
+ const prefix = range.cloneRange();
2120
+ prefix.selectNodeContents(input);
2121
+ prefix.setEnd(container, offset);
2122
+ return prefix.toString().length;
2123
+ };
2124
+ return {
2125
+ start: offsetOf(range.startContainer, range.startOffset),
2126
+ end: offsetOf(range.endContainer, range.endOffset)
2127
+ };
2128
+ }
2129
+ function setComposerCaret(input, caret) {
2130
+ input.focus({ preventScroll: true });
2131
+ if (input instanceof HTMLTextAreaElement) {
2132
+ input.setSelectionRange(caret, caret);
2133
+ return;
2134
+ }
2135
+ const range = document.createRange();
2136
+ let remaining = caret;
2137
+ const walker = document.createTreeWalker(input, NodeFilter.SHOW_TEXT);
2138
+ let text = walker.nextNode();
2139
+ while (text !== null) {
2140
+ const length = text.textContent?.length ?? 0;
2141
+ if (remaining <= length) {
2142
+ range.setStart(text, remaining);
2143
+ range.collapse(true);
2144
+ const selection = window.getSelection();
2145
+ selection?.removeAllRanges();
2146
+ selection?.addRange(range);
2147
+ return;
2148
+ }
2149
+ remaining -= length;
2150
+ text = walker.nextNode();
2151
+ }
2152
+ range.selectNodeContents(input);
2153
+ range.collapse(false);
2154
+ const selection = window.getSelection();
2155
+ selection?.removeAllRanges();
2156
+ selection?.addRange(range);
2157
+ }
2114
2158
  /** One row of the composer skill picker. */
2115
2159
  function SkillsPicker({ t, sessionId, useInput, inputActions, actions }) {
2116
2160
  const input = useInput((value) => value.draft);
@@ -2164,24 +2208,14 @@ window.__ModuleLoader__.load({
2164
2208
  draftRef.current = input;
2165
2209
  skillNamesRef.current = usable.map((skill) => skill.name);
2166
2210
  const scheduleComposerFocus = (expectedDraft, caret) => {
2167
- const textarea = composerTextareaFor(rootRef.current);
2211
+ const input = composerInputFor(rootRef.current);
2168
2212
  if (caretFrameRef.current !== void 0) window.cancelAnimationFrame(caretFrameRef.current);
2169
2213
  caretFrameRef.current = window.requestAnimationFrame(() => {
2170
2214
  caretFrameRef.current = void 0;
2171
- if (textarea === void 0 || !textarea.isConnected || textarea.value !== expectedDraft) return;
2172
- textarea.focus({ preventScroll: true });
2173
- textarea.setSelectionRange(caret, caret);
2215
+ if (input === void 0 || !input.isConnected || composerText(input) !== expectedDraft) return;
2216
+ setComposerCaret(input, caret);
2174
2217
  });
2175
2218
  };
2176
- (0, react.useEffect)(() => {
2177
- const onFocusRequest = (event) => {
2178
- const request = event.detail;
2179
- if (request.sessionId !== sessionId) return;
2180
- scheduleComposerFocus(request.expectedDraft, request.caret);
2181
- };
2182
- window.addEventListener(COMPOSER_FOCUS_EVENT, onFocusRequest);
2183
- return () => window.removeEventListener(COMPOSER_FOCUS_EVENT, onFocusRequest);
2184
- }, [sessionId]);
2185
2219
  (0, react.useEffect)(() => {
2186
2220
  const onKeyDown = (event) => {
2187
2221
  if (![
@@ -2192,18 +2226,20 @@ window.__ModuleLoader__.load({
2192
2226
  if (event.defaultPrevented || event.isComposing || event.keyCode === 229) return;
2193
2227
  if (event.metaKey || event.ctrlKey || event.altKey) return;
2194
2228
  if (event.shiftKey && event.key !== "Backspace") return;
2195
- const textarea = event.target;
2196
- if (!(textarea instanceof HTMLTextAreaElement) || document.activeElement !== textarea) return;
2197
- if (composerTextareaFor(rootRef.current) !== textarea || textarea.value !== draftRef.current) return;
2198
- const start = textarea.selectionStart;
2199
- const end = textarea.selectionEnd;
2200
- if (start === null || end === null || start !== end) return;
2229
+ const target = event.target;
2230
+ if (!(target instanceof Node)) return;
2231
+ const input = composerInputFor(rootRef.current);
2232
+ if (input === void 0 || document.activeElement !== input || !input.contains(target)) return;
2233
+ if (composerText(input) !== draftRef.current) return;
2234
+ const selection = composerCaret(input);
2235
+ if (selection === void 0 || selection.start !== selection.end) return;
2236
+ const start = selection.start;
2201
2237
  if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
2202
2238
  const caret = atomicSkillArrow(draftRef.current, start, event.key === "ArrowLeft" ? "left" : "right", skillNamesRef.current);
2203
2239
  if (caret === void 0) return;
2204
2240
  event.preventDefault();
2205
2241
  event.stopPropagation();
2206
- textarea.setSelectionRange(caret, caret);
2242
+ setComposerCaret(input, caret);
2207
2243
  return;
2208
2244
  }
2209
2245
  const edit = atomicSkillBackspace(draftRef.current, start, skillNamesRef.current);
@@ -2214,8 +2250,8 @@ window.__ModuleLoader__.load({
2214
2250
  if (caretFrameRef.current !== void 0) window.cancelAnimationFrame(caretFrameRef.current);
2215
2251
  caretFrameRef.current = window.requestAnimationFrame(() => {
2216
2252
  caretFrameRef.current = void 0;
2217
- if (!textarea.isConnected || document.activeElement !== textarea || textarea.value !== edit.draft) return;
2218
- textarea.setSelectionRange(edit.caret, edit.caret);
2253
+ if (!input.isConnected || document.activeElement !== input || composerText(input) !== edit.draft) return;
2254
+ setComposerCaret(input, edit.caret);
2219
2255
  });
2220
2256
  };
2221
2257
  document.addEventListener("keydown", onKeyDown, true);
@@ -2248,7 +2284,7 @@ window.__ModuleLoader__.load({
2248
2284
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2249
2285
  style: triggerIconStyle,
2250
2286
  "aria-hidden": "true",
2251
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChecklistOutline14, {})
2287
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChecklistOutlineRegular, {})
2252
2288
  }),
2253
2289
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2254
2290
  style: triggerLabelStyle,
@@ -2260,7 +2296,7 @@ window.__ModuleLoader__.load({
2260
2296
  transform: open ? "rotate(180deg)" : void 0
2261
2297
  },
2262
2298
  "aria-hidden": "true",
2263
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {})
2299
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {})
2264
2300
  })
2265
2301
  ]
2266
2302
  }), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -2703,11 +2739,15 @@ window.__ModuleLoader__.load({
2703
2739
  };
2704
2740
  //#endregion
2705
2741
  //#region src/client/index.ts
2706
- /** Required services (cordis fiber inject). */
2742
+ /** Every client service used during apply is explicit; alpha DSH no longer tolerates load-order access. */
2707
2743
  const inject = [
2708
2744
  "slots",
2709
2745
  "locale",
2710
- "connection"
2746
+ "remote",
2747
+ "remote.directoryPicker",
2748
+ "commandUi",
2749
+ "sessions",
2750
+ "conversation"
2711
2751
  ];
2712
2752
  /** Same-origin route literals (mirrors the host half's ROUTES). */
2713
2753
  const ROUTES = {
@@ -2753,7 +2793,6 @@ window.__ModuleLoader__.load({
2753
2793
  const sourceLabel = (source) => source === "project-dsh" ? t("pickerSourceProjectDsh") : source === "project-agents" ? t("pickerSourceProjectAgents") : source === "user-dsh" ? t("pickerSourceUserDsh") : t("pickerSourceUserAgents");
2754
2794
  let catalog = [];
2755
2795
  let issues = [];
2756
- const sessionCatalogs = /* @__PURE__ */ new Map();
2757
2796
  const listeners = /* @__PURE__ */ new Set();
2758
2797
  const notify = () => {
2759
2798
  for (const listener of [...listeners]) try {
@@ -2762,63 +2801,39 @@ window.__ModuleLoader__.load({
2762
2801
  console.error("[dsh-skill-importer] listener failed:", error);
2763
2802
  }
2764
2803
  };
2765
- const connection = ctx.get("connection");
2766
- const skillsApi = connection.api.skills;
2767
- skillsApi.list.bind(skillsApi);
2768
- skillsApi.list = ((_request, _signal) => {
2769
- return Promise.reject(/* @__PURE__ */ new Error("skill group hidden: use the composer skill picker or /skills"));
2770
- });
2771
- const usableNames = () => [...new Set([...sessionCatalogs.values()].flat().filter((skill) => skill.userInvocable).map((skill) => skill.name))];
2772
- ctx.effect(() => {
2773
- return ctx.get("inputTriggers").registerSource({
2774
- trigger: "/",
2775
- name: "skill-importer",
2776
- order: 99,
2777
- async candidates() {
2778
- throw new Error("skill group hidden: use the composer skill picker");
2779
- },
2780
- onPick() {},
2781
- warm() {},
2782
- lexicon() {
2783
- return usableNames();
2784
- },
2785
- subscribeLexicon(_session, listener) {
2786
- listeners.add(listener);
2787
- return () => {
2788
- listeners.delete(listener);
2789
- };
2790
- }
2791
- });
2792
- }, "dsh-skill-importer: lexicon source");
2793
2804
  const commandUi = ctx.get("commandUi");
2794
2805
  const sessions = ctx.get("sessions");
2795
- const conversation = ctx.get("conversation");
2796
- if (commandUi !== void 0 && sessions !== void 0 && conversation !== void 0) ctx.effect(() => {
2806
+ if (commandUi !== void 0 && sessions !== void 0) ctx.effect(() => {
2797
2807
  return commandUi.register({
2798
2808
  name: "skills",
2799
- description: t("commandDescription"),
2809
+ description: () => t("commandDescription"),
2800
2810
  available: () => true,
2801
2811
  ui: {
2802
2812
  kind: "popupSelect",
2813
+ searchMode: "fuzzy-label",
2803
2814
  async options(session, _signal) {
2804
2815
  return (await refreshSkillsForSession(session.sessionId)).filter((skill) => skill.userInvocable).map((skill) => ({
2805
2816
  id: skill.name,
2806
- label: `${skill.name} · ${sourceLabel(skill.source)}`
2817
+ label: skill.name,
2818
+ detail: sourceLabel(skill.source)
2807
2819
  }));
2808
2820
  },
2809
2821
  onSelect(option, session) {
2810
2822
  const actx = sessions.scope(session.sessionId);
2811
- if (actx === void 0) return;
2812
- const input = conversation.input.for(actx);
2813
- const rest = input.state.getSnapshot().draft.replace(/^\s*\/[a-zA-Z][a-zA-Z0-9-]*\s*/, "");
2814
- const prefix = `/${option.id} `;
2815
- const nextDraft = `${prefix}${rest}`;
2816
- input.setDraft(nextDraft);
2817
- requestComposerFocus({
2818
- sessionId: session.sessionId,
2819
- expectedDraft: nextDraft,
2820
- caret: prefix.length
2821
- });
2823
+ if (actx === void 0) throw new Error("this session is no longer available");
2824
+ const conversation = actx.get("conversation");
2825
+ if (conversation === void 0) throw new Error("conversation input is unavailable");
2826
+ const rest = conversation.input.for(actx).state.getSnapshot().draft.replace(/^\s*\/[a-zA-Z][a-zA-Z0-9-]*\s*/, "");
2827
+ const nextDraft = `${`/${option.id} `}${rest}`;
2828
+ window.setTimeout(() => {
2829
+ const liveScope = sessions.scope(session.sessionId);
2830
+ if (liveScope === void 0) return;
2831
+ const liveConversation = liveScope.get("conversation");
2832
+ if (liveConversation === void 0) return;
2833
+ const liveInput = liveConversation.input.for(liveScope);
2834
+ liveInput.setDraft(nextDraft);
2835
+ liveInput.focus();
2836
+ }, 0);
2822
2837
  }
2823
2838
  }
2824
2839
  });
@@ -2833,7 +2848,6 @@ window.__ModuleLoader__.load({
2833
2848
  const refreshSkillsForSession = async (sessionId) => {
2834
2849
  const cwd = sessions.list.getSnapshot().byId[sessionId]?.cwd;
2835
2850
  const effective = effectiveSkills((await call(cwd === void 0 ? `${ROUTES.list}?scope=global` : `${ROUTES.list}?workspacePath=${encodeURIComponent(cwd)}`)).skills);
2836
- sessionCatalogs.set(sessionId, effective);
2837
2851
  notify();
2838
2852
  return effective;
2839
2853
  };
@@ -2847,9 +2861,9 @@ window.__ModuleLoader__.load({
2847
2861
  return (await call(ROUTES.delete, request)).removed;
2848
2862
  };
2849
2863
  const pickDirectory = async () => {
2850
- const response = await connection.api.host.pickDirectory({});
2851
- if (!response.result.ok) throw new Error(response.result.error.message);
2852
- return response.result.value.path;
2864
+ const result = await ctx.remote.directoryPicker.pick();
2865
+ if (!result.ok) throw new Error(result.error.message);
2866
+ return result.value;
2853
2867
  };
2854
2868
  const scanBatch = (request) => call(ROUTES.batchScan, request);
2855
2869
  const commitBatch = (request) => call(ROUTES.batchCommit, request);
@@ -1,5 +1,5 @@
1
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
2
- import type { SessionId } from '@deepseek-ai/dsh-api-remotes/client';
1
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
2
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
3
3
  import type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots';
4
4
  import type { SkillImporterProps } from './SkillImporterSection.tsx';
5
5
  import type { SkillsPickerProps } from './SkillsPicker.tsx';
@@ -43,7 +43,7 @@ export interface SkillImporterInjected {
43
43
  checkForUpdates: () => Promise<UpdateStatusResponse>;
44
44
  };
45
45
  }
46
- /** Required services (cordis fiber inject). */
46
+ /** Every client service used during apply is explicit; alpha DSH no longer tolerates load-order access. */
47
47
  export declare const inject: string[];
48
48
  /**
49
49
  * Client plugin body: register the section and its dictionaries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-skill-importer",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Web UI plugin for DeepSeek Harness: import skills from local Markdown files or URLs into the skill roots the harness discovers automatically",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -19,13 +19,16 @@
19
19
  "dsh": {
20
20
  "client": {
21
21
  "inject": [
22
- "@deepseek-ai/dsh-client-runtime",
23
- "@deepseek-ai/dsh-client-connection",
22
+ "@deepseek-ai/dsh-api-session-controller",
23
+ "@deepseek-ai/dsh-api-workspace-controller",
24
24
  "@deepseek-ai/dsh-client-locale",
25
+ "@deepseek-ai/dsh-client-ui-renderer",
26
+ "@deepseek-ai/dsh-client-ui-session",
25
27
  "@deepseek-ai/dsh-client-ui-slots",
26
28
  "@deepseek-ai/dsh-client-ui-settings",
27
29
  "@deepseek-ai/dsh-client-ui-primitives",
28
- "@deepseek-ai/dsh-api-remotes"
30
+ "@deepseek-ai/dsh-client-ui-conversation",
31
+ "@deepseek-ai/dsh-client-ui-commands"
29
32
  ],
30
33
  "platform": "web"
31
34
  },
@@ -54,42 +57,46 @@
54
57
  },
55
58
  "license": "MIT",
56
59
  "peerDependencies": {
57
- "@deepseek-ai/cordis": "^4.0.1",
58
- "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
59
- "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
60
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
61
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
62
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
63
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
64
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
60
+ "@deepseek-ai/cordis": "^4.0.4 || ^4.0.5-alpha.1",
61
+ "@deepseek-ai/dsh-api-session-controller": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
62
+ "@deepseek-ai/dsh-api-workspace-controller": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
63
+ "@deepseek-ai/dsh-client-locale": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
64
+ "@deepseek-ai/dsh-client-store": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
65
+ "@deepseek-ai/dsh-client-ui-settings": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
66
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
67
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
68
+ "@deepseek-ai/dsh-client-ui-session": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
69
+ "@deepseek-ai/dsh-client-ui-slots": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
65
70
  "react": "^18.2.0",
66
- "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
67
- "@deepseek-ai/dsh-workspace": "^0.1.0-rc.6",
68
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
69
- "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
70
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
71
- "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.6"
71
+ "@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
72
+ "@deepseek-ai/dsh-workspace": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
73
+ "@deepseek-ai/dsh-skill": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
74
+ "@deepseek-ai/dsh-session": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
75
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.2.0-rc.2 || ^0.2.1-alpha.1",
76
+ "@deepseek-ai/dsh-client-ui-commands": "^0.2.0-rc.2 || ^0.2.1-alpha.1"
72
77
  },
73
78
  "devDependencies": {
74
- "@deepseek-ai/cordis": "^4.0.1",
75
- "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
76
- "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
77
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
78
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
79
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
80
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
81
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
79
+ "@deepseek-ai/cordis": "4.0.5-alpha.1",
80
+ "@deepseek-ai/dsh-api-session-controller": "^0.2.1-alpha.1",
81
+ "@deepseek-ai/dsh-api-workspace-controller": "^0.2.1-alpha.1",
82
+ "@deepseek-ai/dsh-client-locale": "^0.2.1-alpha.1",
83
+ "@deepseek-ai/dsh-client-store": "^0.2.1-alpha.1",
84
+ "@deepseek-ai/dsh-client-ui-settings": "^0.2.1-alpha.1",
85
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.2.1-alpha.1",
86
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.2.1-alpha.1",
87
+ "@deepseek-ai/dsh-client-ui-session": "^0.2.1-alpha.1",
88
+ "@deepseek-ai/dsh-client-ui-slots": "^0.2.1-alpha.1",
82
89
  "@types/react": "^18.3.0",
83
90
  "react": "^18.2.0",
84
91
  "tsdown": "^0.22.2",
85
92
  "typescript": "^6.0.3",
86
- "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
93
+ "@deepseek-ai/dsh-host-webserver": "^0.2.1-alpha.1",
87
94
  "@types/node": "^24.0.0",
88
- "@deepseek-ai/dsh-workspace": "^0.1.0-rc.6",
89
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
90
- "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
91
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
92
- "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.6"
95
+ "@deepseek-ai/dsh-workspace": "^0.2.1-alpha.1",
96
+ "@deepseek-ai/dsh-skill": "^0.2.1-alpha.1",
97
+ "@deepseek-ai/dsh-session": "^0.2.1-alpha.1",
98
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.2.1-alpha.1",
99
+ "@deepseek-ai/dsh-client-ui-commands": "^0.2.1-alpha.1"
93
100
  },
94
101
  "repository": {
95
102
  "type": "git",
@@ -1,5 +1,6 @@
1
1
  import assert from 'node:assert/strict'
2
2
  import test from 'node:test'
3
+ import { readFileSync } from 'node:fs'
3
4
  import { compareVersions, currentVersion, updateCommand } from '../src/update.ts'
4
5
 
5
6
  test('compares stable semantic versions', () => {
@@ -14,7 +15,8 @@ test('orders prereleases before stable releases', () => {
14
15
  })
15
16
 
16
17
  test('reads package version and produces an exact update command', () => {
17
- assert.equal(currentVersion(), '0.2.4')
18
+ const manifest = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
19
+ assert.equal(currentVersion(), manifest.version)
18
20
  assert.equal(
19
21
  updateCommand('0.2.4'),
20
22
  'npx @deepseek-ai/dsh plugin --profile web add dsh-skill-importer@0.2.4',
@@ -1,9 +0,0 @@
1
- /** Session-routed request emitted after a non-React command popup edits the draft. */
2
- export interface ComposerFocusRequest {
3
- readonly sessionId: string;
4
- readonly expectedDraft: string;
5
- readonly caret: number;
6
- }
7
- export declare const COMPOSER_FOCUS_EVENT = "dsh-skill-importer/composer-focus";
8
- /** Ask the mounted picker in one session to restore its composer focus. */
9
- export declare function requestComposerFocus(request: ComposerFocusRequest): void;