dsh-desktop-kit 2.7.3 → 2.7.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.7.4 (2026-11-11)
4
+
5
+ - **Agents project detection.** Settings → Агенты берёт `path` текущего workspace через `useWorkspaces` и передаёт `cwd`; хост предпочитает `cwd → sessionId → живая сессия`. Исправлен показ `C:\Users\bulav` вместо папки проекта.
6
+ - **Agents API fallback.** Если sessionId не пришёл, используется cwd последней живой сессии, а не `process.cwd()`.
7
+
3
8
  ## 2.7.3 (2026-11-11)
4
9
 
5
10
  - **Agents UI.** Настройки → **Агенты**: карточки `.dsh/agents/*.md`, enforced `permission`, tools и модель; 1440/390 скриншоты, аудит без overflow/markup.
package/README.md CHANGED
@@ -21,7 +21,7 @@
21
21
  - **Approval** — штатная карточка DSH: Allow once / Always allow / Reject.
22
22
  - **`.dsh/`** создаётся автоматически: agents, commands, rules, hooks, verify, mcp, PROJECT.md.
23
23
 
24
- **v2.7.3** · MIT · проверено на DSH `0.2.1-rc.5` и `0.2.2-rc.1` (Windows 11) · без внешних зависимостей и телеметрии
24
+ **v2.7.4** · MIT · проверено на DSH `0.2.1-rc.5` и `0.2.2-rc.1` (Windows 11) · без внешних зависимостей и телеметрии
25
25
 
26
26
  **План развития:** [docs/ROADMAP-3.0.md](docs/ROADMAP-3.0.md) — Memory Fabric, семантическое
27
27
  слияние, локальный индекс памяти, шифрованные переносы, Memory Hub и npm trusted publishing.
package/client.js CHANGED
@@ -7315,26 +7315,35 @@ var(--dsw-alias-bg-layer-1,#fff);box-shadow:inset 0 1px 0 color-mix(in srgb,#fff
7315
7315
  try {
7316
7316
  const sessions = Object.values(state.byId || {});
7317
7317
  const main = sessions.find((session) => session && session.retainedBy && (session.retainedBy.mainView || 0) > 0);
7318
- return main ? main.id : undefined;
7318
+ if (main) return main.id;
7319
+ const ids = Array.isArray(state.ids) ? state.ids : [];
7320
+ return ids.length > 0 ? ids[ids.length - 1] : undefined;
7319
7321
  } catch { return undefined; }
7320
7322
  }
7321
7323
 
7322
7324
  function AgentsSection(props) {
7323
7325
  const [state, setState] = useState({ loading: true, error: null, data: null });
7324
7326
  const useSessions = props && props.useSessions;
7327
+ const useWorkspaces = props && props.useWorkspaces;
7325
7328
  const sessionId = useSessions ? useSessions(currentSessionSelector) : undefined;
7329
+ const workspaceSnapshot = useWorkspaces ? useWorkspaces((snapshot) => snapshot) : undefined;
7330
+ const workspaces = Array.isArray(workspaceSnapshot?.items) ? workspaceSnapshot.items : [];
7331
+ const workspace = workspaces.find((item) => Array.isArray(item.sessionIds) && item.sessionIds.includes(sessionId))
7332
+ ?? workspaces.find((item) => Array.isArray(item.sessionIds) && item.sessionIds.length > 0)
7333
+ ?? workspaces[0];
7334
+ const cwd = typeof workspace?.path === "string" ? workspace.path : undefined;
7326
7335
  useEffect(() => {
7327
7336
  let cancelled = false;
7328
7337
  (async () => {
7329
7338
  try {
7330
- const data = await call(window.__DSH_AGENTS_CTX__, "list", { sessionId });
7339
+ const data = await call(window.__DSH_AGENTS_CTX__, "list", { sessionId, cwd });
7331
7340
  if (!cancelled) setState({ loading: false, error: null, data });
7332
7341
  } catch (error) {
7333
7342
  if (!cancelled) setState({ loading: false, error: fallbackError(error), data: null });
7334
7343
  }
7335
7344
  })();
7336
7345
  return () => { cancelled = true; };
7337
- }, [sessionId]);
7346
+ }, [sessionId, cwd]);
7338
7347
  const agents = state.data?.agents ?? [];
7339
7348
  const readOnly = agents.filter((agent) => agent.permission === "read-only").length;
7340
7349
  const models = new Set(agents.map((agent) => agent.model).filter(Boolean)).size;
@@ -7393,7 +7402,7 @@ var(--dsw-alias-bg-layer-1,#fff);box-shadow:inset 0 1px 0 color-mix(in srgb,#fff
7393
7402
  if (__kitErrors.length <= 5) console.error("[dsh-desktop-kit] registration failed:", label, message);
7394
7403
  };
7395
7404
  try {
7396
- window.__DSH_DESKTOP_KIT__ = { version: "2.7.3", parts: __partNames, errors: __kitErrors, ready: false };
7405
+ window.__DSH_DESKTOP_KIT__ = { version: "2.7.4", parts: __partNames, errors: __kitErrors, ready: false };
7397
7406
  } catch {}
