dsh-novel-generator 0.1.1 → 0.1.2
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/client.js +26 -16
- package/package.json +3 -2
package/client.js
CHANGED
|
@@ -185,6 +185,7 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
185
185
|
.dsn-input:focus,.dsn-select:focus,.dsn-textarea:focus{border-color:var(--dsw-alias-brand-primary)}
|
|
186
186
|
.dsn-input.dsn-readonly{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);cursor:default}
|
|
187
187
|
.dsn-input.dsn-readonly:focus{border-color:var(--dsw-alias-border-l1)}
|
|
188
|
+
.dsn-input.dsn-input-invalid{border-color:var(--dsw-alias-state-warn-primary)}
|
|
188
189
|
.dsn-path{display:flex;gap:6px}
|
|
189
190
|
.dsn-list{display:flex;flex-direction:column;gap:8px}
|
|
190
191
|
.dsn-row{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:12px;
|
|
@@ -425,7 +426,7 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
425
426
|
}, busy ? t('保存中…', "Saving…") : t('保存', "Save")))));
|
|
426
427
|
}
|
|
427
428
|
|
|
428
|
-
function ProjectsPage({ boot,
|
|
429
|
+
function ProjectsPage({ boot, resolveWorkspace, onOpen, onReload, onEditModel }) {
|
|
429
430
|
const [title, setTitle] = useState('');
|
|
430
431
|
const [cwd, setCwd] = useState('');
|
|
431
432
|
const [preset, setPreset] = useState('');
|
|
@@ -451,17 +452,20 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
451
452
|
}, [models]);
|
|
452
453
|
|
|
453
454
|
const pickDirectory = useCallback(async () => {
|
|
454
|
-
|
|
455
|
-
|
|
455
|
+
// Resolved at click time: the workspace service may activate after this
|
|
456
|
+
// plugin, so an instance captured in `apply` can come back undefined.
|
|
457
|
+
const ui = typeof resolveWorkspace === 'function' ? resolveWorkspace() : null;
|
|
458
|
+
if (!ui || typeof ui.pickDirectory !== 'function') {
|
|
459
|
+
setError(t('目录选择器还没就绪,请稍后再点一次「选择」', 'The directory picker is not ready yet — try "Select" again in a moment.'));
|
|
456
460
|
return;
|
|
457
461
|
}
|
|
458
462
|
try {
|
|
459
|
-
const picked = await
|
|
463
|
+
const picked = await ui.pickDirectory();
|
|
460
464
|
if (picked) setCwd(picked);
|
|
461
465
|
} catch (pickError) {
|
|
462
466
|
setError(messageOf(pickError));
|
|
463
467
|
}
|
|
464
|
-
}, [
|
|
468
|
+
}, [resolveWorkspace]);
|
|
465
469
|
|
|
466
470
|
const create = useCallback(async () => {
|
|
467
471
|
setError('');
|
|
@@ -502,13 +506,12 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
502
506
|
h('label', { className: 'dsn-field' },
|
|
503
507
|
h('span', { className: 'dsn-label' }, t('作品名称', "Title")),
|
|
504
508
|
h('input', {
|
|
505
|
-
className: 'dsn-input'
|
|
509
|
+
className: `dsn-input${titleIssue ? ' dsn-input-invalid' : ''}`,
|
|
506
510
|
value: title,
|
|
507
511
|
placeholder: t('例如:长夜将尽', "e.g. The Long Night Ends"),
|
|
512
|
+
title: titleIssue || t('会成为工作目录下的文件夹名', "Becomes a folder name inside the working directory."),
|
|
508
513
|
onChange: (event) => setTitle(event.target.value),
|
|
509
|
-
}),
|
|
510
|
-
h('span', { className: `dsn-hint${titleIssue ? ' warn' : ''}` },
|
|
511
|
-
titleIssue || t('会成为工作目录下的文件夹名', "Becomes a folder name inside the working directory."))),
|
|
514
|
+
})),
|
|
512
515
|
h('label', { className: 'dsn-field' },
|
|
513
516
|
h('span', { className: 'dsn-label' }, t('工作目录', "Working directory")),
|
|
514
517
|
h('div', { className: 'dsn-path' },
|
|
@@ -557,7 +560,9 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
557
560
|
onClick: create,
|
|
558
561
|
}, busy ? t('创建中…', "Creating…") : t('创建作品并开会话', "Create work and open its session")))),
|
|
559
562
|
|
|
560
|
-
error
|
|
563
|
+
error || titleIssue
|
|
564
|
+
? h('div', { className: 'dsn-error', style: { margin: 0 } }, error || titleIssue)
|
|
565
|
+
: null,
|
|
561
566
|
|
|
562
567
|
h('div', { className: 'dsn-list' },
|
|
563
568
|
boot.projects.length === 0
|
|
@@ -1654,7 +1659,7 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
1654
1659
|
|
|
1655
1660
|
/* ------------------------------------------------------------ studio app */
|
|
1656
1661
|
|
|
1657
|
-
function StudioApp({
|
|
1662
|
+
function StudioApp({ resolveWorkspace }) {
|
|
1658
1663
|
// Subscribes every screen below to Settings → General → Language.
|
|
1659
1664
|
useLocaleId();
|
|
1660
1665
|
const [boot, setBoot] = useState(null);
|
|
@@ -1742,7 +1747,7 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
1742
1747
|
? h('div', { className: 'dsn-scroll' },
|
|
1743
1748
|
h(ProjectsPage, {
|
|
1744
1749
|
boot,
|
|
1745
|
-
|
|
1750
|
+
resolveWorkspace,
|
|
1746
1751
|
onOpen: openProject,
|
|
1747
1752
|
onReload: loadBoot,
|
|
1748
1753
|
onEditModel: setModelTarget,
|
|
@@ -1772,12 +1777,12 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
1772
1777
|
: null);
|
|
1773
1778
|
}
|
|
1774
1779
|
|
|
1775
|
-
function StudioOverlay({
|
|
1780
|
+
function StudioOverlay({ resolveWorkspace }) {
|
|
1776
1781
|
const open = useOverlayOpen();
|
|
1777
1782
|
if (!open) return null;
|
|
1778
1783
|
// No backdrop-click close: leaving with unsaved chapter text goes through
|
|
1779
1784
|
// the 关闭 button, which asks first.
|
|
1780
|
-
return h('div', { className: 'dsn-overlay' }, h(StudioApp, {
|
|
1785
|
+
return h('div', { className: 'dsn-overlay' }, h(StudioApp, { resolveWorkspace }));
|
|
1781
1786
|
}
|
|
1782
1787
|
|
|
1783
1788
|
/* ---------------------------------------------------------------- apply */
|
|
@@ -1785,7 +1790,12 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
1785
1790
|
return {
|
|
1786
1791
|
inject: ['slots'],
|
|
1787
1792
|
apply(ctx) {
|
|
1788
|
-
|
|
1793
|
+
/**
|
|
1794
|
+
* Read at use time, not at activation: this plugin may mount before the
|
|
1795
|
+
* workspace UI that owns `uiWorkspace`, and a captured instance would
|
|
1796
|
+
* then be undefined for the life of the page.
|
|
1797
|
+
*/
|
|
1798
|
+
const resolveWorkspace = () => ctx.get('uiWorkspace') || null;
|
|
1789
1799
|
// Settings → General → Language drives every string that goes through
|
|
1790
1800
|
// the translator below; a host without the service stays Chinese.
|
|
1791
1801
|
localeService = ctx.get('locale') || null;
|
|
@@ -1798,7 +1808,7 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
1798
1808
|
name: 'shell.overlay',
|
|
1799
1809
|
id: 'dsh-novel-generator-studio',
|
|
1800
1810
|
order: 40,
|
|
1801
|
-
}, () => h(StudioOverlay, {
|
|
1811
|
+
}, () => h(StudioOverlay, { resolveWorkspace })));
|
|
1802
1812
|
},
|
|
1803
1813
|
};
|
|
1804
1814
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-novel-generator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Novel studio for DeepSeek Harness: a draggable story timeline, world snapshots, chapter outlines, and chapters written by the work's own agent.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"platform": "web",
|
|
52
52
|
"immediately": true,
|
|
53
53
|
"inject": [
|
|
54
|
-
"@deepseek-ai/dsh-client-locale"
|
|
54
|
+
"@deepseek-ai/dsh-client-locale",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-workspace"
|
|
55
56
|
]
|
|
56
57
|
}
|
|
57
58
|
}
|