@ninkch/dsh-infinite-canvas 0.17.7 → 0.17.9
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 +94 -59
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -356,6 +356,12 @@ window.__ModuleLoader__.load({
|
|
|
356
356
|
'dataRootOpen': '打开目录',
|
|
357
357
|
'dataRootMigrate': '迁移历史资产',
|
|
358
358
|
'dataRootMigrated': '已迁移 {n} 个资产到数据根目录',
|
|
359
|
+
'collapse': '折叠',
|
|
360
|
+
'foldOpen': '展开',
|
|
361
|
+
'craftReadyCount': '{r}/{n} 就绪',
|
|
362
|
+
'craftDirLabel': '当前项目后期目录',
|
|
363
|
+
'craftDataRootNeed': '请先在上方设置画布数据根目录:Craft 后期文件将存放于 数据根目录\\projects\\<项目>\\craft',
|
|
364
|
+
'craftRootMismatch': 'ArtCraft 自身数据目录与画布数据根目录不一致:请在 ArtCraft 设置里把数据目录改成同一根目录,否则后期文件会落到两处',
|
|
359
365
|
'dataRootImportBtn': '从数据目录导入',
|
|
360
366
|
'dataRootImported': '导入完成:合并 {n} 个项目、补入 {a} 条资产元数据',
|
|
361
367
|
'dataRootImportHint': '换电脑迁移:把整个数据目录拷到新机器 → 设置为数据根目录 → 点"从数据目录导入"即可恢复项目/节点/设定集/资产',
|
|
@@ -687,6 +693,12 @@ window.__ModuleLoader__.load({
|
|
|
687
693
|
'dataRootOpen': 'Open folder',
|
|
688
694
|
'dataRootMigrate': 'Migrate existing assets',
|
|
689
695
|
'dataRootMigrated': 'Migrated {n} assets to the data root',
|
|
696
|
+
'collapse': 'Collapse',
|
|
697
|
+
'foldOpen': 'Expand',
|
|
698
|
+
'craftReadyCount': '{r}/{n} ready',
|
|
699
|
+
'craftDirLabel': 'Project craft dir',
|
|
700
|
+
'craftDataRootNeed': 'Set the canvas data root above first: craft files go to <root>\\projects\\<project>\\craft',
|
|
701
|
+
'craftRootMismatch': "ArtCraft's own data root differs from the canvas data root — point ArtCraft at the same root or craft files will land in two places",
|
|
690
702
|
'dataRootImportBtn': 'Import from data root',
|
|
691
703
|
'dataRootImported': 'Imported: {n} projects merged, {a} asset records added',
|
|
692
704
|
'dataRootImportHint': 'Migration: copy the whole data folder to the new machine, set it as data root, then click "Import from data root" to restore projects/nodes/bible/assets',
|
|
@@ -1092,8 +1104,8 @@ window.__ModuleLoader__.load({
|
|
|
1092
1104
|
try { localStorage.setItem(key, JSON.stringify(value)); } catch { /* 忽略配额错误 */ }
|
|
1093
1105
|
}
|
|
1094
1106
|
const DEFAULT_SETTINGS = {
|
|
1095
|
-
//
|
|
1096
|
-
textLlm: { provider: '', model: ''
|
|
1107
|
+
// 文本模型全部用 Harness 的当前模型与默认参数:画布只选择模型,不单独配置生成参数
|
|
1108
|
+
textLlm: { provider: '', model: '' },
|
|
1097
1109
|
imageApis: [], // [{id, name, baseUrl, apiKey, model, mode, size?, responseFormat?}]
|
|
1098
1110
|
videoApis: [], // [{id, name, url, apiKey, model, protocol?, watermark?, generateAudio?}]
|
|
1099
1111
|
ttsApis: [], // [{id, name, baseUrl, apiKey, model, voice}]
|
|
@@ -1107,7 +1119,7 @@ window.__ModuleLoader__.load({
|
|
|
1107
1119
|
function loadSettings() {
|
|
1108
1120
|
const s = lsGet(LS_SETTINGS, {}) || {};
|
|
1109
1121
|
const out = {
|
|
1110
|
-
textLlm: {
|
|
1122
|
+
textLlm: { provider: (s.textLlm && s.textLlm.provider) || '', model: (s.textLlm && s.textLlm.model) || '' },
|
|
1111
1123
|
imageApis: Array.isArray(s.imageApis) ? s.imageApis : [],
|
|
1112
1124
|
videoApis: Array.isArray(s.videoApis) ? s.videoApis : [],
|
|
1113
1125
|
ttsApis: Array.isArray(s.ttsApis) ? s.ttsApis : [],
|
|
@@ -1598,6 +1610,20 @@ window.__ModuleLoader__.load({
|
|
|
1598
1610
|
}
|
|
1599
1611
|
return { migrated: done, total: targets.length };
|
|
1600
1612
|
}
|
|
1613
|
+
/** 数据根目录就绪后自动把浏览器 IndexedDB 里的存量资产搬到磁盘(替代原"迁移历史资产"按钮,全自动无需手动触发)。 */
|
|
1614
|
+
async function autoMigrateAssetsToRoot() {
|
|
1615
|
+
if (!S.dataRoot) return;
|
|
1616
|
+
try {
|
|
1617
|
+
const all = await idbAll();
|
|
1618
|
+
const pending = all.some((r) => r && r.blob && !r.rel);
|
|
1619
|
+
if (!pending) return;
|
|
1620
|
+
const r = await migrateAssetsToDisk();
|
|
1621
|
+
if (r.migrated) {
|
|
1622
|
+
toast(T('dataRootMigrated').replace('{n}', String(r.migrated)));
|
|
1623
|
+
update((s) => { s.assetsTick++; });
|
|
1624
|
+
}
|
|
1625
|
+
} catch { /* 静默:迁移失败不影响主流程,下次设置数据根目录时再试 */ }
|
|
1626
|
+
}
|
|
1601
1627
|
function useAssetUrl(id) {
|
|
1602
1628
|
const [url, setUrl] = useState(null);
|
|
1603
1629
|
useEffect(() => {
|
|
@@ -2302,7 +2328,9 @@ window.__ModuleLoader__.load({
|
|
|
2302
2328
|
const pid = S.activeId;
|
|
2303
2329
|
const map = craftMapLoad(pid);
|
|
2304
2330
|
if (!opts.force && map[rec.id]) return map[rec.id];
|
|
2305
|
-
|
|
2331
|
+
// Craft 后期数据统一放在**画布数据根目录**的项目目录下:projects/<项目>/<slug 前缀去掉>/craft/…
|
|
2332
|
+
// (ArtCraft 数据根目录 = 画布数据根目录时,即落在 <root>/projects/<项目>/craft/media/)
|
|
2333
|
+
const rel = 'projects/' + craftProjectSlug() + '/craft/media/' + assetFileBase(rec) + extForMime(rec.mime, rec.name);
|
|
2306
2334
|
const blob = rec.blob || await assetBlob(rec.id);
|
|
2307
2335
|
if (!blob) throw new Error('资产内容不可用: ' + rec.id);
|
|
2308
2336
|
await craft.write(rel, blob);
|
|
@@ -5331,12 +5359,12 @@ window.__ModuleLoader__.load({
|
|
|
5331
5359
|
width: dims.w, height: dims.h,
|
|
5332
5360
|
});
|
|
5333
5361
|
try {
|
|
5334
|
-
await craft.writeText(slug + '/craft/timeline.xml', xml);
|
|
5335
|
-
await craft.writeText(slug + '/craft/subs.srt', buildSrt(items));
|
|
5362
|
+
await craft.writeText('projects/' + slug + '/craft/timeline.xml', xml);
|
|
5363
|
+
await craft.writeText('projects/' + slug + '/craft/subs.srt', buildSrt(items));
|
|
5336
5364
|
} catch (e) { return; /* craftFetch 已提示 */ }
|
|
5337
5365
|
setFcDialog({
|
|
5338
|
-
args: JSON.stringify(['--project', slug + '/craft/drama.fcproj', '--import', slug + '/craft/timeline.xml', '--export', slug + '/out/final.mp4'], null, 1),
|
|
5339
|
-
outRel: slug + '/out/final.mp4',
|
|
5366
|
+
args: JSON.stringify(['--project', 'projects/' + slug + '/craft/drama.fcproj', '--import', 'projects/' + slug + '/craft/timeline.xml', '--export', 'projects/' + slug + '/craft/out/final.mp4'], null, 1),
|
|
5367
|
+
outRel: 'projects/' + slug + '/craft/out/final.mp4',
|
|
5340
5368
|
});
|
|
5341
5369
|
};
|
|
5342
5370
|
const submitFc = (args, outRel) => {
|
|
@@ -6131,13 +6159,12 @@ window.__ModuleLoader__.load({
|
|
|
6131
6159
|
// 默认项 = 内置专家 persona + 内置创作方法论 canvas-craft(自动叠加)
|
|
6132
6160
|
const options = [{ value: '', label: T('builtinExpert') }].concat((data.skills || []).map((x) => ({ value: x.name, label: x.name })));
|
|
6133
6161
|
return h('div', { className: 'dshic-field' },
|
|
6134
|
-
h('span', { className: 'dshic-field-label' }, label),
|
|
6162
|
+
h('span', { className: 'dshic-field-label' }, label, InfoTip(T('skillHint'))),
|
|
6135
6163
|
h('select', {
|
|
6136
6164
|
className: 'dshic-select', value: value || '',
|
|
6137
6165
|
onChange: (e) => onChange(e.target.value),
|
|
6138
6166
|
onPointerDown: (e) => e.stopPropagation(),
|
|
6139
|
-
}, options.map((o) => h('option', { key: o.value, value: o.value }, o.label)))
|
|
6140
|
-
h('div', { className: 'dshic-hint' }, T('skillHint')));
|
|
6167
|
+
}, options.map((o) => h('option', { key: o.value, value: o.value }, o.label))));
|
|
6141
6168
|
}
|
|
6142
6169
|
|
|
6143
6170
|
function LlmModelSelect() {
|
|
@@ -6188,7 +6215,6 @@ window.__ModuleLoader__.load({
|
|
|
6188
6215
|
},
|
|
6189
6216
|
onPointerDown: (e) => e.stopPropagation(),
|
|
6190
6217
|
}),
|
|
6191
|
-
h('div', { className: 'dshic-hint' }, T('llmHint')),
|
|
6192
6218
|
);
|
|
6193
6219
|
}
|
|
6194
6220
|
|
|
@@ -6202,6 +6228,13 @@ window.__ModuleLoader__.load({
|
|
|
6202
6228
|
onPointerDown: (e) => e.stopPropagation(),
|
|
6203
6229
|
}));
|
|
6204
6230
|
}
|
|
6231
|
+
/** ⓘ 悬停说明:界面简洁化——长解释一律收进悬停提示(原生 title),不再平铺文字。 */
|
|
6232
|
+
function InfoTip(text) {
|
|
6233
|
+
return h('span', {
|
|
6234
|
+
title: String(text || ''), 'aria-label': String(text || ''),
|
|
6235
|
+
style: { flex: 'none', width: 14, height: 14, lineHeight: '13px', textAlign: 'center', fontSize: 10, borderRadius: '50%', border: '1px solid var(--dsw-alias-border-secondary, #777)', color: 'var(--dsw-alias-label-secondary, #999)', cursor: 'help', userSelect: 'none', opacity: 0.85 },
|
|
6236
|
+
}, 'i');
|
|
6237
|
+
}
|
|
6205
6238
|
function ApiListEditor({ kind }) {
|
|
6206
6239
|
const [s, setS] = useState(loadSettings);
|
|
6207
6240
|
const [openId, setOpenId] = useState(null);
|
|
@@ -6351,10 +6384,19 @@ window.__ModuleLoader__.load({
|
|
|
6351
6384
|
/** T2:设置面板 Craft 后期卡片(连接状态 / 工具灯 / 数据目录)。 */
|
|
6352
6385
|
function CraftCard() {
|
|
6353
6386
|
const [, force] = useState(0);
|
|
6387
|
+
const [open, setOpen] = useState(false); // 默认折叠:界面简洁,摘要常显
|
|
6354
6388
|
useEffect(() => { probeCraft().then(() => force((x) => x + 1)); }, []);
|
|
6355
6389
|
const cs = S.craftStatus;
|
|
6356
6390
|
const data = cs && cs.data;
|
|
6357
6391
|
const slug = craftProjectSlug();
|
|
6392
|
+
// Craft 后期目录 = **画布数据根目录** + 项目目录 + \craft(不再有 ArtCraft 独立数据目录的 second 口径)
|
|
6393
|
+
const craftDir = S.dataRoot ? (S.dataRoot.replace(/[\\/]+$/, '') + '\\projects\\' + slug + '\\craft') : '';
|
|
6394
|
+
// ArtCraft 自身的数据目录若与画布数据根目录不一致 → 后期文件会落到两处,必须提醒
|
|
6395
|
+
const artRoot = data && data.dataRoot ? data.dataRoot.path : '';
|
|
6396
|
+
const rootMismatch = !!(S.dataRoot && artRoot && artRoot.replace(/[\\/]+$/, '') !== S.dataRoot.replace(/[\\/]+$/, ''));
|
|
6397
|
+
// Craft 家族全量动态渲染:ArtCraft /status 返回几款 bins 就渲染几款(当前 12 款),不再写死
|
|
6398
|
+
const binKeys = (data && data.bins ? Object.keys(data.bins) : []).sort();
|
|
6399
|
+
const readyCount = binKeys.filter((k) => data.bins[k] && data.bins[k].found).length;
|
|
6358
6400
|
const binRow = (key) => {
|
|
6359
6401
|
const info = data && data.bins ? data.bins[key] : null;
|
|
6360
6402
|
const ok = !!(info && info.found);
|
|
@@ -6366,18 +6408,22 @@ window.__ModuleLoader__.load({
|
|
|
6366
6408
|
);
|
|
6367
6409
|
};
|
|
6368
6410
|
return h('div', { className: 'dshic-card' },
|
|
6369
|
-
h('div', {
|
|
6411
|
+
h('div', {
|
|
6412
|
+
className: 'dshic-row', style: { cursor: 'pointer' },
|
|
6413
|
+
onPointerDown: (e) => e.stopPropagation(), onClick: () => setOpen((x) => !x),
|
|
6414
|
+
title: open ? T('collapse') : T('foldOpen'),
|
|
6415
|
+
},
|
|
6370
6416
|
Ic('film', 12),
|
|
6371
6417
|
h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('craftCard')),
|
|
6372
|
-
h('
|
|
6418
|
+
data ? h('span', { className: 'dshic-hint', style: { flex: 'none' } }, T('craftReadyCount').replace('{r}', String(readyCount)).replace('{n}', String(binKeys.length))) : null,
|
|
6419
|
+
h('button', { type: 'button', className: 'dshic-mini is-ghost', onPointerDown: (e) => e.stopPropagation(), onClick: (e) => { e.stopPropagation(); probeCraft().then(() => force((x) => x + 1)); } }, '↻'),
|
|
6420
|
+
h('span', { style: { flex: 'none', fontSize: 10, transition: 'transform .15s', transform: open ? 'rotate(90deg)' : 'rotate(0deg)' } }, '▶'),
|
|
6373
6421
|
),
|
|
6374
|
-
|
|
6375
|
-
? h('div', { className: 'dshic-hint' }, T('
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
data ? binRow('effectcraft') : null,
|
|
6380
|
-
data ? h('div', { className: 'dshic-hint' }, T('craftProjectDir') + ':' + slug + '/') : null,
|
|
6422
|
+
open ? [
|
|
6423
|
+
craftDir ? h('div', { className: 'dshic-hint' }, T('craftDirLabel') + ':' + craftDir) : h('div', { className: 'dshic-err' }, T('craftDataRootNeed')),
|
|
6424
|
+
rootMismatch ? h('div', { className: 'dshic-err' }, T('craftRootMismatch')) : null,
|
|
6425
|
+
...(data ? binKeys.map((k) => binRow(k)) : []),
|
|
6426
|
+
] : null,
|
|
6381
6427
|
);
|
|
6382
6428
|
}
|
|
6383
6429
|
|
|
@@ -6406,7 +6452,7 @@ window.__ModuleLoader__.load({
|
|
|
6406
6452
|
setRunning(true); setErr(null); setProgress('…');
|
|
6407
6453
|
try {
|
|
6408
6454
|
const mediaRel = await ensureAssetOnDisk(rec);
|
|
6409
|
-
const outRel = craftProjectSlug() + '/out/graded/' + rec.id + '-graded' + extForMime(rec.mime, rec.name);
|
|
6455
|
+
const outRel = 'projects/' + craftProjectSlug() + '/craft/out/graded/' + rec.id + '-graded' + extForMime(rec.mime, rec.name);
|
|
6410
6456
|
const job = await craft.jobStart({
|
|
6411
6457
|
bin: 'photocraft',
|
|
6412
6458
|
args: ['run', mediaRel, '--cmd', cmd, '--params', JSON.stringify(paramsObj), '--out', outRel],
|
|
@@ -6514,7 +6560,6 @@ window.__ModuleLoader__.load({
|
|
|
6514
6560
|
const [val, setVal] = useState('');
|
|
6515
6561
|
const [busy, setBusy] = useState(false);
|
|
6516
6562
|
const [picking, setPicking] = useState(false);
|
|
6517
|
-
const [mig, setMig] = useState(null); // null | {done,total} | 'done'
|
|
6518
6563
|
useEffect(() => { if (S.dataRoot) setVal(S.dataRoot); }, [S.dataRoot]);
|
|
6519
6564
|
const save = async () => {
|
|
6520
6565
|
if (busy) return;
|
|
@@ -6524,7 +6569,7 @@ window.__ModuleLoader__.load({
|
|
|
6524
6569
|
await refreshDataRoot();
|
|
6525
6570
|
toast(T('dataRootSaved') + (S.dataRoot ? ':' + S.dataRoot : ''));
|
|
6526
6571
|
assetIndexSynced = false; // 换了目录:索引要往新目录重建
|
|
6527
|
-
syncAssetIndexToHost();
|
|
6572
|
+
autoMigrateAssetsToRoot().then(() => syncAssetIndexToHost()); // 先搬存量资产,再对齐索引
|
|
6528
6573
|
} catch (e) { toast('设置失败:' + ((e && e.message) || e)); }
|
|
6529
6574
|
setBusy(false);
|
|
6530
6575
|
};
|
|
@@ -6534,7 +6579,7 @@ window.__ModuleLoader__.load({
|
|
|
6534
6579
|
setVal(S.dataRoot || root);
|
|
6535
6580
|
toast(T('dataRootSaved') + ':' + S.dataRoot);
|
|
6536
6581
|
assetIndexSynced = false; // 换了目录:索引要往新目录重建
|
|
6537
|
-
syncAssetIndexToHost();
|
|
6582
|
+
autoMigrateAssetsToRoot().then(() => syncAssetIndexToHost());
|
|
6538
6583
|
};
|
|
6539
6584
|
const browse = async () => {
|
|
6540
6585
|
if (busy || picking) return;
|
|
@@ -6576,18 +6621,12 @@ window.__ModuleLoader__.load({
|
|
|
6576
6621
|
} catch (e) { toast('导入失败:' + ((e && e.message) || e)); }
|
|
6577
6622
|
setBusy(false);
|
|
6578
6623
|
};
|
|
6579
|
-
const migrate = async () => {
|
|
6580
|
-
if (busy || picking || mig) return;
|
|
6581
|
-
setBusy(true); setMig({ done: 0, total: 0 });
|
|
6582
|
-
try {
|
|
6583
|
-
const r = await migrateAssetsToDisk((done, total) => setMig({ done, total }));
|
|
6584
|
-
setMig('done');
|
|
6585
|
-
toast(T('dataRootMigrated').replace('{n}', String(r.migrated)));
|
|
6586
|
-
} catch (e) { setMig(null); toast('迁移失败:' + ((e && e.message) || e)); }
|
|
6587
|
-
setBusy(false);
|
|
6588
|
-
};
|
|
6589
6624
|
return h('div', { key: 'dataroot', className: 'dshic-card' },
|
|
6590
|
-
h('div', { className: 'dshic-row' },
|
|
6625
|
+
h('div', { className: 'dshic-row' },
|
|
6626
|
+
Ic('image', 12),
|
|
6627
|
+
h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('dataRootLabel')),
|
|
6628
|
+
InfoTip(T('dataRootHint')),
|
|
6629
|
+
),
|
|
6591
6630
|
S.dataRootSupported === false
|
|
6592
6631
|
? h('div', { className: 'dshic-hint' }, T('dataRootUnsupported'))
|
|
6593
6632
|
: [
|
|
@@ -6600,17 +6639,12 @@ window.__ModuleLoader__.load({
|
|
|
6600
6639
|
h('button', { type: 'button', className: 'dshic-mini', disabled: busy || picking, onPointerDown: (e) => e.stopPropagation(), onClick: save }, T('dataRootSave')),
|
|
6601
6640
|
),
|
|
6602
6641
|
picking ? h('div', { className: 'dshic-hint', key: 'picking' }, T('dataRootPicking')) : null,
|
|
6603
|
-
h('div', { className: 'dshic-hint', key: 'hint' }, T('dataRootHint')),
|
|
6604
6642
|
h('div', { className: 'dshic-row', key: 'row2' },
|
|
6605
6643
|
S.dataRoot ? h('button', { type: 'button', className: 'dshic-mini', onPointerDown: (e) => e.stopPropagation(), onClick: openDir }, T('dataRootOpen')) : null,
|
|
6606
|
-
S.dataRoot ? h('button', { type: 'button', className: 'dshic-mini', disabled: busy || picking || !!mig, onPointerDown: (e) => e.stopPropagation(), onClick: migrate }, mig === 'done' ? T('dataRootMigratedDone') : T('dataRootMigrate')) : null,
|
|
6607
|
-
(mig && mig !== 'done') ? h('span', { style: { fontSize: 11, opacity: 0.85 } }, T('dataRootMigrating') + ' ' + mig.done + '/' + mig.total) : null,
|
|
6608
|
-
),
|
|
6609
|
-
h('div', { className: 'dshic-row', key: 'row3' },
|
|
6610
6644
|
S.dataRoot ? h('button', { type: 'button', className: 'dshic-mini is-ghost', disabled: busy || picking, onPointerDown: (e) => e.stopPropagation(), onClick: importFromRoot }, Ic('folder', 11), T('dataRootImportBtn')) : null,
|
|
6645
|
+
S.dataRoot ? InfoTip(T('dataRootImportHint')) : null,
|
|
6611
6646
|
h('div', { className: 'dshic-flex' }),
|
|
6612
6647
|
),
|
|
6613
|
-
S.dataRoot ? h('div', { className: 'dshic-hint', key: 'importHint' }, T('dataRootImportHint')) : null,
|
|
6614
6648
|
],
|
|
6615
6649
|
);
|
|
6616
6650
|
}
|
|
@@ -6626,8 +6660,6 @@ window.__ModuleLoader__.load({
|
|
|
6626
6660
|
};
|
|
6627
6661
|
const field = (label, value, onChange, placeholder, password) => h(Field, { label, value, onChange, placeholder, password });
|
|
6628
6662
|
return [
|
|
6629
|
-
h(CraftCard, { key: 'craft' }),
|
|
6630
|
-
h(DataRootCard, { key: 'dataroot' }),
|
|
6631
6663
|
h('div', { key: 'lang', className: 'dshic-card' },
|
|
6632
6664
|
h('div', { className: 'dshic-row' }, Ic('text', 12), h('strong', { style: { fontSize: 12 } }, T('langLabel'))),
|
|
6633
6665
|
h('select', {
|
|
@@ -6643,24 +6675,27 @@ window.__ModuleLoader__.load({
|
|
|
6643
6675
|
h('option', { value: 'zh' }, T('langZh')),
|
|
6644
6676
|
h('option', { value: 'en' }, T('langEn'))),
|
|
6645
6677
|
),
|
|
6646
|
-
h(
|
|
6647
|
-
|
|
6648
|
-
|
|
6678
|
+
h(DataRootCard, { key: 'dataroot' }),
|
|
6679
|
+
h(CraftCard, { key: 'craft' }),
|
|
6680
|
+
// 专家与技能卡:独立于模型选择
|
|
6681
|
+
h('div', { key: 'skills', className: 'dshic-card' },
|
|
6649
6682
|
h('div', { className: 'dshic-row' },
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
}),
|
|
6654
|
-
h(Field, {
|
|
6655
|
-
label: T('llmTemperature'), value: s.textLlm.temperature || '', placeholder: T('llmParamAuto'),
|
|
6656
|
-
onChange: (v) => apply((d) => { d.textLlm.temperature = v; }),
|
|
6657
|
-
}),
|
|
6683
|
+
Ic('spark', 12),
|
|
6684
|
+
h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('skillEnhance')),
|
|
6685
|
+
InfoTip(T('skillHint')),
|
|
6658
6686
|
),
|
|
6659
|
-
h('div', { className: 'dshic-hint' }, T('llmParamHint')),
|
|
6660
|
-
h('div', { className: 'dshic-hint' }, T('skillEnhance')),
|
|
6661
6687
|
h(SkillSelect, { label: T('skillScript'), value: s.skillScript, onChange: (v) => apply((d) => { d.skillScript = v; }) }),
|
|
6662
6688
|
h(SkillSelect, { label: T('skillStoryboard'), value: s.skillStoryboard, onChange: (v) => apply((d) => { d.skillStoryboard = v; }) }),
|
|
6663
6689
|
),
|
|
6690
|
+
// 文本模型卡:只选模型,参数全用 Harness 默认;紧挨图片/视频/TTS 模型卡片
|
|
6691
|
+
h('div', { key: 'llm', className: 'dshic-card' },
|
|
6692
|
+
h('div', { className: 'dshic-row' },
|
|
6693
|
+
Ic('spark', 12),
|
|
6694
|
+
h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('llmLabel')),
|
|
6695
|
+
InfoTip(T('llmHint')),
|
|
6696
|
+
),
|
|
6697
|
+
h(LlmModelSelect),
|
|
6698
|
+
),
|
|
6664
6699
|
h(ApiListEditor, { key: 'imglist', kind: 'image' }),
|
|
6665
6700
|
h(ApiListEditor, { key: 'vidlist', kind: 'video' }),
|
|
6666
6701
|
h(ApiListEditor, { key: 'ttslist', kind: 'tts' }),
|
|
@@ -7214,8 +7249,8 @@ window.__ModuleLoader__.load({
|
|
|
7214
7249
|
probeCraft();
|
|
7215
7250
|
// 检查更新(Host RPC;Host 旧版未带此方法时静默)
|
|
7216
7251
|
checkUpdate(true);
|
|
7217
|
-
// 数据根目录(Host 旧版静默降级为 IndexedDB
|
|
7218
|
-
refreshDataRoot().then(() => syncAssetIndexToHost()).catch(() => { /* 静默 */ });
|
|
7252
|
+
// 数据根目录(Host 旧版静默降级为 IndexedDB 模式);就绪后自动搬存量资产到磁盘,再对齐索引
|
|
7253
|
+
refreshDataRoot().then(() => autoMigrateAssetsToRoot()).then(() => syncAssetIndexToHost()).catch(() => { /* 静默 */ });
|
|
7219
7254
|
// 对话 ↔ 画布同步(启动一次 + 3s 轮询;旧 Host 自动停轮询)
|
|
7220
7255
|
hostSyncTick().then(() => pushAllProjectsToHost());
|
|
7221
7256
|
const hostSyncTimer = setInterval(() => hostSyncTick(), 3000);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ninkch/dsh-infinite-canvas",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.9",
|
|
4
4
|
"description": "Node-based short-drama studio for DeepSeek Harness: script → storyboard → assets → shots → voiced, subtitled final cut on an infinite canvas.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|