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 +5 -0
- package/README.md +1 -1
- package/client.js +13 -4
- package/docs/TEST-2.7.4.md +19 -0
- package/package.json +1 -1
- package/plugins/dsh-agent-extensions/client.js +12 -3
- package/plugins/dsh-agent-extensions/lib/api.js +7 -2
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.
|
|
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
|
-
|
|
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.
|
|
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
|
+
"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
|
-
|
|
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
|
|
35
|
-
|
|
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,
|