dsh-novel-generator 0.1.2 → 0.1.3
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 +17 -10
- package/index.js +4 -3
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -437,9 +437,10 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
437
437
|
const [busy, setBusy] = useState(false);
|
|
438
438
|
const [error, setError] = useState('');
|
|
439
439
|
|
|
440
|
-
// The title becomes a folder name inside the working directory
|
|
441
|
-
|
|
442
|
-
const
|
|
440
|
+
// The title becomes a folder name inside the working directory, and it is
|
|
441
|
+
// required: an empty name is reported when the user tries to create.
|
|
442
|
+
const trimmedTitle = title.trim();
|
|
443
|
+
const titleIssue = trimmedTitle === '' ? '' : titleProblem(trimmedTitle);
|
|
443
444
|
|
|
444
445
|
const groups = (boot.models && boot.models.groups) || [];
|
|
445
446
|
const models = useMemo(() => {
|
|
@@ -469,6 +470,14 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
469
470
|
|
|
470
471
|
const create = useCallback(async () => {
|
|
471
472
|
setError('');
|
|
473
|
+
if (trimmedTitle === '') {
|
|
474
|
+
setError(t('作品名称不能为空', "Title cannot be empty."));
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
if (titleIssue) {
|
|
478
|
+
setError(titleIssue);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
472
481
|
if (!cwd.trim()) {
|
|
473
482
|
setError(t('请先点「选择」挑一个工作目录', "Pick a working directory with \"Select\" first."));
|
|
474
483
|
return;
|
|
@@ -476,7 +485,7 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
476
485
|
setBusy(true);
|
|
477
486
|
try {
|
|
478
487
|
const result = await api('/project/create', {
|
|
479
|
-
title:
|
|
488
|
+
title: trimmedTitle,
|
|
480
489
|
cwd: cwd.trim(),
|
|
481
490
|
agentPreset: preset || undefined,
|
|
482
491
|
model: provider && model ? { provider, model } : null,
|
|
@@ -489,7 +498,7 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
489
498
|
} finally {
|
|
490
499
|
setBusy(false);
|
|
491
500
|
}
|
|
492
|
-
}, [
|
|
501
|
+
}, [trimmedTitle, titleIssue, cwd, preset, provider, model, onOpen, onReload]);
|
|
493
502
|
|
|
494
503
|
const remove = useCallback(async (project) => {
|
|
495
504
|
if (!window.confirm(t('确定删除作品「{title}」?这会同时删除工作目录下的作品文件夹(正文、梗概、世界快照)。作品的会话本身保留。', 'Delete the work “{title}”? This also deletes its folder in the working directory (chapters, outlines, world snapshots). The session itself stays.', { title: project.title }))) return;
|
|
@@ -555,14 +564,12 @@ body[data-ds-dark-theme] .dsn-shell{color-scheme:dark}
|
|
|
555
564
|
h('button', {
|
|
556
565
|
className: 'dsn-btn primary',
|
|
557
566
|
type: 'button',
|
|
558
|
-
|
|
559
|
-
|
|
567
|
+
// Enabled even when the form is incomplete: the click itself says why.
|
|
568
|
+
disabled: busy,
|
|
560
569
|
onClick: create,
|
|
561
570
|
}, busy ? t('创建中…', "Creating…") : t('创建作品并开会话', "Create work and open its session")))),
|
|
562
571
|
|
|
563
|
-
error
|
|
564
|
-
? h('div', { className: 'dsn-error', style: { margin: 0 } }, error || titleIssue)
|
|
565
|
-
: null,
|
|
572
|
+
error ? h('div', { className: 'dsn-error', style: { margin: 0 } }, error) : null,
|
|
566
573
|
|
|
567
574
|
h('div', { className: 'dsn-list' },
|
|
568
575
|
boot.projects.length === 0
|
package/index.js
CHANGED
|
@@ -982,7 +982,7 @@ async function bootstrap(ctx, root) {
|
|
|
982
982
|
}
|
|
983
983
|
}
|
|
984
984
|
return {
|
|
985
|
-
revision: '2026-10-20.
|
|
985
|
+
revision: '2026-10-20.15',
|
|
986
986
|
projects,
|
|
987
987
|
models: {
|
|
988
988
|
default: modelCatalog.default || null,
|
|
@@ -1005,8 +1005,9 @@ async function bootstrap(ctx, root) {
|
|
|
1005
1005
|
async function createProject(ctx, root, body) {
|
|
1006
1006
|
const controller = ctx.get('sessionController');
|
|
1007
1007
|
if (controller === undefined) throw httpError(503, '当前部署缺少 sessionController 服务,无法创建会话');
|
|
1008
|
-
|
|
1009
|
-
//
|
|
1008
|
+
// The title is required and becomes a folder name inside the chosen
|
|
1009
|
+
// directory, so an empty or illegal one is refused rather than defaulted.
|
|
1010
|
+
const title = asText(body.title);
|
|
1010
1011
|
const titleIssue = titleProblem(title);
|
|
1011
1012
|
if (titleIssue !== null) throw httpError(400, titleIssue);
|
|
1012
1013
|
const cwd = asText(body.cwd);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-novel-generator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
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",
|