7398
7407
  const __inject = [];
7399
7408
  for (const __part of __parts) {
@@ -0,0 +1,19 @@
1
+ # DSH Desktop Kit 2.7.4 — тест
2
+
3
+ Дата: 2026-11-11.
4
+
5
+ ## Что проверено
6
+
7
+ - `npm test` — exit 0.
8
+ - `npm run build:client` — OK; `check:client` — OK.
9
+ - Agents API: `cwd` из workspace, fallback на последнюю живую сессию.
10
+ - UI: Agents, MCP; скриншоты 390/1440.
11
+
12
+ ## Исправление
13
+
14
+ `C:\Users\bulav` в футере Agents был вызван fallback-ом на `process.cwd()`.
15
+ Теперь клиент передаёт путь текущего workspace, а хост проверяет его первым.
16
+
17
+ ## Ограничения
18
+
19
+ - MCP OAuth/prompts/sampling и worktrees не входят в 2.7.4.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-desktop-kit",
3
- "version": "2.7.3",
3
+ "version": "2.7.4",
4
4
  "description": "DeepSeek Harness desktop kit 2.7: 16 plugins and 30 skills — self-applying skills, token lab, Skills Studio, project memory, GitHub and USB memory transfer, guardrails, repo map, checkpoints, plan mode, browser QA, GitHub review, Claude Code-like hooks/agents/commands, Russian UI, peak guard, chat move and profile transfer.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -85,26 +85,35 @@ window.__ModuleLoader__.load({
85
85
  try {
86
86
  const sessions = Object.values(state.byId || {});
87
87
  const main = sessions.find((session) => session && session.retainedBy && (session.retainedBy.mainView || 0) > 0);
88
- return main ? main.id : undefined;
88
+ if (main) return main.id;
89
+ const ids = Array.isArray(state.ids) ? state.ids : [];
90
+ return ids.length > 0 ? ids[ids.length - 1] : undefined;
89
91
  } catch { return undefined; }
90
92
  }
91
93
 
92
94
  function AgentsSection(props) {
93
95
  const [state, setState] = useState({ loading: true, error: null, data: null });
94
96
  const useSessions = props && props.useSessions;
97
+ const useWorkspaces = props && props.useWorkspaces;
95
98
  const sessionId = useSessions ? useSessions(currentSessionSelector) : undefined;
99
+ const workspaceSnapshot = useWorkspaces ? useWorkspaces((snapshot) => snapshot) : undefined;
100
+ const workspaces = Array.isArray(workspaceSnapshot?.items) ? workspaceSnapshot.items : [];
101
+ const workspace = workspaces.find((item) => Array.isArray(item.sessionIds) && item.sessionIds.includes(sessionId))
102
+ ?? workspaces.find((item) => Array.isArray(item.sessionIds) && item.sessionIds.length > 0)
103
+ ?? workspaces[0];
104
+ const cwd = typeof workspace?.path === "string" ? workspace.path : undefined;
96
105
  useEffect(() => {
97
106
  let cancelled = false;
98
107
  (async () => {
99
108
  try {
100
- const data = await call(window.__DSH_AGENTS_CTX__, "list", { sessionId });
109
+ const data = await call(window.__DSH_AGENTS_CTX__, "list", { sessionId, cwd });
101
110
  if (!cancelled) setState({ loading: false, error: null, data });
102
111
  } catch (error) {
103
112
  if (!cancelled) setState({ loading: false, error: fallbackError(error), data: null });
104
113
  }
105
114
  })();
106
115
  return () => { cancelled = true; };
107
- }, [sessionId]);
116
+ }, [sessionId, cwd]);
108
117
  const agents = state.data?.agents ?? [];
109
118
  const readOnly = agents.filter((agent) => agent.permission === "read-only").length;
110
119
  const models = new Set(agents.map((agent) => agent.model).filter(Boolean)).size;
@@ -31,8 +31,13 @@ export function registerAgentApi(ctx) {
31
31
  const value = await envelope(request);
32
32
  rpcId = value.rpcId;
33
33
  if (value.method !== `${RPC_NAMESPACE}/list`) throw new Error("endpoint/method mismatch");
34
- const session = value.payload?.sessionId ? ctx.get?.("sessions")?.get?.(value.payload.sessionId) : undefined;
35
- const project = projectFor(session?.header?.cwd || value.payload?.cwd || process.cwd());
34
+ const sessions = ctx.get?.("sessions");
35
+ let session = value.payload?.sessionId ? sessions?.get?.(value.payload.sessionId) : undefined;
36
+ if (!session && typeof sessions?.list === "function") {
37
+ const live = sessions.list();
38
+ session = live.length > 0 ? live[live.length - 1] : undefined;
39
+ }
40
+ const project = projectFor(value.payload?.cwd || session?.header?.cwd || process.cwd());
36
41
  const agents = loadAgents(project.root, project.dsh).map((agent) => ({
37
42
  name: agent.name,
38
43
  description: agent.description,