@mokuyoaxis/dsh-iris 0.2.1 → 0.2.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/.dsh/skills/iris-compose-media/SKILL.md +23 -73
- package/.dsh/skills/iris-compose-media/agents/openai.yaml +1 -1
- package/.dsh/skills/iris-compose-media/references/task-v2-recovery.md +23 -22
- package/.dsh/skills/iris-compose-media/references/workflows.md +25 -30
- package/.dsh/skills/iris-use/SKILL.md +41 -0
- package/.dsh/skills/iris-use/agents/openai.yaml +4 -0
- package/.dsh/skills/iris-use/references/media-contract.md +73 -0
- package/.dsh/skills/iris-verify-ui/SKILL.md +9 -7
- package/.dsh/skills/iris-verify-ui/agents/openai.yaml +1 -1
- package/.dsh/skills/iris-verify-ui/references/verdict-and-degradation.md +3 -0
- package/CHANGELOG.md +48 -2
- package/README.en.md +47 -40
- package/README.md +45 -39
- package/bin/dsh-iris.js +27 -6
- package/docs/AGENT_QUICKSTART.md +9 -9
- package/docs/ARCHITECTURE.md +11 -3
- package/docs/ARTIFACT_LIBRARY.md +1 -1
- package/docs/CLI_MANAGEMENT.md +5 -3
- package/docs/COMPOSITE_VISION.md +1 -1
- package/docs/CORE_RUNTIME_CONTRACT.md +12 -2
- package/docs/DSH_CORE_MIGRATION.md +7 -3
- package/docs/FAULT_INJECTION.md +11 -1
- package/docs/HEADLESS_CLI.md +10 -4
- package/docs/HOST_ADAPTER_CONTRACT.md +1 -1
- package/docs/HOST_DOCTOR.md +3 -3
- package/docs/MODEL_PORT_CONTRACT.md +9 -3
- package/docs/MUSIC.md +77 -0
- package/docs/OCR_MODEL.md +1 -1
- package/docs/PROMPT_OPTIMIZER.md +74 -6
- package/docs/PROVIDER_ADAPTER_CONTRACT.md +12 -2
- package/docs/PROVIDER_HEALTH.md +1 -1
- package/docs/ROADMAP.md +15 -18
- package/docs/SECURITY.md +4 -3
- package/docs/SYNC_DELIVERY_RECOVERY.md +39 -0
- package/docs/TASK_SEMANTICS.md +5 -5
- package/docs/VISION_CLI.md +1 -1
- package/docs/VISION_MODEL.md +1 -1
- package/docs/WORKBENCH_ARTIFACTS.md +1 -1
- package/docs/releases/0.2.2.md +31 -0
- package/docs/releases/0.2.3.md +54 -0
- package/lib/actions.js +52 -19
- package/lib/adapters.js +89 -24
- package/lib/api.js +14 -5
- package/lib/bundled-skills.js +1 -1
- package/lib/capability.js +25 -16
- package/lib/client.js +374 -43
- package/lib/command-service.js +12 -3
- package/lib/config.js +39 -6
- package/lib/core-artifact-store.js +44 -6
- package/lib/core-delivery-cache.js +145 -0
- package/lib/core-lease-recovery.js +64 -92
- package/lib/core-maintenance.js +12 -1
- package/lib/core-runtime.js +45 -47
- package/lib/core-tasks.js +19 -5
- package/lib/core-user-projection.js +2 -2
- package/lib/core-writer-lease.js +134 -0
- package/lib/dsh-core-adapter.js +14 -4
- package/lib/dsh-text-model-adapter.js +15 -2
- package/lib/generation-input.js +10 -0
- package/lib/host-runtime.js +4 -2
- package/lib/index.js +23 -4
- package/lib/models.js +23 -38
- package/lib/music-generation.js +21 -0
- package/lib/music-options.js +18 -0
- package/lib/music-transport.js +46 -0
- package/lib/prompt-optimizer-config.js +111 -30
- package/lib/prompt-optimizer-core.js +183 -12
- package/lib/prompt-optimizer.js +20 -14
- package/lib/provider-adapter.js +1 -0
- package/lib/provider-adapters.js +26 -2
- package/lib/provider-catalog.js +18 -7
- package/lib/provider-config-service.js +16 -5
- package/lib/provider-protocol.js +73 -0
- package/lib/provider-task-runner.js +86 -9
- package/package.json +4 -2
- package/user_guide.md +52 -24
package/lib/client.js
CHANGED
|
@@ -21,7 +21,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
21
21
|
var exports = module.exports;
|
|
22
22
|
|
|
23
23
|
var React = require('react');
|
|
24
|
-
var IRIS_CLIENT_VERSION = '0.2.
|
|
24
|
+
var IRIS_CLIENT_VERSION = '0.2.3';
|
|
25
25
|
var HOST_CLIENT_PROTOCOL_VERSION = 0;
|
|
26
26
|
var reportedSeats = [];
|
|
27
27
|
|
|
@@ -299,9 +299,31 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
299
299
|
'.iris-po-trigger:hover { transform: translateY(-2px) scale(1.10); filter: drop-shadow(0 5px 10px rgba(112,137,255,.42)); }',
|
|
300
300
|
'.iris-po-trigger:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary, #7aa2f7); outline-offset: 2px; }',
|
|
301
301
|
'.iris-po-backdrop { position: fixed; inset: 0; z-index: 10019; background: rgba(8,10,18,.30); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); touch-action: none; animation: iris-po-fade .16s ease-out; }',
|
|
302
|
-
'.iris-po-panel
|
|
302
|
+
'.iris-po-panel:where(dialog) { left: auto; top: auto; margin: 0; max-width: none; }',
|
|
303
|
+
'dialog.iris-po-panel::backdrop { background: rgba(8,10,18,.30); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); }',
|
|
304
|
+
'.iris-po-panel { position: fixed; z-index: 10020; right: max(14px, env(safe-area-inset-right)); bottom: max(78px, calc(env(safe-area-inset-bottom) + 68px)); width: min(560px, calc(100vw - 28px)); max-height: min(780px, calc(100dvh - 104px)); overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; box-sizing: border-box; padding: 18px; display: grid; gap: 14px; background-color: rgba(35,36,47,.84); background: radial-gradient(circle at 10% -5%, rgba(132,160,255,.20), transparent 42%), color-mix(in srgb, var(--dsw-alias-bg-layer-1, #26262e) 92%, transparent); color: var(--dsw-alias-label-primary, #eeeeF2); border: 1px solid rgba(150,164,215,.25); border-radius: 22px; box-shadow: 0 24px 70px rgba(0,0,0,.36), inset 0 1px 0 rgba(255,255,255,.07); backdrop-filter: blur(28px) saturate(1.28); -webkit-backdrop-filter: blur(28px) saturate(1.28); animation: iris-po-rise .20s cubic-bezier(.2,.8,.2,1); scrollbar-width: thin; outline: none; }',
|
|
303
305
|
'.iris-po-head { position: sticky; top: -18px; z-index: 1; margin: -18px -18px 0; padding: 16px 18px 10px; display: flex; align-items: center; justify-content: space-between; gap: 10px; background: linear-gradient(to bottom, color-mix(in srgb, var(--dsw-alias-bg-layer-1, #26262e) 88%, transparent) 72%, transparent); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }',
|
|
304
|
-
'.iris-po-title { display: inline-flex; align-items: center; gap: 9px; font-size:
|
|
306
|
+
'.iris-po-title { display: inline-flex; align-items: center; gap: 9px; font-size: 16px; letter-spacing: .01em; }',
|
|
307
|
+
'.iris-po-intro { display: grid; gap: 9px; }',
|
|
308
|
+
'.iris-po-principles { display: flex; flex-wrap: wrap; gap: 6px; }',
|
|
309
|
+
'.iris-po-principles span { padding: 3px 8px; border-radius: 999px; background: rgba(113,139,219,.09); color: var(--dsw-alias-label-secondary, #b4bdd5); font-size: 10px; }',
|
|
310
|
+
'.iris-po-section { min-width: 0; border: 1px solid rgba(137,155,218,.22); border-radius: 16px; background: rgba(128,150,221,.045); overflow: hidden; }',
|
|
311
|
+
'.iris-po-section > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 14px; cursor: pointer; list-style: none; font-size: 13px; font-weight: 650; }',
|
|
312
|
+
'.iris-po-section > summary::-webkit-details-marker { display: none; }',
|
|
313
|
+
'.iris-po-section > summary::after { content: "⌄"; color: var(--dsw-alias-label-secondary, #a6a6b2); transition: transform .15s; }',
|
|
314
|
+
'.iris-po-section[open] > summary::after { transform: rotate(180deg); }',
|
|
315
|
+
'.iris-po-section-caption { margin-left: auto; font-size: 11px; font-weight: 400; color: var(--dsw-alias-label-secondary, #a6a6b2); }',
|
|
316
|
+
'.iris-po-section-body { min-width: 0; display: grid; gap: 13px; padding: 0 14px 14px; }',
|
|
317
|
+
'.iris-po-section:not([open]) > .iris-po-section-body { display: none; }',
|
|
318
|
+
'.iris-po-targets { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 5px; }',
|
|
319
|
+
'.iris-po-target { min-width: 0; min-height: 42px; padding: 7px 3px; border: 1px solid transparent; border-radius: 10px; font: inherit; font-size: 12px; cursor: pointer; color: var(--dsw-alias-label-secondary, #a6a6b2); background: rgba(128,150,221,.05); }',
|
|
320
|
+
'.iris-po-target[aria-pressed="true"] { color: var(--dsw-alias-label-primary, #eeeef2); border-color: rgba(124,147,225,.48); background: rgba(124,147,225,.18); box-shadow: inset 0 1px 0 rgba(255,255,255,.1); font-weight: 650; }',
|
|
321
|
+
'.iris-po-target:disabled { opacity: .45; cursor: not-allowed; }',
|
|
322
|
+
'.iris-po-target:focus-visible, .iris-po-section > summary:focus-visible, .iris-po-config > summary:focus-visible { outline: 2px solid #8d9fe6; outline-offset: 2px; }',
|
|
323
|
+
'.iris-po-source { min-width: 0; padding: 11px 12px; border-radius: 12px; border: 1px solid rgba(150,164,215,.14); background: rgba(128,150,221,.04); }',
|
|
324
|
+
'.iris-po-source-head { display: flex; justify-content: space-between; gap: 10px; font-size: 11px; color: var(--dsw-alias-label-secondary, #a6a6b2); }',
|
|
325
|
+
'.iris-po-source-text { margin: 8px 0 0; max-height: 112px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 12px; line-height: 1.65; }',
|
|
326
|
+
'.iris-po-template { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 200px; overflow: auto; font-size: 11px; line-height: 1.65; padding: 10px; border-radius: 10px; background: rgba(128,150,221,.06); }',
|
|
305
327
|
'.iris-po-mark, .iris-po-settings-mark { display: inline-flex; align-items: center; justify-content: center; width: 29px; height: 29px; border-radius: 999px; background: rgba(255,255,255,.055); box-shadow: inset 0 1px 0 rgba(255,255,255,.10), 0 5px 16px rgba(67,83,168,.16); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); filter: drop-shadow(0 2px 5px rgba(105,128,235,.16)); }',
|
|
306
328
|
'.iris-po-close { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 999px; background: rgba(255,255,255,.05); color: var(--dsw-alias-label-secondary, #a6a6b2); font-size: 14px; cursor: pointer; transition: background .15s, color .15s; }',
|
|
307
329
|
'.iris-po-close:hover { background: rgba(255,255,255,.10); color: var(--dsw-alias-label-primary, #eeeef2); }',
|
|
@@ -313,6 +335,11 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
313
335
|
'.iris-po-field select:focus, .iris-po-field textarea:focus, .iris-po-result textarea:focus { border-color: rgba(122,162,247,.72); background: rgba(255,255,255,.075); box-shadow: 0 0 0 3px rgba(122,162,247,.11); }',
|
|
314
336
|
'.iris-po-field textarea { min-height: 60px; resize: vertical; line-height: 1.55; }',
|
|
315
337
|
'.iris-po-rules { display: grid; gap: 10px; }',
|
|
338
|
+
'.iris-po-editing { display: grid; gap: 8px; padding: 10px 12px; border: 1px solid rgba(150,164,215,.16); border-radius: 12px; }',
|
|
339
|
+
'.iris-po-editing label { display: flex; gap: 8px; align-items: center; font-size: 12px; cursor: pointer; }',
|
|
340
|
+
'.iris-po-suggestion { display: grid; gap: 7px; padding: 10px; margin-top: 8px; border-radius: 10px; background: rgba(128,150,221,.065); overflow-wrap: anywhere; }',
|
|
341
|
+
'.iris-po-suggestion label { display: flex; align-items: start; gap: 8px; font-size: 12px; }',
|
|
342
|
+
'.iris-po-suggestion p { margin: 0; white-space: pre-wrap; font-size: 12px; line-height: 1.6; }',
|
|
316
343
|
'.iris-po-diff { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 28dvh; overflow-y: auto; font-size: 12px; line-height: 1.6; }',
|
|
317
344
|
'.iris-po-diff del, .iris-po-diff ins { display: block; padding: 6px 8px; border-radius: 7px; margin: 5px 0; }',
|
|
318
345
|
'.iris-po-diff del { background: rgba(226,113,126,.12); }',
|
|
@@ -324,7 +351,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
324
351
|
'.iris-po-primary { background: linear-gradient(135deg, #779cf3, #8c79de); color: #fff; border-color: rgba(174,187,255,.55); font-weight: 650; box-shadow: 0 6px 18px rgba(76,92,188,.22); }',
|
|
325
352
|
'.iris-po-primary:hover { transform: translateY(-1px); box-shadow: 0 8px 22px rgba(76,92,188,.32); }',
|
|
326
353
|
'.iris-po-primary:disabled, .iris-po-btn:disabled { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }',
|
|
327
|
-
'.iris-po-result { display: grid; gap: 8px; padding: 12px; border: 1px solid rgba(137,155,218,.18); border-radius: 15px; background: rgba(
|
|
354
|
+
'.iris-po-result { display: grid; gap: 8px; padding: 12px; border: 1px solid rgba(137,155,218,.18); border-radius: 15px; background: rgba(128,150,221,.045); }',
|
|
328
355
|
'.iris-po-result-label { font-size: 11px; font-weight: 650; letter-spacing: .02em; }',
|
|
329
356
|
'.iris-po-result textarea { min-height: 156px; max-height: 34dvh; resize: vertical; line-height: 1.58; }',
|
|
330
357
|
'.iris-po-config { padding: 11px 12px; border: 1px solid rgba(150,164,215,.14); border-radius: 13px; background: rgba(255,255,255,.025); font-size: 11px; }',
|
|
@@ -783,7 +810,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
783
810
|
}
|
|
784
811
|
|
|
785
812
|
/* ---- 模型池(阶段 9 P4):发现/手动模型 + verified 标记 + 逐模型测试/移除 + 手动添加 ---- */
|
|
786
|
-
var CAP_SHORT = { 'image-gen': '图', 'video-gen': '视', 'tts': '音', 'transcribe': '转', 'vision': '视👁' };
|
|
813
|
+
var CAP_SHORT = { 'image-gen': '图', 'video-gen': '视', 'tts': '音', 'music-gen': '乐', 'transcribe': '转', 'vision': '视👁' };
|
|
787
814
|
function ModelPool(props) {
|
|
788
815
|
var p = props.provider;
|
|
789
816
|
var addPair = React.useState('');
|
|
@@ -794,6 +821,11 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
794
821
|
postAction('providers_set_model_image_protocol', { id: p.id, model_id: m.id, imageProtocol: value })
|
|
795
822
|
.then(function (r) { props.onNote(r.ok ? '模型图片协议已更新' : (r.d.error || '更新失败')); if (r.ok) props.onDone(); });
|
|
796
823
|
}
|
|
824
|
+
function setMusicProtocol(m, value) {
|
|
825
|
+
if (!value) return;
|
|
826
|
+
postAction('providers_set_model_music_protocol', { id: p.id, model_id: m.id, musicProtocol: value })
|
|
827
|
+
.then(function (r) { props.onNote(r.ok ? '模型音乐协议已更新' : (r.d.error || '更新失败')); if (r.ok) props.onDone(); });
|
|
828
|
+
}
|
|
797
829
|
function verBadge(m, c) {
|
|
798
830
|
var health = m.health && m.health[c];
|
|
799
831
|
var status = health && HEALTH_META[health.status] ? health.status : 'configured';
|
|
@@ -812,7 +844,8 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
812
844
|
var blocked = caps.map(function (c) { return m.health && m.health[c]; }).find(function (health) { return health && health.rateLimited; });
|
|
813
845
|
return React.createElement('div', { key: m.id, className: 'iris-pm-mrow' },
|
|
814
846
|
React.createElement('span', { className: 'iris-pm-mname' }, m.id, m.source === 'manual' ? React.createElement('span', { className: 'iris-pm-mtag' }, '手动') : null),
|
|
815
|
-
React.createElement('span', { className: 'iris-pm-mcaps' }, caps.map(function (c) { return verBadge(m, c); })),
|
|
847
|
+
React.createElement('span', { className: 'iris-pm-mcaps' }, caps.length ? caps.map(function (c) { return verBadge(m, c); }) : '未标注功能'),
|
|
848
|
+
React.createElement(ModelCapabilityEditor, { provider: p, model: m, onNote: props.onNote, onDone: props.onDone }),
|
|
816
849
|
caps.includes('image-gen') ? React.createElement('label', { className: 'iris-pm-note' }, '图片协议 ',
|
|
817
850
|
React.createElement('select', { value: m.imageProtocol || 'auto', onChange: function (e) { setImageProtocol(m, e.target.value); } },
|
|
818
851
|
React.createElement('option', { value: 'auto' }, '继承账号默认(' + (p.mediaProtocol || '自动') + ')'),
|
|
@@ -821,6 +854,10 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
821
854
|
React.createElement('option', { value: 'openai-chat-images' }, '聊天生图(网关兼容)'),
|
|
822
855
|
React.createElement('option', { value: 'openai-responses-images' }, 'Responses 生图')),
|
|
823
856
|
m.imageRouting && m.imageRouting.protocolInferred ? ' · 协议待确认' : null) : null,
|
|
857
|
+
caps.includes('music-gen') ? React.createElement('label', { className: 'iris-pm-note' }, '音乐协议 ',
|
|
858
|
+
React.createElement('select', { value: m.musicProtocol || '', onChange: function (e) { setMusicProtocol(m, e.target.value); } },
|
|
859
|
+
React.createElement('option', { value: '' }, '请选择音乐协议'),
|
|
860
|
+
React.createElement('option', { value: 'gemini-web-music' }, 'Chat Completions(内嵌音频)'))) : null,
|
|
824
861
|
caps.includes('vision') || (caps.includes('image-gen') && m.imageRouting && m.imageRouting.mediaProtocol === 'openai-chat-images') ? React.createElement(VisionInputEditor, { key: 'vision-input', provider: p, model: m,
|
|
825
862
|
onNote: props.onNote, onDone: props.onDone }) : null,
|
|
826
863
|
blocked ? React.createElement('span', { className: 'iris-pm-ver failed ' + healthClass(blocked), title: healthText(blocked) }, rateLimitLabel(blocked)) : null,
|
|
@@ -834,6 +871,42 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
834
871
|
React.createElement('button', { className: 'iris-pm-btn', onClick: function () { props.addModel(p, newId.trim()); setNewId(''); } }, '+ 添加')));
|
|
835
872
|
}
|
|
836
873
|
|
|
874
|
+
function ModelCapabilityEditor(props) {
|
|
875
|
+
var openPair = React.useState(false);
|
|
876
|
+
var capsPair = React.useState([]);
|
|
877
|
+
var savingPair = React.useState(false);
|
|
878
|
+
var selected = capsPair[0];
|
|
879
|
+
var saving = savingPair[0];
|
|
880
|
+
function save() {
|
|
881
|
+
if (saving) return;
|
|
882
|
+
savingPair[1](true);
|
|
883
|
+
postAction('providers_set_model_caps', { id: props.provider.id, model_id: props.model.id, capabilities: selected })
|
|
884
|
+
.then(function (r) {
|
|
885
|
+
if (r.ok) {
|
|
886
|
+
openPair[1](false);
|
|
887
|
+
props.onNote('模型功能标签已保存');
|
|
888
|
+
props.onDone();
|
|
889
|
+
} else props.onNote(r.d.error || '保存失败');
|
|
890
|
+
}).finally(function () { savingPair[1](false); });
|
|
891
|
+
}
|
|
892
|
+
if (!openPair[0]) return React.createElement('button', { className: 'iris-pm-btn', title: '设置此模型可用于哪些功能',
|
|
893
|
+
onClick: function () { capsPair[1]((props.model.capabilities || []).slice()); openPair[1](true); } }, '设置功能');
|
|
894
|
+
return React.createElement('div', { className: 'iris-wb-row' },
|
|
895
|
+
CAP_ROWS.map(function (row) {
|
|
896
|
+
return React.createElement('label', { key: row.cap, className: 'iris-pm-note' },
|
|
897
|
+
React.createElement('input', { type: 'checkbox', value: row.cap, checked: selected.includes(row.cap), disabled: saving,
|
|
898
|
+
onChange: function (e) {
|
|
899
|
+
var checked = e.target.checked;
|
|
900
|
+
capsPair[1](function (previous) {
|
|
901
|
+
return checked ? previous.filter(function (cap) { return cap !== row.cap; }).concat(row.cap)
|
|
902
|
+
: previous.filter(function (cap) { return cap !== row.cap; });
|
|
903
|
+
});
|
|
904
|
+
} }), row.label);
|
|
905
|
+
}),
|
|
906
|
+
React.createElement('button', { className: 'iris-pm-btn', disabled: saving, onClick: save }, saving ? '保存中…' : '保存功能'),
|
|
907
|
+
React.createElement('button', { className: 'iris-pm-btn', disabled: saving, onClick: function () { openPair[1](false); } }, '取消'));
|
|
908
|
+
}
|
|
909
|
+
|
|
837
910
|
function VisionInputEditor(props) {
|
|
838
911
|
var p = props.provider;
|
|
839
912
|
var m = props.model;
|
|
@@ -936,7 +1009,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
936
1009
|
postAction('providers_discover', { id: p.id }).then(function (r) { setNote(r.d.text || r.d.error || '发现完成'); refresh(); });
|
|
937
1010
|
}
|
|
938
1011
|
function testModel(p, m, capability) {
|
|
939
|
-
var noProbe = capability === 'video-gen' || capability === 'transcribe';
|
|
1012
|
+
var noProbe = capability === 'video-gen' || capability === 'transcribe' || capability === 'music-gen';
|
|
940
1013
|
if (!noProbe && !window.confirm('将用模型「' + m.id + '」发起一次真实的 ' + capability + ' 请求,可能产生费用。继续吗?')) return;
|
|
941
1014
|
setNote('验证 ' + m.id + ' · ' + capability + '…');
|
|
942
1015
|
postAction('providers_test_model', { id: p.id, model_id: m.id, capability: capability, confirm_paid: !noProbe })
|
|
@@ -1102,7 +1175,8 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1102
1175
|
if (!r.ok || !r.d) return;
|
|
1103
1176
|
var opts = (r.d.poolByCapability && r.d.poolByCapability[capability]) || [];
|
|
1104
1177
|
var ord = (r.d.order && r.d.order[capability]) || [];
|
|
1105
|
-
|
|
1178
|
+
if (capability === 'music-gen') opts = opts.filter(function (option) { return ord.includes(option.ref); });
|
|
1179
|
+
var assignedRef = ord[0] || (capability !== 'music-gen' && opts[0] && opts[0].ref) || '';
|
|
1106
1180
|
var assignedOpt = opts.find(function (o) { return o.ref === assignedRef; });
|
|
1107
1181
|
// 不再自动填 vals.model:留空 = 用能力分配的解析结果(避免绕过分配)
|
|
1108
1182
|
setModelInfo({ assigned: assignedOpt ? assignedOpt.label : '', assignedRef: assignedRef, options: opts, loaded: true });
|
|
@@ -1119,7 +1193,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1119
1193
|
})
|
|
1120
1194
|
.then(function (r) { return r.json().then(function (d) { return { ok: r.ok, d: d }; }); })
|
|
1121
1195
|
.then(function (res) {
|
|
1122
|
-
setRun(res.ok ? { ok: true, text: res.d.text || '', img: res.d.imageUrl || res.d.imageDataUrl || null } : { ok: false, text: res.d.error || '执行失败' });
|
|
1196
|
+
setRun(res.ok ? { ok: true, text: res.d.text || '', img: res.d.imageUrl || res.d.imageDataUrl || null, audio: res.d.audioUrl || null } : { ok: false, text: res.d.error || '执行失败' });
|
|
1123
1197
|
if (res.ok && res.d && res.d.storage === 'core') window.dispatchEvent(new CustomEvent('iris-core-artifacts-changed'));
|
|
1124
1198
|
})
|
|
1125
1199
|
.catch(function () { setRun({ ok: false, text: '网络错误' }); });
|
|
@@ -1129,6 +1203,14 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1129
1203
|
if (open) {
|
|
1130
1204
|
var inputs = fields.map(function (f) {
|
|
1131
1205
|
var node;
|
|
1206
|
+
if (f.key === 'model' && capability === 'music-gen') {
|
|
1207
|
+
node = React.createElement('select', { value: vals.model || '', onChange: function (e) { setVal('model', e.target.value); } },
|
|
1208
|
+
React.createElement('option', { value: '' }, '按 Music 分配顺序'),
|
|
1209
|
+
((modelInfo && modelInfo.options) || []).map(function (option) {
|
|
1210
|
+
return React.createElement('option', { key: option.ref, value: option.ref }, option.label);
|
|
1211
|
+
}));
|
|
1212
|
+
return React.createElement('div', { key: f.key, className: 'iris-act-field' }, React.createElement('label', {}, f.label), node);
|
|
1213
|
+
}
|
|
1132
1214
|
if (f.type === 'file') {
|
|
1133
1215
|
node = React.createElement(FileField, { value: vals[f.key] || '', accept: f.accept || '', onChange: function (v) { setVal(f.key, v); } });
|
|
1134
1216
|
return React.createElement('div', { key: f.key, className: 'iris-act-field' },
|
|
@@ -1156,6 +1238,10 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1156
1238
|
result = React.createElement('div', { className: 'iris-act-result' },
|
|
1157
1239
|
React.createElement('div', {}, run.text),
|
|
1158
1240
|
React.createElement('img', { className: 'iris-act-img', src: run.img, alt: '结果' }));
|
|
1241
|
+
} else if (run.ok && run.audio) {
|
|
1242
|
+
result = React.createElement('div', { className: 'iris-act-result' }, React.createElement('div', {}, run.text),
|
|
1243
|
+
React.createElement('audio', { src: run.audio, controls: true, preload: 'metadata' }),
|
|
1244
|
+
React.createElement('a', { href: run.audio, download: '' }, '下载音乐'));
|
|
1159
1245
|
} else {
|
|
1160
1246
|
result = React.createElement('div', { className: 'iris-act-result' + (run.ok ? '' : ' err') }, run.text);
|
|
1161
1247
|
}
|
|
@@ -1168,7 +1254,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1168
1254
|
modelBar = React.createElement('div', { className: 'iris-act-field' },
|
|
1169
1255
|
React.createElement('label', {},
|
|
1170
1256
|
React.createElement('span', { className: 'iris-pm-dot ' + healthClass(cardHealth) }, cardHealth.retryAt ? '◷' : HEALTH_META[cardHealth.status].symbol),
|
|
1171
|
-
' 模型:' + (shown || '自动') + (available ? '' : '(无可用模型)')),
|
|
1257
|
+
' 模型:' + (shown || (capability === 'music-gen' ? '未分配' : '自动')) + (available ? '' : '(无可用模型)')),
|
|
1172
1258
|
React.createElement('div', { className: 'iris-wb-muted' },
|
|
1173
1259
|
healthText(cardHealth) + ' · 改分配 → 上方「能力分配(failover 顺序)」'));
|
|
1174
1260
|
}
|
|
@@ -1208,6 +1294,12 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1208
1294
|
{ action: 'tts', title: '🔊 语音合成', capability: 'tts', fields: [
|
|
1209
1295
|
{ key: 'text', label: '文本', type: 'textarea', placeholder: '要合成的文字' },
|
|
1210
1296
|
{ key: 'voice', label: '音色 (可选)', placeholder: '如 Cherry' }] },
|
|
1297
|
+
{ action: 'music', title: '🎵 音乐生成', capability: 'music-gen', fields: [
|
|
1298
|
+
{ key: 'prompt', label: '音乐描述', type: 'textarea', placeholder: '描述风格、情绪、乐器;歌词、演唱语言和期望时长也可写在这里' },
|
|
1299
|
+
{ key: 'model', label: '音乐模型' },
|
|
1300
|
+
{ key: 'timeout_ms', label: '单次等待上限(毫秒,可选)', type: 'number', placeholder: '300000' },
|
|
1301
|
+
{ key: 'retry_502', label: '502重新生成次数(可选,会额外占用调用额度)', type: 'number', placeholder: '2(0关闭,最多5)' },
|
|
1302
|
+
{ key: 'retry_delay_ms', label: '重试等待(毫秒,可选)', type: 'number', placeholder: '5000' }] },
|
|
1211
1303
|
{ action: 'transcribe', title: '🎙️ 音频转写', capability: 'transcribe', fields: [
|
|
1212
1304
|
{ key: 'audio_path', label: '音频文件', type: 'file', accept: 'audio/*', placeholder: '/path/audio.wav' }] },
|
|
1213
1305
|
{ action: 'video_frames', title: '🎞️ 视频抽帧', fields: [
|
|
@@ -1261,6 +1353,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1261
1353
|
{ cap: 'image-gen', label: '🎨 画图' },
|
|
1262
1354
|
{ cap: 'video-gen', label: '🎬 视频' },
|
|
1263
1355
|
{ cap: 'tts', label: '🔊 语音' },
|
|
1356
|
+
{ cap: 'music-gen', label: '🎵 音乐' },
|
|
1264
1357
|
{ cap: 'transcribe', label: '🎙️ 转写' },
|
|
1265
1358
|
{ cap: 'vision', label: '👁 视觉' }
|
|
1266
1359
|
];
|
|
@@ -1306,7 +1399,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1306
1399
|
});
|
|
1307
1400
|
return React.createElement('div', { key: row.cap, className: 'iris-cap-row' },
|
|
1308
1401
|
React.createElement('span', { className: 'iris-cap-name' }, row.label),
|
|
1309
|
-
chips.length ? chips : React.createElement('span', { className: 'iris-cap-auto' }, '自动(按池顺序)'),
|
|
1402
|
+
chips.length ? chips : React.createElement('span', { className: 'iris-cap-auto' }, row.cap === 'music-gen' ? '尚未分配音乐模型' : '自动(按池顺序)'),
|
|
1310
1403
|
available.length ? React.createElement('select', {
|
|
1311
1404
|
className: 'iris-pm-model-sel', value: '',
|
|
1312
1405
|
onChange: function (e) { if (e.target.value) save(row.cap, list.concat([e.target.value])); }
|
|
@@ -1924,7 +2017,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
1924
2017
|
}
|
|
1925
2018
|
|
|
1926
2019
|
function coreCapabilityLabel(value) {
|
|
1927
|
-
return ({ image: '图片生成', video: '视频生成', tts: '语音合成', transcribe: '音频转写' })[value] || String(value || '媒体任务');
|
|
2020
|
+
return ({ image: '图片生成', video: '视频生成', tts: '语音合成', music: '音乐生成', transcribe: '音频转写' })[value] || String(value || '媒体任务');
|
|
1928
2021
|
}
|
|
1929
2022
|
|
|
1930
2023
|
/* 高级诊断与用户任务区共用五类用户状态投影;与服务端 lib/core-user-projection.js 保持同一映射,
|
|
@@ -2458,6 +2551,24 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2458
2551
|
note ? React.createElement('div', { className: 'iris-clean-note', style: { width: '100%' } }, note) : null);
|
|
2459
2552
|
}
|
|
2460
2553
|
|
|
2554
|
+
function promptConfigFeedback(state) {
|
|
2555
|
+
var warnings = state && state.feedback && state.feedback.warnings;
|
|
2556
|
+
if (!Array.isArray(warnings) || !warnings.length) return null;
|
|
2557
|
+
return React.createElement('div', { className: 'iris-po-note', role: 'status' }, warnings.map(function (warning, index) {
|
|
2558
|
+
var text = '';
|
|
2559
|
+
if (warning.code === 'config-fallback') {
|
|
2560
|
+
text = warning.reason === 'read-failed' ? '配置读取失败,当前使用 Iris 默认设置。' : '配置内容无效,当前使用 Iris 默认设置。';
|
|
2561
|
+
text += warning.isolation === 'saved' ? '原文件已隔离保留,可在修正后重新导入。'
|
|
2562
|
+
: warning.isolation === 'failed' ? '隔离未完成,Iris 没有覆盖原文件;请检查原文件。' : '原文件未移动;请检查文件读取权限。';
|
|
2563
|
+
} else if (warning.code === 'ignored-fields' && Array.isArray(warning.fields)) {
|
|
2564
|
+
text = '已忽略不支持或当前路由未使用的字段:' + warning.fields.filter(function (field) { return typeof field === 'string'; }).map(function (field) { return JSON.stringify(field); }).join('、');
|
|
2565
|
+
if (warning.count > warning.fields.length) text += '(共 ' + warning.count + ' 个,仅显示前 ' + warning.fields.length + ' 个)';
|
|
2566
|
+
text += '。请检查字段名;这些字段未保存到配置。';
|
|
2567
|
+
}
|
|
2568
|
+
return text ? React.createElement('div', { key: index }, text) : null;
|
|
2569
|
+
}));
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2461
2572
|
function PromptOptimizerSettings() {
|
|
2462
2573
|
var pair = React.useState(null);
|
|
2463
2574
|
var state = pair[0];
|
|
@@ -2502,6 +2613,7 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2502
2613
|
React.createElement('span', { style: { flex: 1 } }, enabled ? '对话框入口已启用' : '对话框入口已关闭'),
|
|
2503
2614
|
React.createElement('button', { className: 'iris-pm-btn', onClick: toggle }, enabled ? '关闭入口' : '重新启用')),
|
|
2504
2615
|
React.createElement('div', { className: 'iris-wb-muted' }, '这里只控制对话框提示词优化入口;Iris 工作台、Agent 工具和任务后台始终保持运行。'),
|
|
2616
|
+
promptConfigFeedback(state),
|
|
2505
2617
|
note ? React.createElement('div', { className: 'iris-clean-note' }, note) : null);
|
|
2506
2618
|
}
|
|
2507
2619
|
|
|
@@ -2674,6 +2786,14 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2674
2786
|
selectedTask ? React.createElement(TaskDetailDrawer, { taskId: selectedTask }) : null);
|
|
2675
2787
|
}
|
|
2676
2788
|
|
|
2789
|
+
var PROMPT_TARGET_OPTIONS = [
|
|
2790
|
+
{ value: 'general', label: '通用', description: '整理目标、背景、约束与输出要求。' },
|
|
2791
|
+
{ value: 'image', label: '画图', description: '整理已有主体、场景与构图要求,未指定细节不自动补齐。' },
|
|
2792
|
+
{ value: 'image-edit', label: '改图', description: '明确要修改的部分,保留原图其余特征。' },
|
|
2793
|
+
{ value: 'video', label: '视频', description: '组织动作、镜头与时间上的连续性。' },
|
|
2794
|
+
{ value: 's2v', label: '数字人', description: '围绕已有首帧与音频设计表情、动作和镜头。' }
|
|
2795
|
+
];
|
|
2796
|
+
|
|
2677
2797
|
// 折叠相同首尾,只显示中间替换区;按 Unicode code point 比较,不拆开 emoji。
|
|
2678
2798
|
function promptChanges(original, edited) {
|
|
2679
2799
|
var before = Array.from(original);
|
|
@@ -2685,6 +2805,18 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2685
2805
|
return { removed: before.slice(start, before.length - end).join(''), added: after.slice(start, after.length - end).join('') };
|
|
2686
2806
|
}
|
|
2687
2807
|
|
|
2808
|
+
function promptRequestSnapshot(processing, title) {
|
|
2809
|
+
var request = processing && processing.request;
|
|
2810
|
+
if (!request || typeof request.system !== 'string' || typeof request.prompt !== 'string') return null;
|
|
2811
|
+
return React.createElement('details', { className: 'iris-po-config' },
|
|
2812
|
+
React.createElement('summary', {}, title),
|
|
2813
|
+
React.createElement('div', { className: 'iris-po-muted' }, 'Iris 发送的指令快照;宿主或供应商后续处理可能不同。'),
|
|
2814
|
+
React.createElement('div', { className: 'iris-po-result-label' }, '系统指令 · 含本次规则与输出协议'),
|
|
2815
|
+
React.createElement('div', { className: 'iris-po-template', 'aria-label': title + ' · 系统指令' }, request.system),
|
|
2816
|
+
React.createElement('div', { className: 'iris-po-result-label' }, '用户输入 · 含素材包装'),
|
|
2817
|
+
React.createElement('div', { className: 'iris-po-template', 'aria-label': title + ' · 用户输入' }, request.prompt));
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2688
2820
|
function PromptOptimizerControl(props) {
|
|
2689
2821
|
var draft = props.useInput(function (value) { return value.draft; });
|
|
2690
2822
|
var phase = props.useInput(function (value) { return value.phase; });
|
|
@@ -2695,6 +2827,8 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2695
2827
|
var openPair = React.useState(false);
|
|
2696
2828
|
var open = openPair[0];
|
|
2697
2829
|
var setOpen = openPair[1];
|
|
2830
|
+
var generalPair = React.useState(true);
|
|
2831
|
+
var generalOpen = generalPair[0];
|
|
2698
2832
|
var targetPair = React.useState('general');
|
|
2699
2833
|
var target = targetPair[0];
|
|
2700
2834
|
var setTarget = targetPair[1];
|
|
@@ -2722,14 +2856,39 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2722
2856
|
var editedPair = React.useState('');
|
|
2723
2857
|
var edited = editedPair[0];
|
|
2724
2858
|
var setEdited = editedPair[1];
|
|
2859
|
+
var editingPair = React.useState('faithful');
|
|
2860
|
+
var editing = editingPair[0];
|
|
2861
|
+
var suggestionsPair = React.useState(null);
|
|
2862
|
+
var suggestions = suggestionsPair[0];
|
|
2863
|
+
var setSuggestions = suggestionsPair[1];
|
|
2864
|
+
var selectedSuggestionsPair = React.useState([]);
|
|
2865
|
+
var selectedSuggestions = selectedSuggestionsPair[0];
|
|
2866
|
+
var setSelectedSuggestions = selectedSuggestionsPair[1];
|
|
2867
|
+
var undoPair = React.useState([]);
|
|
2868
|
+
var suggestionUndo = undoPair[0];
|
|
2869
|
+
var setSuggestionUndo = undoPair[1];
|
|
2870
|
+
var editedRef = React.useRef(edited);
|
|
2871
|
+
var resultRef = React.useRef(result);
|
|
2872
|
+
editedRef.current = edited;
|
|
2873
|
+
resultRef.current = result;
|
|
2725
2874
|
var abortRef = React.useRef(null);
|
|
2726
2875
|
var fileRef = React.useRef(null);
|
|
2876
|
+
var panelRef = React.useRef(null);
|
|
2727
2877
|
var lastWrittenRef = React.useRef(null);
|
|
2728
2878
|
var resultSessionRef = React.useRef(null);
|
|
2729
2879
|
var sessionRef = React.useRef(props.sessionId);
|
|
2730
2880
|
sessionRef.current = props.sessionId;
|
|
2731
2881
|
var supportsRules = !!(configState && configState.capabilities && configState.capabilities.rules === true);
|
|
2732
2882
|
var supportsAssembly = !!(configState && configState.capabilities && configState.capabilities.assemble === true);
|
|
2883
|
+
var editingCapabilities = configState && configState.capabilities && configState.capabilities.editing;
|
|
2884
|
+
var supportsFaithful = Array.isArray(editingCapabilities) && editingCapabilities.indexOf('faithful') >= 0 && editingCapabilities.indexOf('rewrite') >= 0;
|
|
2885
|
+
var supportsLocalFaithful = supportsFaithful && configState.capabilities.localFaithful === true;
|
|
2886
|
+
var supportsSuggestions = Array.isArray(editingCapabilities) && editingCapabilities.indexOf('suggestions') >= 0;
|
|
2887
|
+
var supportsResetInstructions = !!(configState && configState.capabilities && configState.capabilities.resetInstructions === true);
|
|
2888
|
+
function supportsTarget(value) {
|
|
2889
|
+
var available = configState && configState.capabilities && configState.capabilities.targets;
|
|
2890
|
+
return Array.isArray(available) ? available.indexOf(value) >= 0 : value !== 'image-edit';
|
|
2891
|
+
}
|
|
2733
2892
|
|
|
2734
2893
|
function promptRequest(operation, body, signal) {
|
|
2735
2894
|
return fetch('/iris/api/prompt-optimizer/' + operation, {
|
|
@@ -2769,10 +2928,35 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2769
2928
|
React.useEffect(function () {
|
|
2770
2929
|
cancel();
|
|
2771
2930
|
setResult(null);
|
|
2931
|
+
setSuggestions(null); setSelectedSuggestions([]); setSuggestionUndo([]);
|
|
2772
2932
|
lastWrittenRef.current = null;
|
|
2773
2933
|
resultSessionRef.current = null;
|
|
2774
2934
|
}, [props.sessionId]);
|
|
2775
2935
|
|
|
2936
|
+
React.useEffect(function () {
|
|
2937
|
+
if (!open) return;
|
|
2938
|
+
var previous = document.activeElement;
|
|
2939
|
+
var dialog = panelRef.current;
|
|
2940
|
+
if (dialog) { dialog.showModal(); dialog.focus(); }
|
|
2941
|
+
function keyboard(event) {
|
|
2942
|
+
if (event.key === 'Escape') { event.preventDefault(); closePanel(); }
|
|
2943
|
+
if (event.key !== 'Tab' || !panelRef.current) return;
|
|
2944
|
+
var items = Array.from(panelRef.current.querySelectorAll('button:not(:disabled), textarea:not(:disabled), summary, input:not(:disabled)'))
|
|
2945
|
+
.filter(function (item) { return item.getClientRects().length > 0; });
|
|
2946
|
+
if (!items.length) return;
|
|
2947
|
+
var first = items[0], last = items[items.length - 1];
|
|
2948
|
+
if (event.shiftKey && (document.activeElement === first || document.activeElement === panelRef.current)) {
|
|
2949
|
+
event.preventDefault(); last.focus();
|
|
2950
|
+
} else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }
|
|
2951
|
+
}
|
|
2952
|
+
window.addEventListener('keydown', keyboard);
|
|
2953
|
+
return function () {
|
|
2954
|
+
window.removeEventListener('keydown', keyboard);
|
|
2955
|
+
if (dialog && dialog.open) dialog.close();
|
|
2956
|
+
if (previous && previous.isConnected) previous.focus();
|
|
2957
|
+
};
|
|
2958
|
+
}, [open]);
|
|
2959
|
+
|
|
2776
2960
|
function publishConfig(data) {
|
|
2777
2961
|
setConfigState(data);
|
|
2778
2962
|
try { window.dispatchEvent(new CustomEvent('iris-prompt-config-changed', { detail: data })); } catch (_) {}
|
|
@@ -2789,22 +2973,28 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2789
2973
|
|
|
2790
2974
|
function optimize(mode) {
|
|
2791
2975
|
mode = mode === 'assemble' ? 'assemble' : 'optimize';
|
|
2976
|
+
if (!supportsTarget(target)) { setNote('当前后端尚未支持此优化目标,请更新并重新载入'); return; }
|
|
2792
2977
|
if (mode === 'assemble' && !supportsAssembly) { setNote('当前后端尚未支持只组装,请更新并重新载入'); return; }
|
|
2793
2978
|
if (!draft || !draft.trim()) { setNote('请先在输入框中写入提示词'); return; }
|
|
2794
2979
|
if (refCount) { setNote('当前版本暂不改写含 @ 或 / 结构化引用的草稿,以免引用失效'); return; }
|
|
2795
2980
|
if (phase !== 'plain') { setNote('输入框正忙,请稍后再试'); return; }
|
|
2981
|
+
if (mode === 'optimize' && supportsFaithful && editing === 'faithful' && optimizationText.trim()) {
|
|
2982
|
+
setNote('忠实整理只调整分段;使用本次改写规则前,请选择“改写表达”。'); return;
|
|
2983
|
+
}
|
|
2796
2984
|
if (abortRef.current) abortRef.current.abort();
|
|
2797
2985
|
var controller = new AbortController();
|
|
2798
2986
|
var requestSessionId = props.sessionId;
|
|
2987
|
+
var previousResult = result;
|
|
2988
|
+
var previewSnapshot = edited;
|
|
2799
2989
|
abortRef.current = controller;
|
|
2800
2990
|
setBusy(true);
|
|
2801
|
-
setNote(mode === 'assemble' ? '正在组装,不调用模型…' : '
|
|
2802
|
-
|
|
2803
|
-
lastWrittenRef.current = null;
|
|
2991
|
+
setNote(mode === 'assemble' ? '正在组装,不调用模型…' : supportsLocalFaithful && editing === 'faithful'
|
|
2992
|
+
? '正在忠实整理…需要分段时可能调用模型并产生费用' : '正在调用模型优化…这可能产生模型费用');
|
|
2804
2993
|
promptRequest('optimize', {
|
|
2805
2994
|
text: draft,
|
|
2806
2995
|
target: target,
|
|
2807
2996
|
mode: mode,
|
|
2997
|
+
editing: mode === 'optimize' && supportsFaithful ? editing : undefined,
|
|
2808
2998
|
rules: selectedRules(mode),
|
|
2809
2999
|
sessionId: props.sessionId,
|
|
2810
3000
|
route: selectedRoute || undefined
|
|
@@ -2812,19 +3002,91 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2812
3002
|
if (abortRef.current !== controller || controller.signal.aborted) return;
|
|
2813
3003
|
if (sessionRef.current !== requestSessionId) throw new Error('会话已切换,请在当前会话重新生成预览');
|
|
2814
3004
|
if (!data.ok || typeof data.optimized !== 'string' || typeof data.original !== 'string') throw new Error('未收到完整优化结果');
|
|
3005
|
+
if (data.original !== draft) throw new Error('结果原稿与本次请求不一致');
|
|
3006
|
+
if (mode === 'optimize' && supportsFaithful && editing === 'faithful'
|
|
3007
|
+
&& (data.editing?.strategy !== 'faithful' || data.editing.coverage !== 'exact' || data.editing.order !== 'preserved')) throw new Error('后端未确认完整的忠实整理结果');
|
|
3008
|
+
if (resultRef.current !== previousResult || editedRef.current !== previewSnapshot) {
|
|
3009
|
+
setNote('预览已变化,本次结果未替换;你的编辑已保留。'); return;
|
|
3010
|
+
}
|
|
2815
3011
|
setResult(data);
|
|
2816
3012
|
setEdited(data.optimized);
|
|
3013
|
+
setSuggestions(null); setSelectedSuggestions([]); setSuggestionUndo([]);
|
|
3014
|
+
lastWrittenRef.current = null;
|
|
2817
3015
|
resultSessionRef.current = requestSessionId;
|
|
2818
|
-
setNote('
|
|
3016
|
+
setNote(data.execution?.reason === 'single-part-faithful' && data.execution.modelInvocations === 0
|
|
3017
|
+
? '原文无需分段,未调用模型;尚未写回输入框' : '已生成预览,尚未写回输入框');
|
|
2819
3018
|
}).catch(function (err) {
|
|
2820
3019
|
if (abortRef.current !== controller) return;
|
|
2821
3020
|
if (controller.signal.aborted) setNote('已取消');
|
|
2822
|
-
else setNote(String(err && err.message || err));
|
|
3021
|
+
else setNote(String(err && err.message || err) + (previousResult ? ';原有预览已保留' : ''));
|
|
2823
3022
|
}).finally(function () {
|
|
2824
3023
|
if (abortRef.current === controller) { abortRef.current = null; setBusy(false); }
|
|
2825
3024
|
});
|
|
2826
3025
|
}
|
|
2827
3026
|
|
|
3027
|
+
function requestSuggestions() {
|
|
3028
|
+
if (!supportsSuggestions || !result || busy || !validEdited()) return;
|
|
3029
|
+
if (resultSessionRef.current !== props.sessionId) { setNote('会话已切换,请重新生成预览'); return; }
|
|
3030
|
+
var snapshot = edited;
|
|
3031
|
+
var previousResult = result;
|
|
3032
|
+
var requestSessionId = props.sessionId;
|
|
3033
|
+
var controller = new AbortController();
|
|
3034
|
+
abortRef.current = controller;
|
|
3035
|
+
setBusy(true); setNote('正在获取可选建议,正文保持原样;这会调用文本模型。');
|
|
3036
|
+
promptRequest('optimize', { text: snapshot, target: result.target, mode: 'optimize', editing: 'suggestions', rules: [],
|
|
3037
|
+
sessionId: props.sessionId, route: selectedRoute || undefined }, controller.signal).then(function (data) {
|
|
3038
|
+
if (abortRef.current !== controller || controller.signal.aborted) return;
|
|
3039
|
+
if (sessionRef.current !== requestSessionId || resultRef.current !== previousResult || editedRef.current !== snapshot) {
|
|
3040
|
+
setNote('预览已变化,本次建议未载入;请针对当前文字重新获取。'); return;
|
|
3041
|
+
}
|
|
3042
|
+
var ids = [];
|
|
3043
|
+
if (!data.ok || data.original !== snapshot || data.optimized !== snapshot || data.target !== previousResult.target || data.editing?.strategy !== 'suggestions'
|
|
3044
|
+
|| !Array.isArray(data.suggestions) || data.suggestions.length > 6 || !Array.isArray(data.questions) || data.questions.length > 6
|
|
3045
|
+
|| !data.suggestions.every(function (item) {
|
|
3046
|
+
if (!item || typeof item.id !== 'string' || !/^suggestion-[1-6]$/.test(item.id) || ids.indexOf(item.id) >= 0
|
|
3047
|
+
|| typeof item.label !== 'string' || !item.label.trim() || item.label.length > 80
|
|
3048
|
+
|| typeof item.text !== 'string' || !item.text.trim() || item.text.length > 600) return false;
|
|
3049
|
+
ids.push(item.id); return true;
|
|
3050
|
+
}) || !data.questions.every(function (text) { return typeof text === 'string' && text.trim() && text.length <= 600; })) throw new Error('未收到完整补充建议');
|
|
3051
|
+
setSuggestions({ source: snapshot, items: data.suggestions, questions: data.questions, adopted: [], processing: data.processing });
|
|
3052
|
+
setSelectedSuggestions([]); setSuggestionUndo([]);
|
|
3053
|
+
setNote('建议尚未加入正文;只有采纳所选建议才会改变预览。');
|
|
3054
|
+
}).catch(function (err) {
|
|
3055
|
+
if (abortRef.current !== controller) return;
|
|
3056
|
+
setNote(controller.signal.aborted ? '已取消,原有预览保留' : String(err && err.message || err));
|
|
3057
|
+
}).finally(function () {
|
|
3058
|
+
if (abortRef.current === controller) { abortRef.current = null; setBusy(false); }
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3061
|
+
|
|
3062
|
+
function adoptSuggestions() {
|
|
3063
|
+
if (!suggestions || busy || !selectedSuggestions.length) return;
|
|
3064
|
+
var items = suggestions.items.filter(function (item) { return selectedSuggestions.indexOf(item.id) >= 0 && suggestions.adopted.indexOf(item.id) < 0; });
|
|
3065
|
+
if (!items.length) return;
|
|
3066
|
+
var next = edited + '\n\n' + items.map(function (item) { return item.text; }).join('\n\n');
|
|
3067
|
+
if (next.length > 16000) { setNote('采纳后将超过 16000 字符,请减少建议或手动编辑'); return; }
|
|
3068
|
+
var ids = items.map(function (item) { return item.id; });
|
|
3069
|
+
setSuggestionUndo(suggestionUndo.concat([{ before: edited, after: next, ids: ids }]));
|
|
3070
|
+
setSuggestions(Object.assign({}, suggestions, { adopted: suggestions.adopted.concat(ids) }));
|
|
3071
|
+
setEdited(next); editedRef.current = next; setSelectedSuggestions([]);
|
|
3072
|
+
setNote('已将所选建议加入预览,尚未写回;可以撤回上次采纳。');
|
|
3073
|
+
}
|
|
3074
|
+
|
|
3075
|
+
function undoSuggestions() {
|
|
3076
|
+
var last = suggestionUndo[suggestionUndo.length - 1];
|
|
3077
|
+
if (!last || busy) return;
|
|
3078
|
+
if (edited !== last.after) { setNote('预览已被手动修改;请手动移除建议,撤回不会覆盖你的编辑。'); return; }
|
|
3079
|
+
setEdited(last.before); editedRef.current = last.before;
|
|
3080
|
+
setSuggestionUndo(suggestionUndo.slice(0, -1));
|
|
3081
|
+
if (suggestions) setSuggestions(Object.assign({}, suggestions, { adopted: suggestions.adopted.filter(function (id) { return last.ids.indexOf(id) < 0; }) }));
|
|
3082
|
+
setNote('已撤回上次采纳,尚未写回输入框。');
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3085
|
+
function editPreview(value) {
|
|
3086
|
+
setEdited(value); editedRef.current = value;
|
|
3087
|
+
setSuggestions(null); setSelectedSuggestions([]); setSuggestionUndo([]);
|
|
3088
|
+
}
|
|
3089
|
+
|
|
2828
3090
|
function cancel() {
|
|
2829
3091
|
if (abortRef.current) {
|
|
2830
3092
|
abortRef.current.abort();
|
|
@@ -2866,7 +3128,8 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2866
3128
|
event.target.value = '';
|
|
2867
3129
|
if (!file) return;
|
|
2868
3130
|
file.text().then(function (raw) {
|
|
2869
|
-
var parsed
|
|
3131
|
+
var parsed;
|
|
3132
|
+
try { parsed = JSON.parse(raw); } catch (_) { throw new Error('文件不是有效 JSON,请检查格式后重新导入'); }
|
|
2870
3133
|
return promptRequest('import', { config: parsed });
|
|
2871
3134
|
}).then(function (data) {
|
|
2872
3135
|
publishConfig(data);
|
|
@@ -2892,11 +3155,14 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2892
3155
|
}
|
|
2893
3156
|
}
|
|
2894
3157
|
|
|
2895
|
-
function resetConfig() {
|
|
2896
|
-
if (
|
|
2897
|
-
|
|
3158
|
+
function resetConfig(scope) {
|
|
3159
|
+
if (scope === 'instructions' && !supportsResetInstructions) { setNote('当前后端不支持仅恢复指令,请更新后重新载入'); return; }
|
|
3160
|
+
var question = scope === 'instructions' ? '仅恢复 Iris 内置系统指令和全部用途模板?模型路由、生成参数和入口开关保持不变。'
|
|
3161
|
+
: '恢复全部 Iris 提示词设置?系统指令、全部用途模板、模型路由、生成参数与预算、入口开关都会重置;模型路由恢复为当前会话,入口重新启用。';
|
|
3162
|
+
if (!window.confirm(question)) return;
|
|
3163
|
+
promptRequest('reset', { scope: scope }).then(function (data) {
|
|
2898
3164
|
publishConfig(data);
|
|
2899
|
-
setNote('
|
|
3165
|
+
setNote(scope === 'instructions' ? '已恢复默认指令;模型路由、生成参数与入口开关保持不变' : '已恢复全部 Iris 提示词设置');
|
|
2900
3166
|
}).catch(function (err) {
|
|
2901
3167
|
setNote('重置失败:' + String(err && err.message || err));
|
|
2902
3168
|
});
|
|
@@ -2922,6 +3188,11 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2922
3188
|
var reasoningLabel = reasoningSetting === 'off-if-supported' ? '支持时关闭' : reasoningSetting === 'provider-default' ? '供应商默认' : reasoningSetting === 'inherit' ? '跟随会话' : reasoningSetting;
|
|
2923
3189
|
var outputBudget = configState && configState.config && configState.config.generation && configState.config.generation.maxOutputTokens || 1200;
|
|
2924
3190
|
var changes = result ? promptChanges(result.original, edited) : null;
|
|
3191
|
+
var targetInfo = PROMPT_TARGET_OPTIONS.find(function (item) { return item.value === target; }) || PROMPT_TARGET_OPTIONS[0];
|
|
3192
|
+
var resultTarget = result && PROMPT_TARGET_OPTIONS.find(function (item) { return item.value === result.target; });
|
|
3193
|
+
var config = configState && configState.config;
|
|
3194
|
+
var targetTemplate = config && config.targets && config.targets[target];
|
|
3195
|
+
var requestConfigFeedback = result && promptConfigFeedback({ feedback: result.configFeedback });
|
|
2925
3196
|
function ruleField(label, value, update, placeholder) {
|
|
2926
3197
|
return React.createElement('label', { className: 'iris-po-field' }, React.createElement('span', {}, label),
|
|
2927
3198
|
React.createElement('textarea', { value: value, disabled: busy || !supportsRules, placeholder: placeholder,
|
|
@@ -2931,20 +3202,44 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2931
3202
|
var panel = null;
|
|
2932
3203
|
if (open) {
|
|
2933
3204
|
panel = React.createElement(React.Fragment, {},
|
|
2934
|
-
React.createElement('
|
|
2935
|
-
|
|
3205
|
+
React.createElement('dialog', { ref: panelRef, tabIndex: -1, className: 'iris-po-panel', role: 'dialog', 'aria-modal': 'true', 'aria-label': 'Iris 提示词优化',
|
|
3206
|
+
onCancel: function (event) { event.preventDefault(); closePanel(); },
|
|
3207
|
+
onClick: function (event) {
|
|
3208
|
+
event.stopPropagation();
|
|
3209
|
+
if (event.target !== event.currentTarget) return;
|
|
3210
|
+
var bounds = event.currentTarget.getBoundingClientRect();
|
|
3211
|
+
if (event.clientX < bounds.left || event.clientX > bounds.right || event.clientY < bounds.top || event.clientY > bounds.bottom) closePanel();
|
|
3212
|
+
} },
|
|
2936
3213
|
React.createElement('div', { className: 'iris-po-head' },
|
|
2937
3214
|
React.createElement('strong', { className: 'iris-po-title' }, React.createElement('span', { className: 'iris-po-mark' }, '🫧'), 'Iris 提示词优化'),
|
|
2938
|
-
React.createElement('button', { className: 'iris-po-close', onClick: closePanel, title: '关闭' }, '✕')),
|
|
2939
|
-
React.createElement('div', { className: 'iris-po-
|
|
2940
|
-
React.createElement('
|
|
2941
|
-
|
|
2942
|
-
React.createElement('
|
|
2943
|
-
React.createElement('
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
3215
|
+
React.createElement('button', { className: 'iris-po-close', onClick: closePanel, title: '关闭', 'aria-label': '关闭提示词优化' }, '✕')),
|
|
3216
|
+
React.createElement('div', { className: 'iris-po-intro' },
|
|
3217
|
+
React.createElement('div', { className: 'iris-po-muted' }, '按用途整理草稿,先预览和编辑,再决定是否写回。'),
|
|
3218
|
+
promptConfigFeedback(configState),
|
|
3219
|
+
React.createElement('div', { className: 'iris-po-principles' },
|
|
3220
|
+
React.createElement('span', {}, '保留原意'), React.createElement('span', {}, '可查看改动'), React.createElement('span', {}, '确认后写回'))),
|
|
3221
|
+
React.createElement('details', { className: 'iris-po-section', open: generalOpen,
|
|
3222
|
+
onToggle: function (event) { generalPair[1](event.currentTarget.open); } },
|
|
3223
|
+
React.createElement('summary', {}, '一般功能',
|
|
3224
|
+
React.createElement('span', { className: 'iris-po-section-caption' }, targetInfo.label + ' · 提示词优化' + (result ? ' · 有预览' : ''))),
|
|
3225
|
+
React.createElement('div', { className: 'iris-po-section-body' },
|
|
3226
|
+
React.createElement('div', { className: 'iris-po-targets', role: 'group', 'aria-label': '优化目标' },
|
|
3227
|
+
PROMPT_TARGET_OPTIONS.map(function (item) {
|
|
3228
|
+
return React.createElement('button', { key: item.value, type: 'button', className: 'iris-po-target',
|
|
3229
|
+
'aria-pressed': target === item.value, value: item.value,
|
|
3230
|
+
disabled: busy || !supportsTarget(item.value), title: supportsTarget(item.value) ? item.description : '当前后端未提供此目标',
|
|
3231
|
+
onClick: function () { setTarget(item.value); } }, item.label);
|
|
3232
|
+
})),
|
|
3233
|
+
React.createElement('div', { className: 'iris-po-muted' }, targetInfo.description),
|
|
3234
|
+
supportsFaithful ? React.createElement('div', { className: 'iris-po-editing', role: 'group', 'aria-label': '编辑方式' },
|
|
3235
|
+
['faithful', 'rewrite'].map(function (strategy) {
|
|
3236
|
+
return React.createElement('label', { key: strategy }, React.createElement('input', { type: 'radio', name: 'iris-prompt-editing',
|
|
3237
|
+
value: strategy, checked: editing === strategy, disabled: busy, onChange: function () { editingPair[1](strategy); } }), strategy === 'faithful' ? '忠实整理(默认)' : '改写表达');
|
|
3238
|
+
}),
|
|
3239
|
+
React.createElement('div', { className: 'iris-po-muted' }, editing === 'faithful' ? '保持原文和句序,只调整分组与分段;不补充细节。' : '按本次规则改写,结果需逐项核对;未授权内容保持原意。')) : null,
|
|
3240
|
+
React.createElement('div', { className: 'iris-po-source' },
|
|
3241
|
+
React.createElement('div', { className: 'iris-po-source-head' }, '当前草稿', React.createElement('span', {}, (draft || '').length + ' 字符')),
|
|
3242
|
+
React.createElement('p', { className: 'iris-po-source-text' }, draft || '先在对话输入框写下你的想法。')),
|
|
2948
3243
|
React.createElement('details', { className: 'iris-po-config' },
|
|
2949
3244
|
React.createElement('summary', {}, '本次规则(可选)'),
|
|
2950
3245
|
React.createElement('div', { className: 'iris-po-rules' },
|
|
@@ -2953,12 +3248,35 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2953
3248
|
ruleField('输出后缀 · 原样加入结果末尾', suffixText, setSuffixText, '例如:禁止添加文字和水印。')),
|
|
2954
3249
|
React.createElement('div', { className: 'iris-po-muted' }, supportsRules ? '非空内容表示本次选择;只组装保留原稿,只添加前后缀。刷新后重置,不修改 JSON 配置。' : '当前后端尚未支持规则,请更新后重新载入。')),
|
|
2955
3250
|
React.createElement('div', { className: 'iris-po-actions' },
|
|
2956
|
-
React.createElement('button', { className: 'iris-po-primary', disabled: busy || !draft || !draft.trim() || phase !== 'plain' || refCount > 0, onClick: function () { optimize('optimize'); } }, busy ? '处理中…' : '智能优化'),
|
|
3251
|
+
React.createElement('button', { className: 'iris-po-primary', disabled: busy || !draft || !draft.trim() || phase !== 'plain' || refCount > 0, onClick: function () { optimize('optimize'); } }, busy ? '处理中…' : supportsFaithful ? editing === 'faithful' ? '忠实整理' : '改写表达' : '智能优化'),
|
|
2957
3252
|
React.createElement('button', { className: 'iris-po-btn', disabled: busy || !supportsAssembly || !draft || !draft.trim() || phase !== 'plain' || refCount > 0, onClick: function () { optimize('assemble'); } }, '只组装(不调用模型)'),
|
|
2958
3253
|
busy ? React.createElement('button', { className: 'iris-po-btn', onClick: cancel }, '取消') : null),
|
|
3254
|
+
React.createElement('div', { className: 'iris-po-muted' }, supportsLocalFaithful
|
|
3255
|
+
? '单片段忠实整理与只组装不调用模型;其他优化及获取建议可能产生模型费用。'
|
|
3256
|
+
: '智能优化调用文本模型,可能产生费用;只组装原稿与前后缀。'),
|
|
2959
3257
|
result ? React.createElement('div', { className: 'iris-po-result' },
|
|
2960
|
-
React.createElement('div', { className: 'iris-po-result-label' }, '结果预览 · 可编辑'),
|
|
2961
|
-
React.createElement('textarea', { 'aria-label': '结果预览', value: edited, onChange: function (event) {
|
|
3258
|
+
React.createElement('div', { className: 'iris-po-result-label' }, '结果预览 · ' + (resultTarget ? resultTarget.label + ' · ' : '') + '可编辑 · ' + edited.length + ' 字符'),
|
|
3259
|
+
React.createElement('textarea', { 'aria-label': '结果预览', value: edited, onChange: function (event) { editPreview(event.target.value); } }),
|
|
3260
|
+
result.editing?.strategy === 'faithful' ? React.createElement('div', { className: 'iris-po-muted' }, '本次整理保留了全部原文片段与句序;手动编辑或采纳建议后,请重新核对内容。') : null,
|
|
3261
|
+
supportsSuggestions ? React.createElement('details', { className: 'iris-po-config' },
|
|
3262
|
+
React.createElement('summary', {}, '可选补充与待确认'),
|
|
3263
|
+
React.createElement('div', { className: 'iris-po-muted' }, '建议独立生成,默认未采纳;不会自动加入正文或写回。每次获取会调用文本模型。'),
|
|
3264
|
+
React.createElement('button', { className: 'iris-po-btn', disabled: busy || !edited.trim(), onClick: requestSuggestions }, '获取补充建议'),
|
|
3265
|
+
suggestions ? React.createElement('div', {},
|
|
3266
|
+
suggestions.items.map(function (item) {
|
|
3267
|
+
var adopted = suggestions.adopted.indexOf(item.id) >= 0;
|
|
3268
|
+
return React.createElement('div', { className: 'iris-po-suggestion', key: item.id },
|
|
3269
|
+
React.createElement('label', {}, React.createElement('input', { type: 'checkbox', checked: adopted || selectedSuggestions.indexOf(item.id) >= 0, disabled: busy || adopted,
|
|
3270
|
+
onChange: function (event) { setSelectedSuggestions(event.target.checked ? selectedSuggestions.concat([item.id]) : selectedSuggestions.filter(function (id) { return id !== item.id; })); } }), item.label + (adopted ? ' · 已加入预览' : '')),
|
|
3271
|
+
React.createElement('p', {}, item.text));
|
|
3272
|
+
}),
|
|
3273
|
+
!suggestions.items.length ? React.createElement('div', { className: 'iris-po-muted' }, '没有额外补充建议。') : null,
|
|
3274
|
+
suggestions.questions.length ? React.createElement('div', { className: 'iris-po-suggestion' }, React.createElement('strong', {}, '待确认 · 尚未作为要求'),
|
|
3275
|
+
suggestions.questions.map(function (question, index) { return React.createElement('p', { key: index }, question); })) : null,
|
|
3276
|
+
promptRequestSnapshot(suggestions.processing, '本次建议完整指令'),
|
|
3277
|
+
React.createElement('div', { className: 'iris-po-actions' },
|
|
3278
|
+
React.createElement('button', { className: 'iris-po-btn', disabled: busy || !selectedSuggestions.length, onClick: adoptSuggestions }, '采纳所选建议'),
|
|
3279
|
+
React.createElement('button', { className: 'iris-po-btn', disabled: busy || !suggestionUndo.length, onClick: undoSuggestions }, '撤回上次采纳'))) : null) : null,
|
|
2962
3280
|
React.createElement('details', { className: 'iris-po-config' }, React.createElement('summary', {}, '原文与改动'),
|
|
2963
3281
|
React.createElement('textarea', { 'aria-label': '优化前原文', readOnly: true, value: result.original }),
|
|
2964
3282
|
React.createElement('div', { className: 'iris-po-muted' }, '以下折叠相同首尾,显示中间替换区:'),
|
|
@@ -2971,20 +3289,33 @@ window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) =>
|
|
|
2971
3289
|
return React.createElement('div', { className: 'iris-po-diff', key: rule.id }, rule.label + '(' + (rule.kind === 'optimization' ? '指导改写' : rule.position === 'prefix' ? '输出前缀' : '输出后缀') + ')\n' + rule.text);
|
|
2972
3290
|
}) : React.createElement('div', { className: 'iris-po-muted' }, '未选择额外规则'),
|
|
2973
3291
|
result.processing ? React.createElement('div', { className: 'iris-po-diff' }, '优化处理规则:\n' + result.processing.systemPrompt + '\n\n目标模板:\n' + result.processing.targetTemplate) : null),
|
|
2974
|
-
|
|
3292
|
+
promptRequestSnapshot(result.processing, '本次正文处理完整指令'),
|
|
3293
|
+
React.createElement('div', { className: 'iris-po-route' }, result.route ? '实际使用:' + result.route.provider + ' / ' + result.route.model + ' · 思考:' + (result.route.reasoningEffort === 'provider-default' ? '供应商默认' : result.route.reasoningEffort)
|
|
3294
|
+
: result.execution?.reason === 'single-part-faithful' && result.execution.modelInvocations === 0 ? '忠实整理:无需分段,未调用模型'
|
|
3295
|
+
: result.mode === 'assemble' ? '本次只组装,未调用模型' : '未提供模型调用信息'),
|
|
3296
|
+
result.route && result.route.reason ? React.createElement('div', { className: 'iris-po-muted' }, '选择原因:' + result.route.reason + ' · ' + (result.route.textInput === 'supported' ? '宿主声明支持文本输入' : '文本输入能力未知')) : null,
|
|
3297
|
+
requestConfigFeedback ? React.createElement('details', { className: 'iris-po-config' },
|
|
3298
|
+
React.createElement('summary', {}, '本次请求的配置反馈'), requestConfigFeedback) : null,
|
|
2975
3299
|
React.createElement('div', { className: 'iris-po-actions' },
|
|
2976
3300
|
React.createElement('button', { className: 'iris-po-primary', onClick: function () { replaceDraft(edited); } }, '写回输入框'),
|
|
2977
3301
|
React.createElement('button', { className: 'iris-po-btn', onClick: copyResult }, '复制'),
|
|
2978
3302
|
React.createElement('button', { className: 'iris-po-btn', disabled: busy, onClick: function () { optimize(result.mode); } }, '重新生成预览'),
|
|
2979
3303
|
React.createElement('button', { className: 'iris-po-btn', onClick: function () { replaceDraft(result.original); } }, '恢复原文'))) : null,
|
|
2980
|
-
note ? React.createElement('div', { className: 'iris-po-note' }, note) : null,
|
|
3304
|
+
note ? React.createElement('div', { className: 'iris-po-note', role: 'status' }, note) : null)),
|
|
2981
3305
|
React.createElement('details', { className: 'iris-po-config' },
|
|
2982
|
-
React.createElement('summary', {}, '
|
|
2983
|
-
React.createElement('div', { className: 'iris-po-
|
|
3306
|
+
React.createElement('summary', {}, '指令与模型设置'),
|
|
3307
|
+
React.createElement('div', { className: 'iris-po-route', title: routeLabel }, '模型:' + routeLabel + ' · 思考:' + reasoningLabel + ' · 输出:' + outputBudget + ' tokens'),
|
|
3308
|
+
React.createElement('details', {}, React.createElement('summary', {}, '查看当前功能的优化指令'),
|
|
3309
|
+
React.createElement('div', { className: 'iris-po-template' }, config && config.systemPrompt || '配置尚未载入'),
|
|
3310
|
+
React.createElement('div', { className: 'iris-po-template' }, targetTemplate || '当前后端未提供此目标模板')),
|
|
3311
|
+
React.createElement('div', { className: 'iris-po-result-label' }, 'JSON 配置'),
|
|
3312
|
+
React.createElement('div', { className: 'iris-po-muted' }, '导入会替换当前配置;局部 JSON 缺少的字段使用内置默认值。可导出后修改 systemPrompt、targets、route 和 generation,再重新导入。'),
|
|
2984
3313
|
React.createElement('div', { className: 'iris-po-actions' },
|
|
2985
3314
|
React.createElement('button', { className: 'iris-po-btn', onClick: exportConfig }, '导出'),
|
|
2986
|
-
React.createElement('button', { className: 'iris-po-btn', onClick: function () { if (fileRef.current) fileRef.current.click(); } }, '导入'),
|
|
2987
|
-
React.createElement('button', { className: 'iris-po-btn
|
|
3315
|
+
React.createElement('button', { className: 'iris-po-btn', disabled: busy, onClick: function () { if (fileRef.current) fileRef.current.click(); } }, '导入'),
|
|
3316
|
+
React.createElement('button', { className: 'iris-po-btn', disabled: busy || !supportsResetInstructions,
|
|
3317
|
+
title: supportsResetInstructions ? '只更新系统指令与全部用途模板' : '当前后端尚未支持仅恢复指令', onClick: function () { resetConfig('instructions'); } }, '仅恢复默认指令'),
|
|
3318
|
+
React.createElement('button', { className: 'iris-po-btn danger', disabled: busy, onClick: function () { resetConfig('all'); } }, '恢复全部设置'),
|
|
2988
3319
|
React.createElement('input', { ref: fileRef, className: 'iris-po-file', type: 'file', accept: 'application/json,.json', onChange: importConfig })),
|
|
2989
3320
|
React.createElement('div', { className: 'iris-po-muted' }, '当前:' + (configState && configState.source === 'custom' ? '用户 JSON' : 'Iris 默认'))),
|
|
2990
3321
|
React.createElement('button', { className: 'iris-po-disable', disabled: busy, onClick: disableEntry }, '关闭此对话入口(工作台仍保留)')));
|