dsh-desktop-kit 1.0.0 → 2.0.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/README.md +106 -41
- package/client.js +780 -28
- package/docs/ARCHITECTURE.md +114 -0
- package/docs/COMPATIBILITY.md +61 -0
- package/docs/INSTALL.md +97 -0
- package/docs/PRIVACY.md +50 -0
- package/docs/ROADMAP.md +57 -0
- package/docs/TOKENS.md +118 -0
- package/docs/TROUBLESHOOTING.md +68 -0
- package/docs/images/hero.png +0 -0
- package/index.js +4 -0
- package/package.json +15 -5
- package/plugins/dsh-gkb-ru-ui/lib/client.js +276 -28
- package/plugins/dsh-gkb-ru-ui/lib/index.js +45 -1
- package/plugins/dsh-gkb-ru-ui/lib/skills.js +195 -1
- package/plugins/dsh-gkb-ru-ui/package.json +2 -2
- package/plugins/dsh-gkb-ru-ui/screenshots/01-home-tiles-1440-light.png +0 -0
- package/plugins/dsh-gkb-ru-ui/screenshots/02-skills-1440-light.png +0 -0
- package/plugins/dsh-gkb-ru-ui/screenshots/03-skills-editor-1440-light.png +0 -0
- package/plugins/dsh-gkb-ru-ui/screenshots/04-skills-1440-dark.png +0 -0
- package/plugins/dsh-gkb-ru-ui/screenshots/05-skills-390-light.png +0 -0
- package/plugins/dsh-gkb-ru-ui/screenshots/06-home-tiles-1440-dark.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/01-real-time-peak-start.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/02-real-time-peak-end.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/03-peak-card-1440-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/04-peak-card-1440-dark.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/05-peak-card-390-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/05-peak-card-768-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/06-peak-card-390-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/07-live-preview-check.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/07-pre-peak-1440-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/08-peak-start-1440-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/09-peak-end-1440-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/10-pre-peak-card-1440-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/11-pre-peak-card-1440-dark.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/12-pre-peak-card-390-light.png +0 -0
- package/plugins/dsh-peak-guard/screenshots/qa-report.json +74 -0
- package/plugins/dsh-profile-transfer/screenshots/01-settings-transfer-1440-light.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/02-settings-transfer-preview-1440-light.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/03-settings-transfer-1440-dark.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/04-settings-transfer-390-light.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/05-settings-transfer-768-light.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/06-settings-transfer-390-dark.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/07-settings-transfer-export-result.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/08-settings-transfer-workspaces-1440-light.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/09-settings-transfer-workspaces-1440-dark.png +0 -0
- package/plugins/dsh-profile-transfer/screenshots/10-settings-transfer-workspaces-390-light.png +0 -0
- package/plugins/dsh-session-move/screenshots/01-row-menu-1440-light.png +0 -0
- package/plugins/dsh-session-move/screenshots/02-dialog-1440-light.png +0 -0
- package/plugins/dsh-session-move/screenshots/03-dialog-390-light.png +0 -0
- package/plugins/dsh-session-move/screenshots/04-dialog-1440-dark.png +0 -0
- package/plugins/dsh-session-move/screenshots/05-drag-highlight-1440-light.png +0 -0
- package/plugins/dsh-session-move/screenshots/06-drop-ungrouped-highlight.png +0 -0
- package/plugins/dsh-session-move/screenshots/07-after-drop-ungrouped.png +0 -0
- package/plugins/dsh-session-move/screenshots/08-move-dialog.png +0 -0
- package/plugins/dsh-session-move/screenshots/09-moved-to-second-workspace.png +0 -0
- package/plugins/dsh-session-move/screenshots/qa-report.json +62 -0
- package/plugins/dsh-skill-autopilot/cordis.patch.yml +3 -0
- package/plugins/dsh-skill-autopilot/index.js +444 -0
- package/plugins/dsh-skill-autopilot/package.json +19 -0
- package/plugins/dsh-token-lab/cordis.patch.yml +3 -0
- package/plugins/dsh-token-lab/lib/client.js +504 -0
- package/plugins/dsh-token-lab/lib/index.js +275 -0
- package/plugins/dsh-token-lab/package.json +26 -0
- package/plugins/dsh-token-lab/screenshots/01-token-lab-1440-light.png +0 -0
- package/plugins/dsh-token-lab/screenshots/02-token-lab-1440-dark.png +0 -0
- package/skills/code-review-checklist/SKILL.md +48 -30
- package/skills/content-writing/SKILL.md +64 -327
- package/skills/content-writing/references/process.md +123 -0
- package/skills/content-writing/references/quick-recipes.md +99 -0
- package/skills/content-writing/references/rules.md +85 -0
- package/skills/content-writing/references/sources.md +49 -0
- package/skills/context-economy/SKILL.md +60 -0
- package/skills/context-economy/references/long-session.md +35 -0
- package/skills/context-economy/references/token-math.md +42 -0
- package/skills/context-economy/references/tool-recipes.md +34 -0
- package/skills/database-safety/SKILL.md +40 -24
- package/skills/debugging-playbook/SKILL.md +30 -27
- package/skills/design-critique/SKILL.md +57 -110
- package/skills/design-critique/references/a11y.md +25 -0
- package/skills/design-critique/references/diagnoses.md +33 -0
- package/skills/design-critique/references/quick-tests.md +30 -0
- package/skills/design-critique/references/report-template.md +63 -0
- package/skills/design-critique/references/rubric-fast.md +73 -0
- package/skills/dev-workflow/SKILL.md +41 -34
- package/skills/dev-workflow/references/definition-of-done.md +44 -0
- package/skills/dev-workflow/references/memory-and-boundaries.md +31 -0
- package/skills/dev-workflow/references/stages.md +67 -0
- package/skills/git-and-ci/SKILL.md +46 -26
- package/skills/pg-upgrade-verify/SKILL.md +54 -35
- package/skills/project-deep-dive/SKILL.md +39 -164
- package/skills/project-deep-dive/references/recon-commands.md +12 -0
- package/skills/project-deep-dive/references/section-templates.md +2 -0
- package/skills/project-deep-dive/references/tool-and-process.md +86 -0
- package/skills/project-memory-maintenance/SKILL.md +39 -154
- package/skills/project-memory-maintenance/references/api-and-checklist.md +99 -0
- package/skills/project-memory-maintenance/references/journal-template.md +2 -0
- package/skills/project-memory-maintenance/references/section-rules.md +2 -0
- package/skills/release-and-deploy/SKILL.md +46 -32
- package/skills/requirements-and-planning/SKILL.md +44 -110
- package/skills/requirements-and-planning/references/antipatterns-and-checklist.md +20 -0
- package/skills/requirements-and-planning/references/process-steps.md +52 -0
- package/skills/requirements-and-planning/references/templates-and-estimates.md +29 -0
- package/skills/security-review/SKILL.md +33 -29
- package/skills/seo/SKILL.md +53 -305
- package/skills/seo/references/antipatterns.md +66 -0
- package/skills/seo/references/audit-checklist.md +14 -0
- package/skills/seo/references/content-seo.md +180 -174
- package/skills/seo/references/eeat-medical.md +2 -0
- package/skills/seo/references/measurement.md +28 -1
- package/skills/seo/references/on-page.md +5 -0
- package/skills/seo/references/page-templates.md +56 -0
- package/skills/seo/references/stack-recipes.md +2 -0
- package/skills/seo/references/structured-data.md +2 -0
- package/skills/seo/references/technical-seo.md +2 -0
- package/skills/service-desk-conventions/SKILL.md +40 -28
- package/skills/service-desk-db-safety/SKILL.md +39 -28
- package/skills/service-desk-release/SKILL.md +40 -22
- package/skills/service-desk-testing/SKILL.md +47 -33
- package/skills/service-desk-ui/SKILL.md +43 -24
- package/skills/skills-router/SKILL.md +44 -82
- package/skills/skills-router/references/applying-skills.md +25 -0
- package/skills/skills-router/references/routing-matrix.md +52 -0
- package/skills/testing-strategy/SKILL.md +47 -32
- package/skills/ui-design-system/SKILL.md +43 -38
- package/skills/ui-design-system/references/accessibility-and-responsive.md +50 -0
- package/skills/ui-design-system/references/tokens-and-components.md +67 -0
- package/skills/ui-design-system/references/visual-qa.md +44 -0
- package/skills/web-research/SKILL.md +40 -33
- package/skills/web-research/references/answer-and-citations.md +60 -0
- package/skills/web-research/references/query-recipes.md +44 -0
- package/skills/wow-design/SKILL.md +82 -161
- package/skills/wow-design/references/anti-patterns.md +3 -0
- package/skills/wow-design/references/critique-rubric.md +3 -0
- package/skills/wow-design/references/design-brief-template.md +2 -0
- package/skills/wow-design/references/inspiration.md +3 -0
- package/skills/wow-design/references/presets.md +3 -0
- package/skills/wow-design/references/principles.md +3 -0
- package/skills/wow-design/references/quick-presets.md +50 -0
- package/skills/wow-design/references/report-template.md +21 -0
- package/skills/wow-design/references/stack-recipes.md +3 -0
- package/skills/wow-design/references/visual-qa.md +3 -0
- package/skills/wow-design/references/wow-levers.md +43 -0
- package/tools/skill-cost.mjs +76 -0
|
@@ -32,6 +32,8 @@ const SKILL_CATEGORIES = {
|
|
|
32
32
|
"dev-workflow": ["process", "Процесс"],
|
|
33
33
|
"requirements-and-planning": ["process", "Процесс"],
|
|
34
34
|
"skills-router": ["process", "Процесс"],
|
|
35
|
+
"context-economy": ["process", "Процесс"],
|
|
36
|
+
"requirements-and-planning": ["process", "Процесс"],
|
|
35
37
|
"testing-strategy": ["quality", "Качество"],
|
|
36
38
|
"debugging-playbook": ["quality", "Качество"],
|
|
37
39
|
"code-review-checklist": ["quality", "Качество"],
|
|
@@ -51,9 +53,24 @@ const SKILL_CATEGORIES = {
|
|
|
51
53
|
|
|
52
54
|
const ZSTD_MAGIC = Buffer.from([0x28, 0xb5, 0x2f, 0xfd]);
|
|
53
55
|
const CACHE_TTL_MS = 30 * 1000;
|
|
56
|
+
const CORE_TOKEN_BUDGET = 6000;
|
|
57
|
+
const MAX_SKILL_BYTES = 200 * 1024;
|
|
58
|
+
|
|
59
|
+
/** Rough token count for mixed Russian/English markdown. */
|
|
60
|
+
export function approxTokens(bytes) {
|
|
61
|
+
return Math.max(40, Math.round(Number(bytes) / 3.2));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function skillNameIsValid(name) {
|
|
65
|
+
return typeof name === "string" && /^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name) && name.length <= 64;
|
|
66
|
+
}
|
|
54
67
|
|
|
55
68
|
let cache = { key: "", at: 0, data: null };
|
|
56
69
|
|
|
70
|
+
export function invalidateSkillsCache() {
|
|
71
|
+
cache = { key: "", at: 0, data: null };
|
|
72
|
+
}
|
|
73
|
+
|
|
57
74
|
export function skillsHome() {
|
|
58
75
|
return process.env.DSH_HOME ?? path.join(os.homedir(), ".dsh");
|
|
59
76
|
}
|
|
@@ -160,6 +177,8 @@ export function listSkills(home = skillsHome()) {
|
|
|
160
177
|
const front = parseFrontmatter(text);
|
|
161
178
|
const stats = walkStats(skillDir);
|
|
162
179
|
const category = SKILL_CATEGORIES[entry.name] ?? ["other", "Другое"];
|
|
180
|
+
const skillBytes = Buffer.byteLength(text, "utf8");
|
|
181
|
+
const tokens = approxTokens(skillBytes);
|
|
163
182
|
skills.push({
|
|
164
183
|
name: front.name.length > 0 ? front.name : entry.name,
|
|
165
184
|
directory: entry.name,
|
|
@@ -172,6 +191,9 @@ export function listSkills(home = skillsHome()) {
|
|
|
172
191
|
color: CATEGORY_COLORS[category[0]] ?? CATEGORY_COLORS.other,
|
|
173
192
|
files: stats.files,
|
|
174
193
|
bytes: stats.bytes,
|
|
194
|
+
skillBytes,
|
|
195
|
+
tokens,
|
|
196
|
+
heavy: tokens > CORE_TOKEN_BUDGET,
|
|
175
197
|
human: humanSize(stats.bytes),
|
|
176
198
|
updatedAt: stats.updatedAt > 0 ? new Date(stats.updatedAt).toISOString() : null,
|
|
177
199
|
references: stats.references === 1,
|
|
@@ -352,6 +374,10 @@ export function collectSkillsData(home = skillsHome(), sessionId = null) {
|
|
|
352
374
|
used: skills.filter((skill) => skill.usage.count > 0).length,
|
|
353
375
|
runs: totalRuns,
|
|
354
376
|
active: active.length,
|
|
377
|
+
tokens: skills.reduce((sum, skill) => sum + (skill.tokens || 0), 0),
|
|
378
|
+
heavy: skills.filter((skill) => skill.heavy).length,
|
|
379
|
+
references: skills.filter((skill) => skill.references).length,
|
|
380
|
+
budget: CORE_TOKEN_BUDGET,
|
|
355
381
|
},
|
|
356
382
|
active,
|
|
357
383
|
categories: Object.entries(CATEGORY_COLORS).map(([id, color]) => ({ id, label: (skills.find((skill) => skill.category === id)?.categoryLabel) ?? id, color })),
|
|
@@ -372,5 +398,173 @@ export function readSkillContent(home, name) {
|
|
|
372
398
|
} catch {
|
|
373
399
|
content = "";
|
|
374
400
|
}
|
|
375
|
-
return { ...skill, content:
|
|
401
|
+
return { ...skill, content, resources: listSkillResources(skill.path) };
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* ------------------------------------------------------------------ */
|
|
405
|
+
/* skill studio: read resources, write, create, duplicate, archive */
|
|
406
|
+
/* ------------------------------------------------------------------ */
|
|
407
|
+
|
|
408
|
+
function listSkillResources(skillDir) {
|
|
409
|
+
const resources = [];
|
|
410
|
+
const walk = (current, depth) => {
|
|
411
|
+
if (depth > 3) return;
|
|
412
|
+
let entries = [];
|
|
413
|
+
try {
|
|
414
|
+
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
415
|
+
} catch {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
for (const entry of entries) {
|
|
419
|
+
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
420
|
+
const full = path.join(current, entry.name);
|
|
421
|
+
if (entry.isDirectory()) {
|
|
422
|
+
walk(full, depth + 1);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
if (entry.name === "SKILL.md") continue;
|
|
426
|
+
try {
|
|
427
|
+
const stat = fs.statSync(full);
|
|
428
|
+
if (!/\.(md|txt|json|ya?ml)$/u.test(entry.name)) continue;
|
|
429
|
+
resources.push({
|
|
430
|
+
path: path.relative(skillDir, full).replaceAll("\\", "/"),
|
|
431
|
+
bytes: stat.size,
|
|
432
|
+
tokens: approxTokens(stat.size),
|
|
433
|
+
});
|
|
434
|
+
} catch {
|
|
435
|
+
/* skip */
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
walk(skillDir, 0);
|
|
440
|
+
resources.sort((left, right) => right.tokens - left.tokens);
|
|
441
|
+
return resources;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function resolveSkill(home, name) {
|
|
445
|
+
const skills = listSkills(home);
|
|
446
|
+
return skills.find((item) => item.name === name || item.directory === name) ?? null;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function backupFile(home, skillFile, name) {
|
|
450
|
+
try {
|
|
451
|
+
if (!fs.existsSync(skillFile)) return null;
|
|
452
|
+
const directory = path.join(home, "skills", ".dsh-kit-backups");
|
|
453
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
454
|
+
const stamp = new Date().toISOString().replace(/[:.]/gu, "-");
|
|
455
|
+
const target = path.join(directory, `${name}-${stamp}.md`);
|
|
456
|
+
fs.copyFileSync(skillFile, target);
|
|
457
|
+
return target;
|
|
458
|
+
} catch {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function assertContent(content) {
|
|
464
|
+
if (typeof content !== "string") throw Object.assign(new Error("content должен быть строкой"), { code: "skills/bad-request" });
|
|
465
|
+
const bytes = Buffer.byteLength(content, "utf8");
|
|
466
|
+
if (bytes > MAX_SKILL_BYTES) {
|
|
467
|
+
throw Object.assign(new Error(`слишком большой SKILL.md: ${bytes} байт > ${MAX_SKILL_BYTES}`), { code: "skills/too-large" });
|
|
468
|
+
}
|
|
469
|
+
const front = content.match(/^---\r?\n([\s\S]*?)\r?\n---/u);
|
|
470
|
+
if (front === null) {
|
|
471
|
+
throw Object.assign(new Error("нет frontmatter: файл должен начинаться с --- и полей name/description"), { code: "skills/bad-request" });
|
|
472
|
+
}
|
|
473
|
+
const nameLine = front[1].match(/^name:\s*(.+)$/mu);
|
|
474
|
+
if (nameLine === null) {
|
|
475
|
+
throw Object.assign(new Error("во frontmatter нет поля name"), { code: "skills/bad-request" });
|
|
476
|
+
}
|
|
477
|
+
return { bytes, frontName: unquote(nameLine[1]) };
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export function saveSkillContent(home, name, content) {
|
|
481
|
+
const skill = resolveSkill(home, name);
|
|
482
|
+
if (skill === null) throw Object.assign(new Error(`навык «${name}» не найден`), { code: "skills/not-found" });
|
|
483
|
+
const { bytes, frontName } = assertContent(content);
|
|
484
|
+
if (frontName !== skill.directory) {
|
|
485
|
+
throw Object.assign(new Error(`поле name (${frontName}) не совпадает с папкой (${skill.directory}); переименование — через дубликат`), { code: "skills/bad-request" });
|
|
486
|
+
}
|
|
487
|
+
const backup = backupFile(home, skill.skillFile, skill.directory);
|
|
488
|
+
const temp = `${skill.skillFile}.tmp-${process.pid}-${Date.now()}`;
|
|
489
|
+
fs.writeFileSync(temp, content, "utf8");
|
|
490
|
+
fs.renameSync(temp, skill.skillFile);
|
|
491
|
+
invalidateSkillsCache();
|
|
492
|
+
return { ...readSkillContent(home, skill.name), bytes, backup, savedAt: new Date().toISOString() };
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export function skillTemplate(name, description) {
|
|
496
|
+
return `---
|
|
497
|
+
name: ${name}
|
|
498
|
+
description: "${String(description ?? "").replaceAll('"', "'").slice(0, 200)}"
|
|
499
|
+
whenToUse: "Когда задача совпадает с триггерами ниже"
|
|
500
|
+
user-invocable: true
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
# ${name} — ядро
|
|
504
|
+
|
|
505
|
+
> ≈400 токенов. Это ядро; детали — в references и только когда реально нужны.
|
|
506
|
+
|
|
507
|
+
## 0. Когда применять
|
|
508
|
+
- ...
|
|
509
|
+
|
|
510
|
+
## 1. Главное
|
|
511
|
+
1. ...
|
|
512
|
+
|
|
513
|
+
## 2. Куда грузить дальше
|
|
514
|
+
| Нужно | Файл | ≈токенов |
|
|
515
|
+
|---|---|---|
|
|
516
|
+
| ... | references/....md | ≈... |
|
|
517
|
+
|
|
518
|
+
## 3. Гейт перед сдачей
|
|
519
|
+
- [ ] ...
|
|
520
|
+
`;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export function createSkill(home, payload) {
|
|
524
|
+
const name = String(payload?.name ?? "").trim();
|
|
525
|
+
if (!skillNameIsValid(name)) {
|
|
526
|
+
throw Object.assign(new Error("имя навыка: только kebab-case [a-z0-9-], до 64 символов"), { code: "skills/bad-request" });
|
|
527
|
+
}
|
|
528
|
+
const directory = path.join(home, "skills", name);
|
|
529
|
+
if (fs.existsSync(directory)) {
|
|
530
|
+
throw Object.assign(new Error(`навык «${name}» уже существует`), { code: "skills/exists" });
|
|
531
|
+
}
|
|
532
|
+
const content = typeof payload?.content === "string" && payload.content.trim().length > 0
|
|
533
|
+
? payload.content
|
|
534
|
+
: skillTemplate(name, payload?.description);
|
|
535
|
+
assertContent(content);
|
|
536
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
537
|
+
fs.writeFileSync(path.join(directory, "SKILL.md"), content, "utf8");
|
|
538
|
+
invalidateSkillsCache();
|
|
539
|
+
return readSkillContent(home, name);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export function duplicateSkill(home, source, nextName) {
|
|
543
|
+
const skill = resolveSkill(home, source);
|
|
544
|
+
if (skill === null) throw Object.assign(new Error(`навык «${source}» не найден`), { code: "skills/not-found" });
|
|
545
|
+
const name = String(nextName ?? "").trim();
|
|
546
|
+
if (!skillNameIsValid(name)) {
|
|
547
|
+
throw Object.assign(new Error("новое имя: только kebab-case [a-z0-9-]"), { code: "skills/bad-request" });
|
|
548
|
+
}
|
|
549
|
+
const target = path.join(home, "skills", name);
|
|
550
|
+
if (fs.existsSync(target)) throw Object.assign(new Error(`навык «${name}» уже существует`), { code: "skills/exists" });
|
|
551
|
+
fs.cpSync(skill.path, target, { recursive: true });
|
|
552
|
+
const targetFile = path.join(target, "SKILL.md");
|
|
553
|
+
const text = fs.readFileSync(targetFile, "utf8");
|
|
554
|
+
const rewritten = text.replace(/^(---\r?\n[\s\S]*?)^name:\s*.+$/mu, `$1name: ${name}`);
|
|
555
|
+
fs.writeFileSync(targetFile, rewritten, "utf8");
|
|
556
|
+
invalidateSkillsCache();
|
|
557
|
+
return readSkillContent(home, name);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
export function deleteSkill(home, name) {
|
|
561
|
+
const skill = resolveSkill(home, name);
|
|
562
|
+
if (skill === null) throw Object.assign(new Error(`навык «${name}» не найден`), { code: "skills/not-found" });
|
|
563
|
+
const trash = path.join(home, "skills", ".dsh-kit-trash");
|
|
564
|
+
fs.mkdirSync(trash, { recursive: true });
|
|
565
|
+
const stamp = new Date().toISOString().replace(/[:.]/gu, "-");
|
|
566
|
+
const target = path.join(trash, `${stamp}-${skill.directory}`);
|
|
567
|
+
fs.renameSync(skill.path, target);
|
|
568
|
+
invalidateSkillsCache();
|
|
569
|
+
return { deleted: skill.directory, trash: target };
|
|
376
570
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-gkb-ru-ui",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Russian language pack for the DSH web GUI + sidebar
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Russian language pack for the DSH web GUI + compact AURORA sidebar tiles (skills/tokens/balance/spend) + Skills Studio: catalog, token cost, inline SKILL.md editor, create/duplicate/archive.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prePeak": {
|
|
3
|
+
"before": {
|
|
4
|
+
"fakeNow": "2026-11-04T05:54:59.118Z",
|
|
5
|
+
"mode": "off",
|
|
6
|
+
"cards": 0
|
|
7
|
+
},
|
|
8
|
+
"appeared": true,
|
|
9
|
+
"delayMs": 240,
|
|
10
|
+
"mode": "soon"
|
|
11
|
+
},
|
|
12
|
+
"peakStart": {
|
|
13
|
+
"before": {
|
|
14
|
+
"fakeNow": "2026-11-04T05:59:59.091Z",
|
|
15
|
+
"mode": "soon",
|
|
16
|
+
"cards": 1
|
|
17
|
+
},
|
|
18
|
+
"switched": true,
|
|
19
|
+
"delayMs": 217,
|
|
20
|
+
"mode": "peak"
|
|
21
|
+
},
|
|
22
|
+
"peakEnd": {
|
|
23
|
+
"before": {
|
|
24
|
+
"fakeNow": "2026-11-04T09:59:59.097Z",
|
|
25
|
+
"mode": "peak",
|
|
26
|
+
"cards": 1
|
|
27
|
+
},
|
|
28
|
+
"gone": true,
|
|
29
|
+
"delayMs": 240
|
|
30
|
+
},
|
|
31
|
+
"peakVisual": {
|
|
32
|
+
"mode": "peak",
|
|
33
|
+
"text": "×\nПИКОВЫЙ ТАРИФ\n×2\nТокены сейчас стоят вдвое дороже\nВ пиковые часы стоимость всех типов токенов для deepseek-flash и deepseek-v4-pro увеличивается вдвое. Вне этих часов действует скидка 50% (off-peak).\n26\nмин\nДО КОНЦА ПИ"
|
|
34
|
+
},
|
|
35
|
+
"peakAxe": {
|
|
36
|
+
"violations": []
|
|
37
|
+
},
|
|
38
|
+
"tablet": {
|
|
39
|
+
"scrollWidth": 768,
|
|
40
|
+
"clientWidth": 768,
|
|
41
|
+
"cardWidth": 310.828125
|
|
42
|
+
},
|
|
43
|
+
"mobile": {
|
|
44
|
+
"scrollWidth": 390,
|
|
45
|
+
"clientWidth": 390,
|
|
46
|
+
"cardWidth": 370
|
|
47
|
+
},
|
|
48
|
+
"dismissed": {
|
|
49
|
+
"cards": 0,
|
|
50
|
+
"stored": "1793786400000"
|
|
51
|
+
},
|
|
52
|
+
"soonVisual": {
|
|
53
|
+
"mode": "soon",
|
|
54
|
+
"text": "×\nСКОРО ПИК\n×2\nПиковый тариф начнётся через 4 мин\nСейчас ещё действует off-peak со скидкой 50%. Когда начнётся окно, все типы токенов будут стоить ×2 до самого конца пика.\n4\nмин\nДО НАЧАЛА ПИКА\nОкно 09:00–13:00 МСК\nСейчас 08:56\n→\nДО ПОДОРОЖА",
|
|
55
|
+
"badge": "Пик через 4 мин"
|
|
56
|
+
},
|
|
57
|
+
"soonMobile": {
|
|
58
|
+
"scrollWidth": 390,
|
|
59
|
+
"clientWidth": 390,
|
|
60
|
+
"cardWidth": 370
|
|
61
|
+
},
|
|
62
|
+
"offPeak": {
|
|
63
|
+
"mode": "off",
|
|
64
|
+
"cards": 0,
|
|
65
|
+
"badges": 0
|
|
66
|
+
},
|
|
67
|
+
"logs": [
|
|
68
|
+
"[info] [session-move] ready",
|
|
69
|
+
"[info] [profile-transfer] ready",
|
|
70
|
+
"[info] [peak-guard] ready",
|
|
71
|
+
"[error] [deepseek-account] account read failed {field: profile}",
|
|
72
|
+
"[error] [deepseek-account] account read failed {field: balance}"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/plugins/dsh-profile-transfer/screenshots/08-settings-transfer-workspaces-1440-light.png
ADDED
|
Binary file
|
package/plugins/dsh-profile-transfer/screenshots/09-settings-transfer-workspaces-1440-dark.png
ADDED
|
Binary file
|
package/plugins/dsh-profile-transfer/screenshots/10-settings-transfer-workspaces-390-light.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"steps": [
|
|
3
|
+
{
|
|
4
|
+
"name": "visible-session",
|
|
5
|
+
"value": {
|
|
6
|
+
"key": "session:session-73e5c76d-f3ae-43db-ac82-64e23969f6e4",
|
|
7
|
+
"id": "session-73e5c76d-f3ae-43db-ac82-64e23969f6e4",
|
|
8
|
+
"title": "БегЛокальная база знаний по проектам для ИИ1мин"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "axe-dialog",
|
|
13
|
+
"value": {
|
|
14
|
+
"violations": []
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "viewport-390",
|
|
19
|
+
"value": {
|
|
20
|
+
"scrollWidth": 390,
|
|
21
|
+
"clientWidth": 390,
|
|
22
|
+
"dialogWidth": 342,
|
|
23
|
+
"viewport": 390
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "dark-theme",
|
|
28
|
+
"value": {
|
|
29
|
+
"source": "system",
|
|
30
|
+
"background": "rgb(21, 21, 23)"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "dialog-closed",
|
|
35
|
+
"value": true
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "drag-highlight",
|
|
39
|
+
"value": {
|
|
40
|
+
"dragInfo": {
|
|
41
|
+
"ok": true
|
|
42
|
+
},
|
|
43
|
+
"visible": false
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"errors": [],
|
|
48
|
+
"screenshots": [
|
|
49
|
+
"%USERPROFILE%/Documents/deepseek-harness/default-workspace/projects/dsh-session-move/screenshots/01-row-menu-1440-light.png",
|
|
50
|
+
"%USERPROFILE%/Documents/deepseek-harness/default-workspace/projects/dsh-session-move/screenshots/02-dialog-1440-light.png",
|
|
51
|
+
"%USERPROFILE%/Documents/deepseek-harness/default-workspace/projects/dsh-session-move/screenshots/03-dialog-390-light.png",
|
|
52
|
+
"%USERPROFILE%/Documents/deepseek-harness/default-workspace/projects/dsh-session-move/screenshots/04-dialog-1440-dark.png",
|
|
53
|
+
"%USERPROFILE%/Documents/deepseek-harness/default-workspace/projects/dsh-session-move/screenshots/05-drag-highlight-1440-light.png"
|
|
54
|
+
],
|
|
55
|
+
"axe": {
|
|
56
|
+
"violations": []
|
|
57
|
+
},
|
|
58
|
+
"logs": [
|
|
59
|
+
"[info] [session-move] ready",
|
|
60
|
+
"[error] [deepseek-account] account read failed {field: profile}"
|
|
61
|
+
]
|
|
62
|
+
}
|