@ninkch/dsh-infinite-canvas 0.17.7 → 0.17.8

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.
Files changed (2) hide show
  1. package/client.js +76 -40
  2. 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
- // 生成参数一律"留空即不发送",由 Harness 适配器/模型用已配置的默认值(不在代码里写死)
1096
- textLlm: { provider: '', model: '', maxTokens: '', temperature: '' },
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: { ...DEFAULT_SETTINGS.textLlm, ...(s.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 : [],
@@ -2302,7 +2314,9 @@ window.__ModuleLoader__.load({
2302
2314
  const pid = S.activeId;
2303
2315
  const map = craftMapLoad(pid);
2304
2316
  if (!opts.force && map[rec.id]) return map[rec.id];
2305
- const rel = craftProjectSlug() + '/media/' + assetFileBase(rec) + extForMime(rec.mime, rec.name);
2317
+ // Craft 后期数据统一放在**画布数据根目录**的项目目录下:projects/<项目>/<slug 前缀去掉>/craft/…
2318
+ // (ArtCraft 数据根目录 = 画布数据根目录时,即落在 <root>/projects/<项目>/craft/media/)
2319
+ const rel = 'projects/' + craftProjectSlug() + '/craft/media/' + assetFileBase(rec) + extForMime(rec.mime, rec.name);
2306
2320
  const blob = rec.blob || await assetBlob(rec.id);
2307
2321
  if (!blob) throw new Error('资产内容不可用: ' + rec.id);
2308
2322
  await craft.write(rel, blob);
@@ -5331,12 +5345,12 @@ window.__ModuleLoader__.load({
5331
5345
  width: dims.w, height: dims.h,
5332
5346
  });
5333
5347
  try {
5334
- await craft.writeText(slug + '/craft/timeline.xml', xml);
5335
- await craft.writeText(slug + '/craft/subs.srt', buildSrt(items));
5348
+ await craft.writeText('projects/' + slug + '/craft/timeline.xml', xml);
5349
+ await craft.writeText('projects/' + slug + '/craft/subs.srt', buildSrt(items));
5336
5350
  } catch (e) { return; /* craftFetch 已提示 */ }
5337
5351
  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',
5352
+ args: JSON.stringify(['--project', 'projects/' + slug + '/craft/drama.fcproj', '--import', 'projects/' + slug + '/craft/timeline.xml', '--export', 'projects/' + slug + '/craft/out/final.mp4'], null, 1),
5353
+ outRel: 'projects/' + slug + '/craft/out/final.mp4',
5340
5354
  });
5341
5355
  };
5342
5356
  const submitFc = (args, outRel) => {
@@ -6131,13 +6145,12 @@ window.__ModuleLoader__.load({
6131
6145
  // 默认项 = 内置专家 persona + 内置创作方法论 canvas-craft(自动叠加)
6132
6146
  const options = [{ value: '', label: T('builtinExpert') }].concat((data.skills || []).map((x) => ({ value: x.name, label: x.name })));
6133
6147
  return h('div', { className: 'dshic-field' },
6134
- h('span', { className: 'dshic-field-label' }, label),
6148
+ h('span', { className: 'dshic-field-label' }, label, InfoTip(T('skillHint'))),
6135
6149
  h('select', {
6136
6150
  className: 'dshic-select', value: value || '',
6137
6151
  onChange: (e) => onChange(e.target.value),
6138
6152
  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')));
6153
+ }, options.map((o) => h('option', { key: o.value, value: o.value }, o.label))));
6141
6154
  }
6142
6155
 
6143
6156
  function LlmModelSelect() {
@@ -6188,7 +6201,6 @@ window.__ModuleLoader__.load({
6188
6201
  },
6189
6202
  onPointerDown: (e) => e.stopPropagation(),
6190
6203
  }),
6191
- h('div', { className: 'dshic-hint' }, T('llmHint')),
6192
6204
  );
6193
6205
  }
6194
6206
 
@@ -6202,6 +6214,13 @@ window.__ModuleLoader__.load({
6202
6214
  onPointerDown: (e) => e.stopPropagation(),
6203
6215
  }));
6204
6216
  }
6217
+ /** ⓘ 悬停说明:界面简洁化——长解释一律收进悬停提示(原生 title),不再平铺文字。 */
6218
+ function InfoTip(text) {
6219
+ return h('span', {
6220
+ title: String(text || ''), 'aria-label': String(text || ''),
6221
+ 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 },
6222
+ }, 'i');
6223
+ }
6205
6224
  function ApiListEditor({ kind }) {
6206
6225
  const [s, setS] = useState(loadSettings);
6207
6226
  const [openId, setOpenId] = useState(null);
@@ -6351,10 +6370,19 @@ window.__ModuleLoader__.load({
6351
6370
  /** T2:设置面板 Craft 后期卡片(连接状态 / 工具灯 / 数据目录)。 */
6352
6371
  function CraftCard() {
6353
6372
  const [, force] = useState(0);
6373
+ const [open, setOpen] = useState(false); // 默认折叠:界面简洁,摘要常显
6354
6374
  useEffect(() => { probeCraft().then(() => force((x) => x + 1)); }, []);
6355
6375
  const cs = S.craftStatus;
6356
6376
  const data = cs && cs.data;
6357
6377
  const slug = craftProjectSlug();
6378
+ // Craft 后期目录 = **画布数据根目录** + 项目目录 + \craft(不再有 ArtCraft 独立数据目录的 second 口径)
6379
+ const craftDir = S.dataRoot ? (S.dataRoot.replace(/[\\/]+$/, '') + '\\projects\\' + slug + '\\craft') : '';
6380
+ // ArtCraft 自身的数据目录若与画布数据根目录不一致 → 后期文件会落到两处,必须提醒
6381
+ const artRoot = data && data.dataRoot ? data.dataRoot.path : '';
6382
+ const rootMismatch = !!(S.dataRoot && artRoot && artRoot.replace(/[\\/]+$/, '') !== S.dataRoot.replace(/[\\/]+$/, ''));
6383
+ // Craft 家族全量动态渲染:ArtCraft /status 返回几款 bins 就渲染几款(当前 12 款),不再写死
6384
+ const binKeys = (data && data.bins ? Object.keys(data.bins) : []).sort();
6385
+ const readyCount = binKeys.filter((k) => data.bins[k] && data.bins[k].found).length;
6358
6386
  const binRow = (key) => {
6359
6387
  const info = data && data.bins ? data.bins[key] : null;
6360
6388
  const ok = !!(info && info.found);
@@ -6366,18 +6394,22 @@ window.__ModuleLoader__.load({
6366
6394
  );
6367
6395
  };
6368
6396
  return h('div', { className: 'dshic-card' },
6369
- h('div', { className: 'dshic-row' },
6397
+ h('div', {
6398
+ className: 'dshic-row', style: { cursor: 'pointer' },
6399
+ onPointerDown: (e) => e.stopPropagation(), onClick: () => setOpen((x) => !x),
6400
+ title: open ? T('collapse') : T('foldOpen'),
6401
+ },
6370
6402
  Ic('film', 12),
6371
6403
  h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('craftCard')),
6372
- h('button', { type: 'button', className: 'dshic-mini is-ghost', onPointerDown: (e) => e.stopPropagation(), onClick: () => { probeCraft().then(() => force((x) => x + 1)); } }, '↻'),
6404
+ data ? h('span', { className: 'dshic-hint', style: { flex: 'none' } }, T('craftReadyCount').replace('{r}', String(readyCount)).replace('{n}', String(binKeys.length))) : null,
6405
+ h('button', { type: 'button', className: 'dshic-mini is-ghost', onPointerDown: (e) => e.stopPropagation(), onClick: (e) => { e.stopPropagation(); probeCraft().then(() => force((x) => x + 1)); } }, '↻'),
6406
+ h('span', { style: { flex: 'none', fontSize: 10, transition: 'transform .15s', transform: open ? 'rotate(90deg)' : 'rotate(0deg)' } }, '▶'),
6373
6407
  ),
6374
- data
6375
- ? h('div', { className: 'dshic-hint' }, T('craftDataRoot') + ':' + ((data.dataRoot && data.dataRoot.path) || '—'))
6376
- : h('div', { className: 'dshic-err' }, T('craftUnreachable')),
6377
- data ? binRow('photocraft') : null,
6378
- data ? binRow('filmcraft') : null,
6379
- data ? binRow('effectcraft') : null,
6380
- data ? h('div', { className: 'dshic-hint' }, T('craftProjectDir') + ':' + slug + '/') : null,
6408
+ open ? [
6409
+ craftDir ? h('div', { className: 'dshic-hint' }, T('craftDirLabel') + ':' + craftDir) : h('div', { className: 'dshic-err' }, T('craftDataRootNeed')),
6410
+ rootMismatch ? h('div', { className: 'dshic-err' }, T('craftRootMismatch')) : null,
6411
+ ...(data ? binKeys.map((k) => binRow(k)) : []),
6412
+ ] : null,
6381
6413
  );
6382
6414
  }
6383
6415
 
@@ -6406,7 +6438,7 @@ window.__ModuleLoader__.load({
6406
6438
  setRunning(true); setErr(null); setProgress('…');
6407
6439
  try {
6408
6440
  const mediaRel = await ensureAssetOnDisk(rec);
6409
- const outRel = craftProjectSlug() + '/out/graded/' + rec.id + '-graded' + extForMime(rec.mime, rec.name);
6441
+ const outRel = 'projects/' + craftProjectSlug() + '/craft/out/graded/' + rec.id + '-graded' + extForMime(rec.mime, rec.name);
6410
6442
  const job = await craft.jobStart({
6411
6443
  bin: 'photocraft',
6412
6444
  args: ['run', mediaRel, '--cmd', cmd, '--params', JSON.stringify(paramsObj), '--out', outRel],
@@ -6587,7 +6619,11 @@ window.__ModuleLoader__.load({
6587
6619
  setBusy(false);
6588
6620
  };
6589
6621
  return h('div', { key: 'dataroot', className: 'dshic-card' },
6590
- h('div', { className: 'dshic-row' }, Ic('image', 12), h('strong', { style: { fontSize: 12 } }, T('dataRootLabel'))),
6622
+ h('div', { className: 'dshic-row' },
6623
+ Ic('image', 12),
6624
+ h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('dataRootLabel')),
6625
+ InfoTip(T('dataRootHint')),
6626
+ ),
6591
6627
  S.dataRootSupported === false
6592
6628
  ? h('div', { className: 'dshic-hint' }, T('dataRootUnsupported'))
6593
6629
  : [
@@ -6600,7 +6636,6 @@ window.__ModuleLoader__.load({
6600
6636
  h('button', { type: 'button', className: 'dshic-mini', disabled: busy || picking, onPointerDown: (e) => e.stopPropagation(), onClick: save }, T('dataRootSave')),
6601
6637
  ),
6602
6638
  picking ? h('div', { className: 'dshic-hint', key: 'picking' }, T('dataRootPicking')) : null,
6603
- h('div', { className: 'dshic-hint', key: 'hint' }, T('dataRootHint')),
6604
6639
  h('div', { className: 'dshic-row', key: 'row2' },
6605
6640
  S.dataRoot ? h('button', { type: 'button', className: 'dshic-mini', onPointerDown: (e) => e.stopPropagation(), onClick: openDir }, T('dataRootOpen')) : null,
6606
6641
  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,
@@ -6608,9 +6643,9 @@ window.__ModuleLoader__.load({
6608
6643
  ),
6609
6644
  h('div', { className: 'dshic-row', key: 'row3' },
6610
6645
  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,
6646
+ S.dataRoot ? InfoTip(T('dataRootImportHint')) : null,
6611
6647
  h('div', { className: 'dshic-flex' }),
6612
6648
  ),
6613
- S.dataRoot ? h('div', { className: 'dshic-hint', key: 'importHint' }, T('dataRootImportHint')) : null,
6614
6649
  ],
6615
6650
  );
6616
6651
  }
@@ -6626,8 +6661,6 @@ window.__ModuleLoader__.load({
6626
6661
  };
6627
6662
  const field = (label, value, onChange, placeholder, password) => h(Field, { label, value, onChange, placeholder, password });
6628
6663
  return [
6629
- h(CraftCard, { key: 'craft' }),
6630
- h(DataRootCard, { key: 'dataroot' }),
6631
6664
  h('div', { key: 'lang', className: 'dshic-card' },
6632
6665
  h('div', { className: 'dshic-row' }, Ic('text', 12), h('strong', { style: { fontSize: 12 } }, T('langLabel'))),
6633
6666
  h('select', {
@@ -6643,24 +6676,27 @@ window.__ModuleLoader__.load({
6643
6676
  h('option', { value: 'zh' }, T('langZh')),
6644
6677
  h('option', { value: 'en' }, T('langEn'))),
6645
6678
  ),
6646
- h('div', { key: 'llm', className: 'dshic-card' },
6647
- h('div', { className: 'dshic-row' }, Ic('spark', 12), h('strong', { style: { fontSize: 12 } }, T('llmLabel'))),
6648
- h(LlmModelSelect),
6679
+ h(DataRootCard, { key: 'dataroot' }),
6680
+ h(CraftCard, { key: 'craft' }),
6681
+ // 专家与技能卡:独立于模型选择
6682
+ h('div', { key: 'skills', className: 'dshic-card' },
6649
6683
  h('div', { className: 'dshic-row' },
6650
- h(Field, {
6651
- label: T('llmMaxTokens'), value: s.textLlm.maxTokens || '', placeholder: T('llmParamAuto'),
6652
- onChange: (v) => apply((d) => { d.textLlm.maxTokens = v; }),
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
- }),
6684
+ Ic('spark', 12),
6685
+ h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('skillEnhance')),
6686
+ InfoTip(T('skillHint')),
6658
6687
  ),
6659
- h('div', { className: 'dshic-hint' }, T('llmParamHint')),
6660
- h('div', { className: 'dshic-hint' }, T('skillEnhance')),
6661
6688
  h(SkillSelect, { label: T('skillScript'), value: s.skillScript, onChange: (v) => apply((d) => { d.skillScript = v; }) }),
6662
6689
  h(SkillSelect, { label: T('skillStoryboard'), value: s.skillStoryboard, onChange: (v) => apply((d) => { d.skillStoryboard = v; }) }),
6663
6690
  ),
6691
+ // 文本模型卡:只选模型,参数全用 Harness 默认;紧挨图片/视频/TTS 模型卡片
6692
+ h('div', { key: 'llm', className: 'dshic-card' },
6693
+ h('div', { className: 'dshic-row' },
6694
+ Ic('spark', 12),
6695
+ h('strong', { style: { fontSize: 12, flex: 1, minWidth: 0 } }, T('llmLabel')),
6696
+ InfoTip(T('llmHint')),
6697
+ ),
6698
+ h(LlmModelSelect),
6699
+ ),
6664
6700
  h(ApiListEditor, { key: 'imglist', kind: 'image' }),
6665
6701
  h(ApiListEditor, { key: 'vidlist', kind: 'video' }),
6666
6702
  h(ApiListEditor, { key: 'ttslist', kind: 'tts' }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ninkch/dsh-infinite-canvas",
3
- "version": "0.17.7",
3
+ "version": "0.17.8",
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",