@mokuyoaxis/dsh-iris 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +72 -1
- package/README.en.md +245 -0
- package/README.md +81 -13
- package/cordis.patch.yml +1 -1
- package/docs/ROADMAP.md +49 -21
- package/docs/assets/diagrams/iris-architecture.drawio +1 -0
- package/docs/assets/diagrams/iris-architecture.png +0 -0
- package/docs/assets/diagrams/iris-architecture.svg +63 -0
- package/docs/assets/diagrams/iris-task-lifecycle.drawio +1 -0
- package/docs/assets/diagrams/iris-task-lifecycle.png +0 -0
- package/docs/assets/diagrams/iris-task-lifecycle.svg +64 -0
- package/docs/assets/diagrams/iris-workflow-compose.drawio +1 -0
- package/docs/assets/diagrams/iris-workflow-compose.png +0 -0
- package/docs/assets/diagrams/iris-workflow-compose.svg +41 -0
- package/docs/assets/examples/iris-flower-generated.webp +0 -0
- package/docs/assets/screenshots/image-task-succeeded.webp +0 -0
- package/docs/assets/screenshots/prompt-general-after.webp +0 -0
- package/docs/assets/screenshots/prompt-general-before.webp +0 -0
- package/docs/assets/screenshots/prompt-general-preview.webp +0 -0
- package/docs/assets/screenshots/prompt-image-before.webp +0 -0
- package/docs/assets/screenshots/prompt-image-preview.webp +0 -0
- package/docs/releases/0.1.1.md +51 -0
- package/docs/releases/0.1.2.md +26 -0
- package/docs/screenshots.md +34 -0
- package/lib/actions.js +33 -27
- package/lib/adapters.js +42 -26
- package/lib/api.js +73 -20
- package/lib/bundled-skills.js +62 -0
- package/lib/capability.js +1 -1
- package/lib/client.js +378 -26
- package/lib/config.js +56 -22
- package/lib/guard.js +37 -24
- package/lib/index.js +21 -9
- package/lib/locate.js +1 -1
- package/lib/media-probe.js +4 -4
- package/lib/media.js +1 -1
- package/lib/private-storage.js +77 -0
- package/lib/prompt-optimizer-config.js +170 -0
- package/lib/prompt-optimizer.js +244 -0
- package/lib/provider-protocol.js +25 -0
- package/lib/render.js +3 -2
- package/lib/tasks.js +21 -13
- package/lib/vision.js +2 -2
- package/package.json +25 -17
- package/screenshots.json +6 -0
- package/user_guide.md +97 -11
package/lib/client.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* webServer 前缀模式),client 侧 fetch 轮询。全走标量,
|
|
17
17
|
* apiKey 永不明文,产物给授权播放链接。
|
|
18
18
|
*/
|
|
19
|
-
window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
19
|
+
window.__ModuleLoader__.load({ id: '@mokuyoaxis/dsh-iris', factory: (require) => {
|
|
20
20
|
var module = { exports: {} };
|
|
21
21
|
var exports = module.exports;
|
|
22
22
|
|
|
@@ -111,7 +111,7 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
111
111
|
'.iris-bubble.lit .iris-bubble-btn { border-color: var(--dsw-alias-state-success-primary, #6fcf6f); box-shadow: 0 0 14px var(--dsw-alias-state-success-primary, #6fcf6f); }',
|
|
112
112
|
'.iris-bubble.dim .iris-bubble-btn { opacity: 0.55; border-color: var(--dsw-alias-border-l1, #3a3a44); }',
|
|
113
113
|
'.iris-bubble-badge { position: absolute; top: -2px; right: -2px; min-width: 16px; height: 16px; border-radius: 8px; background: var(--dsw-alias-state-warn-primary, #d9a941); color: #1a1a1e; font-size: 10px; font-weight: 700; display: flex; align-items: center; justify-content: center; padding: 0 3px; }',
|
|
114
|
-
'.iris-bubble-panel { position: fixed; z-index: 9998; width: 360px; max-height: min(520px, 70vh); overflow: auto; background: var(--dsw-alias-bg-layer-1, #26262e); border: 1px solid var(--dsw-alias-border-l1, #3a3a44); border-radius: 12px; padding: 12px 14px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45); }',
|
|
114
|
+
'.iris-bubble-panel { position: fixed; z-index: 9998; width: 360px; max-height: min(520px, 70vh); overflow: auto; background: var(--dsw-alias-bg-layer-1, #26262e); border: 1px solid var(--dsw-alias-border-l1, #3a3a44); border-radius: 12px; padding: 12px 14px; font-size: 12px; line-height: 1.45; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45); }',
|
|
115
115
|
'.iris-bubble-panel-head { position: absolute; top: 6px; right: 6px; z-index: 2; }',
|
|
116
116
|
'.iris-bubble-close { border: none; background: transparent; color: var(--dsw-alias-label-secondary, #9a9a9a); font-size: 14px; cursor: pointer; padding: 4px 6px; }',
|
|
117
117
|
'.iris-bubble-close:hover { color: var(--dsw-alias-label-primary, #e6e6e6); }',
|
|
@@ -160,7 +160,48 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
160
160
|
'.iris-ff-list { display: grid; gap: 2px; max-height: 160px; overflow: auto; border: 1px solid var(--dsw-alias-border-l1, #3a3a44); border-radius: 6px; padding: 4px; background: var(--dsw-alias-bg-layer-2, #32323c); }',
|
|
161
161
|
'.iris-ff-item { display: flex; align-items: center; gap: 6px; font-size: 11px; cursor: pointer; padding: 2px 4px; border-radius: 4px; }',
|
|
162
162
|
'.iris-ff-item:hover { background: var(--dsw-alias-bg-layer-1, #26262e); }',
|
|
163
|
-
'.iris-ff-item .iris-ff-src { color: var(--dsw-alias-brand-primary, #7aa2f7); font-size: 10px; }'
|
|
163
|
+
'.iris-ff-item .iris-ff-src { color: var(--dsw-alias-brand-primary, #7aa2f7); font-size: 10px; }',
|
|
164
|
+
/* 对话框级提示词优化器:桌面浮层 + 窄屏底部 Sheet */
|
|
165
|
+
'.iris-po-wrap { position: relative; display: inline-flex; flex: 0 0 auto; }',
|
|
166
|
+
'.iris-po-trigger { appearance: none; -webkit-appearance: none; width: 30px; height: 30px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 0; outline: 0; background: transparent; color: inherit; font-size: 19px; line-height: 1; cursor: pointer; box-shadow: none; filter: drop-shadow(0 3px 7px rgba(91,113,220,.22)); transition: transform .18s ease, filter .18s ease, opacity .18s ease; }',
|
|
167
|
+
'.iris-po-trigger:hover { transform: translateY(-2px) scale(1.10); filter: drop-shadow(0 5px 10px rgba(112,137,255,.42)); }',
|
|
168
|
+
'.iris-po-trigger:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary, #7aa2f7); outline-offset: 2px; }',
|
|
169
|
+
'.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; }',
|
|
170
|
+
'.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(440px, calc(100vw - 28px)); max-height: min(680px, 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: 13px; background-color: rgba(35,36,47,.84); background: radial-gradient(circle at 10% -5%, rgba(132,160,255,.24), transparent 42%), color-mix(in srgb, var(--dsw-alias-bg-layer-1, #26262e) 82%, transparent); color: var(--dsw-alias-label-primary, #eeeeF2); border: 1px solid rgba(150,164,215,.25); border-radius: 20px; box-shadow: 0 24px 70px rgba(0,0,0,.48), 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; }',
|
|
171
|
+
'.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); }',
|
|
172
|
+
'.iris-po-title { display: inline-flex; align-items: center; gap: 9px; font-size: 14px; letter-spacing: .01em; }',
|
|
173
|
+
'.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)); }',
|
|
174
|
+
'.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; }',
|
|
175
|
+
'.iris-po-close:hover { background: rgba(255,255,255,.10); color: var(--dsw-alias-label-primary, #eeeef2); }',
|
|
176
|
+
'.iris-po-muted, .iris-po-route, .iris-po-note { font-size: 11px; line-height: 1.55; color: var(--dsw-alias-label-secondary, #a6a6b2); word-break: break-word; }',
|
|
177
|
+
'.iris-po-route { padding: 7px 10px; border-radius: 10px; background: rgba(255,255,255,.045); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }',
|
|
178
|
+
'.iris-po-note { padding: 8px 10px; border-radius: 10px; color: var(--dsw-alias-state-warn-primary, #dfbd69); background: rgba(217,169,65,.08); }',
|
|
179
|
+
'.iris-po-field { display: grid; gap: 6px; font-size: 11px; color: var(--dsw-alias-label-secondary, #a6a6b2); }',
|
|
180
|
+
'.iris-po-field select, .iris-po-result textarea { width: 100%; box-sizing: border-box; background: rgba(255,255,255,.055); color: var(--dsw-alias-label-primary, #eeeef2); border: 1px solid rgba(150,164,215,.20); border-radius: 11px; padding: 9px 11px; font: inherit; font-size: 12px; outline: none; transition: border-color .15s, background .15s, box-shadow .15s; }',
|
|
181
|
+
'.iris-po-field select: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); }',
|
|
182
|
+
'.iris-po-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }',
|
|
183
|
+
'.iris-po-btn, .iris-po-primary { min-height: 34px; border: 1px solid rgba(150,164,215,.20); border-radius: 10px; padding: 6px 11px; font: inherit; font-size: 11px; cursor: pointer; transition: transform .15s, background .15s, border-color .15s; }',
|
|
184
|
+
'.iris-po-btn { background: rgba(255,255,255,.045); color: var(--dsw-alias-label-secondary, #b0b0bb); }',
|
|
185
|
+
'.iris-po-btn:hover { background: rgba(255,255,255,.085); color: var(--dsw-alias-label-primary, #eeeef2); border-color: rgba(150,174,255,.50); }',
|
|
186
|
+
'.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); }',
|
|
187
|
+
'.iris-po-primary:hover { transform: translateY(-1px); box-shadow: 0 8px 22px rgba(76,92,188,.32); }',
|
|
188
|
+
'.iris-po-primary:disabled, .iris-po-btn:disabled { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }',
|
|
189
|
+
'.iris-po-result { display: grid; gap: 8px; padding: 12px; border: 1px solid rgba(137,155,218,.18); border-radius: 15px; background: rgba(10,12,20,.16); }',
|
|
190
|
+
'.iris-po-result-label { font-size: 11px; font-weight: 650; letter-spacing: .02em; }',
|
|
191
|
+
'.iris-po-result textarea { min-height: 156px; max-height: 34dvh; resize: vertical; line-height: 1.58; }',
|
|
192
|
+
'.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; }',
|
|
193
|
+
'.iris-po-config summary { cursor: pointer; color: var(--dsw-alias-label-secondary, #a6a6b2); }',
|
|
194
|
+
'.iris-po-config[open] summary { margin-bottom: 9px; color: var(--dsw-alias-label-primary, #eeeef2); }',
|
|
195
|
+
'.iris-po-config .iris-po-actions { margin: 9px 0; }',
|
|
196
|
+
'.iris-po-btn.danger:hover { color: var(--dsw-alias-state-error-primary, #eb7d86); border-color: rgba(235,125,134,.55); background: rgba(235,125,134,.08); }',
|
|
197
|
+
'.iris-po-file { display: none; }',
|
|
198
|
+
'.iris-po-disable { justify-self: start; border: 0; padding: 2px 0; background: transparent; color: var(--dsw-alias-label-tertiary, #777986); font: inherit; font-size: 10px; cursor: pointer; }',
|
|
199
|
+
'.iris-po-disable:hover { color: var(--dsw-alias-state-error-primary, #eb7d86); }',
|
|
200
|
+
'@keyframes iris-po-fade { from { opacity: 0; } to { opacity: 1; } }',
|
|
201
|
+
'@keyframes iris-po-rise { from { opacity: 0; transform: translateY(12px) scale(.985); } to { opacity: 1; transform: translateY(0) scale(1); } }',
|
|
202
|
+
'@media (max-width: 640px) { .iris-po-backdrop { background: rgba(6,8,14,.48); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); } .iris-po-panel { left: max(8px, env(safe-area-inset-left)); right: max(8px, env(safe-area-inset-right)); bottom: max(8px, env(safe-area-inset-bottom)); width: auto; max-height: calc(100dvh - max(16px, env(safe-area-inset-top))); padding: 16px; gap: 11px; border-radius: 22px; } .iris-po-head { top: -16px; margin: -16px -16px 0; padding: 14px 16px 10px; } .iris-po-btn, .iris-po-primary { min-height: 42px; flex: 1 1 auto; } .iris-po-actions .iris-po-primary:first-child { flex-basis: 100%; } .iris-po-result textarea { min-height: 122px; max-height: 28dvh; resize: none; } .iris-po-route { white-space: normal; } }',
|
|
203
|
+
'@media (max-width: 360px) { .iris-po-panel { left: 4px; right: 4px; bottom: max(4px, env(safe-area-inset-bottom)); padding: 13px; border-radius: 18px; } .iris-po-head { top: -13px; margin: -13px -13px 0; padding: 12px 13px 8px; } .iris-po-actions { gap: 6px; } }',
|
|
204
|
+
'@media (prefers-reduced-motion: reduce) { .iris-po-panel, .iris-po-backdrop { animation: none; } .iris-po-trigger, .iris-po-btn, .iris-po-primary { transition: none; } }',
|
|
164
205
|
].join('\n');
|
|
165
206
|
|
|
166
207
|
function adoptStyles() {
|
|
@@ -250,6 +291,15 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
250
291
|
return sharedState;
|
|
251
292
|
}
|
|
252
293
|
|
|
294
|
+
/** 功能卡就绪态直接来自共享 Iris 状态,不再等用户点开卡片后才加载。 */
|
|
295
|
+
function capabilityReady(state, capability) {
|
|
296
|
+
if (!capability) return true;
|
|
297
|
+
var providers = (state && state.providers) || [];
|
|
298
|
+
return providers.some(function (p) {
|
|
299
|
+
return p.enabled && p.apiKeyHint && Array.isArray(p.capabilities) && p.capabilities.indexOf(capability) >= 0;
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
253
303
|
/* ---- 任务详情抽屉:按需拉取 /iris/api/task/:id ---- */
|
|
254
304
|
function useTaskDetail(taskId) {
|
|
255
305
|
var pair = React.useState(null);
|
|
@@ -438,15 +488,15 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
438
488
|
var models = p.models || [];
|
|
439
489
|
function verBadge(m, c) {
|
|
440
490
|
var v = m.verified && m.verified[c];
|
|
441
|
-
|
|
442
|
-
|
|
491
|
+
var cls = 'iris-pm-ver' + (v ? (' ' + (v.ok ? 'ok' : 'bad')) : '');
|
|
492
|
+
var title = v ? ((v.ok ? '实测通过:' : '实测未通过:') + (v.note || '')) : '点击单独验证此能力';
|
|
493
|
+
return React.createElement('button', { key: c, className: cls, title: title, onClick: function () { props.testModel(p, m, c); } }, c + (v ? (v.ok ? '✓' : '✗') : '?'));
|
|
443
494
|
}
|
|
444
495
|
var rows = models.map(function (m) {
|
|
445
496
|
var caps = m.capabilities || [];
|
|
446
497
|
return React.createElement('div', { key: m.id, className: 'iris-pm-mrow' },
|
|
447
498
|
React.createElement('span', { className: 'iris-pm-mname' }, m.id, m.source === 'manual' ? React.createElement('span', { className: 'iris-pm-mtag' }, '手动') : null),
|
|
448
499
|
React.createElement('span', { className: 'iris-pm-mcaps' }, caps.map(function (c) { return verBadge(m, c); })),
|
|
449
|
-
React.createElement('button', { className: 'iris-pm-btn', title: '逐能力实测(image/tts 产生真实调用)', onClick: function () { props.testModel(p, m); } }, '测'),
|
|
450
500
|
React.createElement('button', { className: 'iris-pm-btn danger', title: '从池移除', onClick: function () { props.removeModel(p, m); } }, '✕'));
|
|
451
501
|
});
|
|
452
502
|
return React.createElement('div', { className: 'iris-pm-pool' },
|
|
@@ -466,7 +516,7 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
466
516
|
var addingPair = React.useState(false);
|
|
467
517
|
var adding = addingPair[0];
|
|
468
518
|
var setAdding = addingPair[1];
|
|
469
|
-
var newForm = React.useState({ name: '', baseUrl: '', apiKey: '', type: 'openai' });
|
|
519
|
+
var newForm = React.useState({ name: '', baseUrl: '', apiKey: '', type: 'openai', mediaProtocol: 'auto' });
|
|
470
520
|
var notePair = React.useState('');
|
|
471
521
|
var note = notePair[0];
|
|
472
522
|
var setNote = notePair[1];
|
|
@@ -493,23 +543,25 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
493
543
|
postAction('providers_remove', { id: p.id }).then(function (r) { if (r.ok) refresh(); else setNote(r.d.error || '删除失败'); });
|
|
494
544
|
}
|
|
495
545
|
function testVision(p) {
|
|
546
|
+
if (!window.confirm('视觉实测会向供应商发送一张内置测试图,可能产生费用。继续吗?')) return;
|
|
496
547
|
setNote('测试「' + (p.name || p.id) + '」的视觉能力…');
|
|
497
|
-
postAction('providers_test_vision', { id: p.id }).then(function (r) { setNote(r.d.text || r.d.error || '测试完成'); refresh(); });
|
|
548
|
+
postAction('providers_test_vision', { id: p.id, confirm_paid: true }).then(function (r) { setNote(r.d.text || r.d.error || '测试完成'); refresh(); });
|
|
498
549
|
}
|
|
499
550
|
function discover(p) {
|
|
500
551
|
setNote('正在发现「' + (p.name || p.id) + '」的模型…');
|
|
501
552
|
postAction('providers_discover', { id: p.id }).then(function (r) { setNote(r.d.text || r.d.error || '发现完成'); refresh(); });
|
|
502
553
|
}
|
|
503
|
-
function testModel(p, m) {
|
|
504
|
-
var
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
554
|
+
function testModel(p, m, capability) {
|
|
555
|
+
var noProbe = capability === 'video-gen' || capability === 'transcribe';
|
|
556
|
+
if (!noProbe && !window.confirm('将用模型「' + m.id + '」发起一次真实的 ' + capability + ' 请求,可能产生费用。继续吗?')) return;
|
|
557
|
+
setNote('验证 ' + m.id + ' · ' + capability + '…');
|
|
558
|
+
postAction('providers_test_model', { id: p.id, model_id: m.id, capability: capability, confirm_paid: !noProbe })
|
|
559
|
+
.then(function (r) { setNote(r.d.text || r.d.error || ''); refresh(); });
|
|
560
|
+
}
|
|
561
|
+
function setProtocol(p, value) {
|
|
562
|
+
postAction('providers_upsert', { id: p.id, mediaProtocol: value }).then(function (r) {
|
|
563
|
+
setNote(r.ok ? '媒体协议已更新' : (r.d.error || '更新失败')); refresh();
|
|
564
|
+
});
|
|
513
565
|
}
|
|
514
566
|
function removeModel(p, m) {
|
|
515
567
|
if (!window.confirm('从池中移除模型「' + m.id + '」?')) return;
|
|
@@ -525,6 +577,9 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
525
577
|
if (open) {
|
|
526
578
|
body = React.createElement('div', { className: 'iris-pm-body' },
|
|
527
579
|
React.createElement('div', { className: 'iris-pm-note' }, 'Key ' + (p.apiKeyHint || '未配置') + ' · ' + (p.type || '') + ' · ' + (p.mediaProtocol || '')),
|
|
580
|
+
React.createElement('div', { className: 'iris-pm-field' }, React.createElement('label', {}, '媒体协议'), React.createElement('select', { value: p.mediaProtocol || 'openai-images', onChange: function (e) { setProtocol(p, e.target.value); } },
|
|
581
|
+
React.createElement('option', { value: 'dashscope' }, 'DashScope(仅阿里云官方 HTTPS)'),
|
|
582
|
+
React.createElement('option', { value: 'openai-images' }, 'OpenAI Images 兼容'))),
|
|
528
583
|
React.createElement('div', { className: 'iris-pm-note' }, '能力: ' + ((p.capabilities || []).join(' / ') || '无')),
|
|
529
584
|
React.createElement(ModelPool, { provider: p, onNote: setNote, onDone: refresh, testModel: testModel, removeModel: removeModel, addModel: addModel }),
|
|
530
585
|
React.createElement('div', { className: 'iris-wb-row' },
|
|
@@ -544,6 +599,10 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
544
599
|
React.createElement('div', { className: 'iris-pm-field' }, React.createElement('label', {}, '名称'), React.createElement('input', { value: newForm[0].name, placeholder: '如 阿里云百炼', onChange: function (e) { newForm[1]({ ...newForm[0], name: e.target.value }); } })),
|
|
545
600
|
React.createElement('div', { className: 'iris-pm-field' }, React.createElement('label', {}, 'Base URL *'), React.createElement('input', { value: newForm[0].baseUrl, placeholder: 'https://dashscope.aliyuncs.com/compatible-mode/v1', onChange: function (e) { newForm[1]({ ...newForm[0], baseUrl: e.target.value }); } })),
|
|
546
601
|
React.createElement('div', { className: 'iris-pm-field' }, React.createElement('label', {}, 'API Key *'), React.createElement('input', { type: 'password', value: newForm[0].apiKey, placeholder: 'sk-...', onChange: function (e) { newForm[1]({ ...newForm[0], apiKey: e.target.value }); } })),
|
|
602
|
+
React.createElement('div', { className: 'iris-pm-field' }, React.createElement('label', {}, '媒体协议'), React.createElement('select', { value: newForm[0].mediaProtocol, onChange: function (e) { newForm[1]({ ...newForm[0], mediaProtocol: e.target.value }); } },
|
|
603
|
+
React.createElement('option', { value: 'auto' }, '自动(按 Base URL 安全判断)'),
|
|
604
|
+
React.createElement('option', { value: 'dashscope' }, 'DashScope(阿里云官方)'),
|
|
605
|
+
React.createElement('option', { value: 'openai-images' }, 'OpenAI Images 兼容'))),
|
|
547
606
|
React.createElement('div', { className: 'iris-wb-row' },
|
|
548
607
|
React.createElement('button', { className: 'iris-act-run', onClick: addProvider }, '保存'),
|
|
549
608
|
React.createElement('button', { className: 'iris-pm-btn', onClick: function () { setAdding(false); } }, '取消')));
|
|
@@ -641,6 +700,7 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
641
700
|
var modelPair = React.useState(null); // { assigned, options:[{id,providerId}], tested }
|
|
642
701
|
var modelInfo = modelPair[0];
|
|
643
702
|
var setModelInfo = modelPair[1];
|
|
703
|
+
var irisState = useIrisState(5000);
|
|
644
704
|
function setVal(key, value) { var nv = {}; Object.keys(vals).forEach(function (k) { nv[k] = vals[k]; }); nv[key] = value; setVals(nv); }
|
|
645
705
|
function loadModels() {
|
|
646
706
|
if (!capability) return;
|
|
@@ -720,11 +780,13 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
720
780
|
run === 'running' ? '执行中…' : '执行'),
|
|
721
781
|
result);
|
|
722
782
|
}
|
|
723
|
-
var
|
|
783
|
+
var headError = !!(run && run !== 'running' && run.ok === false);
|
|
784
|
+
var headLit = !capability || (capabilityReady(irisState, capability) && !headError);
|
|
785
|
+
var headTitle = headError ? '最近一次执行出错' : (headLit ? 'API 与能力已配置' : '缺少可用 API 或能力模型');
|
|
724
786
|
return React.createElement('div', { className: 'iris-act-card' + (open ? ' open' : '') + (headLit ? ' lit' : ' dim') },
|
|
725
787
|
React.createElement('div', { className: 'iris-act-head', onClick: function () { setOpen(!open); } },
|
|
726
788
|
React.createElement('span', { className: 'iris-act-title' }, title),
|
|
727
|
-
capability ? React.createElement('span', { className: headLit ? 'iris-pm-dot lit' : 'iris-pm-dot', title:
|
|
789
|
+
capability ? React.createElement('span', { className: headLit ? 'iris-pm-dot lit' : 'iris-pm-dot', title: headTitle }, '●') : null,
|
|
728
790
|
React.createElement('span', { className: 'iris-act-arrow' }, '▶')),
|
|
729
791
|
body);
|
|
730
792
|
}
|
|
@@ -948,6 +1010,53 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
948
1010
|
note ? React.createElement('div', { className: 'iris-clean-note', style: { width: '100%' } }, note) : null);
|
|
949
1011
|
}
|
|
950
1012
|
|
|
1013
|
+
function PromptOptimizerSettings() {
|
|
1014
|
+
var pair = React.useState(null);
|
|
1015
|
+
var state = pair[0];
|
|
1016
|
+
var setState = pair[1];
|
|
1017
|
+
var notePair = React.useState('');
|
|
1018
|
+
var note = notePair[0];
|
|
1019
|
+
var setNote = notePair[1];
|
|
1020
|
+
|
|
1021
|
+
function load() {
|
|
1022
|
+
fetch('/iris/api/prompt-optimizer/config')
|
|
1023
|
+
.then(function (res) { return res.ok ? res.json() : null; })
|
|
1024
|
+
.then(function (data) { if (data && data.config) setState(data); })
|
|
1025
|
+
.catch(function () { setNote('读取提示词优化配置失败'); });
|
|
1026
|
+
}
|
|
1027
|
+
React.useEffect(function () {
|
|
1028
|
+
function changed(event) { if (event.detail && event.detail.config) setState(event.detail); }
|
|
1029
|
+
window.addEventListener('iris-prompt-config-changed', changed);
|
|
1030
|
+
load();
|
|
1031
|
+
return function () { window.removeEventListener('iris-prompt-config-changed', changed); };
|
|
1032
|
+
}, []);
|
|
1033
|
+
|
|
1034
|
+
function toggle() {
|
|
1035
|
+
var enabled = !(state && state.config && state.config.enabled !== false);
|
|
1036
|
+
fetch('/iris/api/prompt-optimizer/enabled', {
|
|
1037
|
+
method: 'POST',
|
|
1038
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1039
|
+
body: JSON.stringify({ enabled: enabled })
|
|
1040
|
+
}).then(function (res) {
|
|
1041
|
+
return res.json().then(function (data) {
|
|
1042
|
+
if (!res.ok) throw new Error(data.error || '更新失败');
|
|
1043
|
+
setState(data);
|
|
1044
|
+
window.dispatchEvent(new CustomEvent('iris-prompt-config-changed', { detail: data }));
|
|
1045
|
+
setNote(enabled ? '对话框 🫧 入口已启用' : '对话框入口已关闭;Iris 工作台与后台能力不受影响');
|
|
1046
|
+
});
|
|
1047
|
+
}).catch(function (err) { setNote(String(err && err.message || err)); });
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
var enabled = !state || !state.config || state.config.enabled !== false;
|
|
1051
|
+
return React.createElement('div', { className: 'iris-wb-card' },
|
|
1052
|
+
React.createElement('div', { className: 'iris-wb-row' },
|
|
1053
|
+
React.createElement('span', { className: 'iris-po-settings-mark' }, '🫧'),
|
|
1054
|
+
React.createElement('span', { style: { flex: 1 } }, enabled ? '对话框入口已启用' : '对话框入口已关闭'),
|
|
1055
|
+
React.createElement('button', { className: 'iris-pm-btn', onClick: toggle }, enabled ? '关闭入口' : '重新启用')),
|
|
1056
|
+
React.createElement('div', { className: 'iris-wb-muted' }, '这里只控制对话框提示词优化入口;Iris 工作台、Agent 工具和任务后台始终保持运行。'),
|
|
1057
|
+
note ? React.createElement('div', { className: 'iris-clean-note' }, note) : null);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
951
1060
|
function WorkbenchPanel() {
|
|
952
1061
|
var state = useIrisState(5000);
|
|
953
1062
|
var running = (state && state.tasks && state.tasks.running) || [];
|
|
@@ -966,6 +1075,8 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
966
1075
|
React.createElement(CapabilityAssigner, {}),
|
|
967
1076
|
React.createElement('div', { className: 'iris-wb-sec' }, 'Iris 泡泡快捷卡片(勾选后显示在「⚡ 常用」标签)'),
|
|
968
1077
|
React.createElement(BubbleCardPicker, {}),
|
|
1078
|
+
React.createElement('div', { className: 'iris-wb-sec' }, '对话框提示词优化'),
|
|
1079
|
+
React.createElement(PromptOptimizerSettings, {}),
|
|
969
1080
|
React.createElement('div', { className: 'iris-wb-sec' }, '运行中任务'),
|
|
970
1081
|
React.createElement('div', { className: 'iris-wb-box' },
|
|
971
1082
|
running.length ? running.map(function (t) { return taskRow(t, true, selectedTask === t.id, onSelect); })
|
|
@@ -993,17 +1104,21 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
993
1104
|
function onSelect(id) { setSelectedTask(id); }
|
|
994
1105
|
var body;
|
|
995
1106
|
if (tab === 'tasks') {
|
|
996
|
-
|
|
1107
|
+
// 快捷面板只承载当前任务与可直接查看的成功产物;失败/取消历史留在完整工作台。
|
|
1108
|
+
var succeeded = recent.filter(function (t) {
|
|
1109
|
+
return t.status === 'succeeded' && Array.isArray(t.media) && t.media.length > 0;
|
|
1110
|
+
});
|
|
1111
|
+
var shown = succeeded.slice(0, 6);
|
|
997
1112
|
body = React.createElement('div', { className: 'iris-wb-box' },
|
|
998
1113
|
running.length ? React.createElement('div', {},
|
|
999
1114
|
React.createElement('div', { className: 'iris-wb-sec' }, '运行中'),
|
|
1000
1115
|
running.map(function (t) { return taskRow(t, true, selectedTask === t.id, onSelect); })) : null,
|
|
1001
|
-
React.createElement('div', { className: 'iris-wb-sec' }, '
|
|
1116
|
+
React.createElement('div', { className: 'iris-wb-sec' }, '最近完成'),
|
|
1002
1117
|
shown.length ? shown.map(function (t) { return taskRowMini(t, selectedTask === t.id, onSelect); })
|
|
1003
|
-
: React.createElement('div', { className: 'iris-wb-empty' }, '
|
|
1004
|
-
|
|
1118
|
+
: React.createElement('div', { className: 'iris-wb-empty' }, '尚无成功产物'),
|
|
1119
|
+
succeeded.length > 6 || recentTotal > succeeded.length
|
|
1005
1120
|
? React.createElement('div', { className: 'iris-bubble-more', style: { cursor: 'default' } },
|
|
1006
|
-
'
|
|
1121
|
+
'失败、取消与完整历史请到 Iris 工作台查看') : null);
|
|
1007
1122
|
} else {
|
|
1008
1123
|
var defs = CARD_DEFS.filter(function (d) { return cards.indexOf(d.action) >= 0; });
|
|
1009
1124
|
body = defs.length
|
|
@@ -1018,6 +1133,234 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
1018
1133
|
selectedTask ? React.createElement(TaskDetailDrawer, { taskId: selectedTask }) : null);
|
|
1019
1134
|
}
|
|
1020
1135
|
|
|
1136
|
+
function PromptOptimizerControl(props) {
|
|
1137
|
+
var draft = props.useInput(function (value) { return value.draft; });
|
|
1138
|
+
var phase = props.useInput(function (value) { return value.phase; });
|
|
1139
|
+
var refCount = props.useInput(function (value) { return (value.occurrences || []).length; });
|
|
1140
|
+
var projection = props.useProjection('modelSelection');
|
|
1141
|
+
var selectedRoute = projection && (projection.current || projection.selection || projection.next || projection.lastUsed || (projection.provider && projection.model ? projection : null));
|
|
1142
|
+
|
|
1143
|
+
var openPair = React.useState(false);
|
|
1144
|
+
var open = openPair[0];
|
|
1145
|
+
var setOpen = openPair[1];
|
|
1146
|
+
var targetPair = React.useState('general');
|
|
1147
|
+
var target = targetPair[0];
|
|
1148
|
+
var setTarget = targetPair[1];
|
|
1149
|
+
var busyPair = React.useState(false);
|
|
1150
|
+
var busy = busyPair[0];
|
|
1151
|
+
var setBusy = busyPair[1];
|
|
1152
|
+
var resultPair = React.useState(null);
|
|
1153
|
+
var result = resultPair[0];
|
|
1154
|
+
var setResult = resultPair[1];
|
|
1155
|
+
var notePair = React.useState('');
|
|
1156
|
+
var note = notePair[0];
|
|
1157
|
+
var setNote = notePair[1];
|
|
1158
|
+
var configPair = React.useState(null);
|
|
1159
|
+
var configState = configPair[0];
|
|
1160
|
+
var setConfigState = configPair[1];
|
|
1161
|
+
var abortRef = React.useRef(null);
|
|
1162
|
+
var fileRef = React.useRef(null);
|
|
1163
|
+
|
|
1164
|
+
function promptRequest(operation, body, signal) {
|
|
1165
|
+
return fetch('/iris/api/prompt-optimizer/' + operation, {
|
|
1166
|
+
method: 'POST',
|
|
1167
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1168
|
+
body: JSON.stringify(body || {}),
|
|
1169
|
+
signal: signal
|
|
1170
|
+
}).then(function (res) {
|
|
1171
|
+
return res.json().catch(function () { return {}; }).then(function (data) {
|
|
1172
|
+
if (!res.ok) throw new Error(data.error || ('请求失败 (' + res.status + ')'));
|
|
1173
|
+
return data;
|
|
1174
|
+
});
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
function loadConfig() {
|
|
1179
|
+
fetch('/iris/api/prompt-optimizer/config')
|
|
1180
|
+
.then(function (res) { return res.ok ? res.json() : null; })
|
|
1181
|
+
.then(function (data) { if (data && data.config) setConfigState(data); })
|
|
1182
|
+
.catch(function () { setNote('无法读取提示词优化配置'); });
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
React.useEffect(function () {
|
|
1186
|
+
return function () {
|
|
1187
|
+
if (abortRef.current) abortRef.current.abort();
|
|
1188
|
+
};
|
|
1189
|
+
}, []);
|
|
1190
|
+
|
|
1191
|
+
React.useEffect(function () {
|
|
1192
|
+
function changed(event) { if (event.detail && event.detail.config) setConfigState(event.detail); }
|
|
1193
|
+
window.addEventListener('iris-prompt-config-changed', changed);
|
|
1194
|
+
loadConfig();
|
|
1195
|
+
return function () { window.removeEventListener('iris-prompt-config-changed', changed); };
|
|
1196
|
+
}, []);
|
|
1197
|
+
|
|
1198
|
+
function publishConfig(data) {
|
|
1199
|
+
setConfigState(data);
|
|
1200
|
+
try { window.dispatchEvent(new CustomEvent('iris-prompt-config-changed', { detail: data })); } catch (_) {}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
function optimize() {
|
|
1204
|
+
if (!draft || !draft.trim()) { setNote('请先在输入框中写入提示词'); return; }
|
|
1205
|
+
if (refCount) { setNote('当前版本暂不改写含 @ 或 / 结构化引用的草稿,以免引用失效'); return; }
|
|
1206
|
+
if (phase !== 'plain') { setNote('输入框正忙,请稍后再试'); return; }
|
|
1207
|
+
if (abortRef.current) abortRef.current.abort();
|
|
1208
|
+
var controller = new AbortController();
|
|
1209
|
+
abortRef.current = controller;
|
|
1210
|
+
setBusy(true);
|
|
1211
|
+
setNote('正在调用模型优化…这可能产生模型费用');
|
|
1212
|
+
setResult(null);
|
|
1213
|
+
promptRequest('optimize', {
|
|
1214
|
+
text: draft,
|
|
1215
|
+
target: target,
|
|
1216
|
+
sessionId: props.sessionId,
|
|
1217
|
+
route: selectedRoute || undefined
|
|
1218
|
+
}, controller.signal).then(function (data) {
|
|
1219
|
+
setResult(data);
|
|
1220
|
+
setNote('已生成预览,尚未写回输入框');
|
|
1221
|
+
}).catch(function (err) {
|
|
1222
|
+
if (controller.signal.aborted) setNote('已取消');
|
|
1223
|
+
else setNote(String(err && err.message || err));
|
|
1224
|
+
}).finally(function () {
|
|
1225
|
+
if (abortRef.current === controller) abortRef.current = null;
|
|
1226
|
+
setBusy(false);
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
function cancel() {
|
|
1231
|
+
if (abortRef.current) abortRef.current.abort();
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
function replaceDraft(text) {
|
|
1235
|
+
if (!result) return;
|
|
1236
|
+
if (draft !== result.original && !window.confirm('输入框内容在优化期间已变化,仍要替换吗?')) return;
|
|
1237
|
+
props.inputActions.setDraft(text);
|
|
1238
|
+
setNote(text === result.original ? '已恢复优化前原文' : '已写回输入框;不会自动发送');
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
function copyResult() {
|
|
1242
|
+
if (!result) return;
|
|
1243
|
+
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
|
|
1244
|
+
navigator.clipboard.writeText(result.optimized).then(function () { setNote('已复制优化结果'); }).catch(function () { setNote('复制失败,请手动选择文本'); });
|
|
1245
|
+
} else {
|
|
1246
|
+
setNote('浏览器不支持自动复制,请手动选择文本');
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
function importConfig(event) {
|
|
1251
|
+
var file = event.target.files && event.target.files[0];
|
|
1252
|
+
event.target.value = '';
|
|
1253
|
+
if (!file) return;
|
|
1254
|
+
file.text().then(function (raw) {
|
|
1255
|
+
var parsed = JSON.parse(raw);
|
|
1256
|
+
return promptRequest('import', { config: parsed });
|
|
1257
|
+
}).then(function (data) {
|
|
1258
|
+
publishConfig(data);
|
|
1259
|
+
setNote('JSON 配置已导入并生效');
|
|
1260
|
+
}).catch(function (err) {
|
|
1261
|
+
setNote('导入失败:' + String(err && err.message || err));
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
function exportConfig() {
|
|
1266
|
+
if (!configState || !configState.config) { setNote('配置尚未载入'); return; }
|
|
1267
|
+
try {
|
|
1268
|
+
var blob = new Blob([JSON.stringify(configState.config, null, 2) + '\n'], { type: 'application/json' });
|
|
1269
|
+
var url = URL.createObjectURL(blob);
|
|
1270
|
+
var a = document.createElement('a');
|
|
1271
|
+
a.href = url;
|
|
1272
|
+
a.download = 'iris-prompt-optimizer.json';
|
|
1273
|
+
a.click();
|
|
1274
|
+
setTimeout(function () { URL.revokeObjectURL(url); }, 0);
|
|
1275
|
+
setNote('已导出当前 JSON 配置');
|
|
1276
|
+
} catch (_) {
|
|
1277
|
+
setNote('导出失败');
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
function resetConfig() {
|
|
1282
|
+
if (!window.confirm('恢复 Iris 内置默认 Prompt、目标模板和会话模型路由?')) return;
|
|
1283
|
+
promptRequest('reset', {}).then(function (data) {
|
|
1284
|
+
publishConfig(data);
|
|
1285
|
+
setNote('已恢复 Iris 内置默认配置');
|
|
1286
|
+
}).catch(function (err) {
|
|
1287
|
+
setNote('重置失败:' + String(err && err.message || err));
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
function disableEntry() {
|
|
1292
|
+
if (busy) return;
|
|
1293
|
+
promptRequest('enabled', { enabled: false }).then(function (data) {
|
|
1294
|
+
publishConfig(data);
|
|
1295
|
+
setOpen(false);
|
|
1296
|
+
}).catch(function (err) { setNote('关闭失败:' + String(err && err.message || err)); });
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
if (configState && configState.config && configState.config.enabled === false) return null;
|
|
1300
|
+
|
|
1301
|
+
var routeLabel = 'DSH 默认模型';
|
|
1302
|
+
if (configState && configState.config && configState.config.route.mode === 'fixed') {
|
|
1303
|
+
routeLabel = configState.config.route.provider + ' / ' + configState.config.route.model;
|
|
1304
|
+
} else if (selectedRoute) {
|
|
1305
|
+
routeLabel = selectedRoute.provider + ' / ' + selectedRoute.model;
|
|
1306
|
+
}
|
|
1307
|
+
var reasoningSetting = configState && configState.config && configState.config.generation && configState.config.generation.reasoningEffort || 'off-if-supported';
|
|
1308
|
+
var reasoningLabel = reasoningSetting === 'off-if-supported' ? '支持时关闭' : reasoningSetting === 'provider-default' ? '供应商默认' : reasoningSetting === 'inherit' ? '跟随会话' : reasoningSetting;
|
|
1309
|
+
var outputBudget = configState && configState.config && configState.config.generation && configState.config.generation.maxOutputTokens || 1200;
|
|
1310
|
+
|
|
1311
|
+
var panel = null;
|
|
1312
|
+
if (open) {
|
|
1313
|
+
panel = React.createElement(React.Fragment, {},
|
|
1314
|
+
React.createElement('div', { className: 'iris-po-backdrop', onClick: function () { setOpen(false); }, 'aria-hidden': 'true' }),
|
|
1315
|
+
React.createElement('div', { className: 'iris-po-panel', role: 'dialog', 'aria-modal': 'true', 'aria-label': 'Iris 提示词优化', onClick: function (e) { e.stopPropagation(); } },
|
|
1316
|
+
React.createElement('div', { className: 'iris-po-head' },
|
|
1317
|
+
React.createElement('strong', { className: 'iris-po-title' }, React.createElement('span', { className: 'iris-po-mark' }, '🫧'), 'Iris 提示词优化'),
|
|
1318
|
+
React.createElement('button', { className: 'iris-po-close', onClick: function () { setOpen(false); }, title: '关闭' }, '✕')),
|
|
1319
|
+
React.createElement('div', { className: 'iris-po-muted' }, '只处理当前未发送草稿,不读取会话历史;调用模型可能产生费用。'),
|
|
1320
|
+
React.createElement('label', { className: 'iris-po-field' },
|
|
1321
|
+
React.createElement('span', {}, '优化目标'),
|
|
1322
|
+
React.createElement('select', { value: target, disabled: busy, onChange: function (e) { setTarget(e.target.value); } },
|
|
1323
|
+
React.createElement('option', { value: 'general' }, '通用对话'),
|
|
1324
|
+
React.createElement('option', { value: 'image' }, '图片生成'),
|
|
1325
|
+
React.createElement('option', { value: 'video' }, '视频生成'),
|
|
1326
|
+
React.createElement('option', { value: 's2v' }, '首尾帧视频'))),
|
|
1327
|
+
React.createElement('div', { className: 'iris-po-route', title: routeLabel }, '模型:' + routeLabel + ' · 思考:' + reasoningLabel + ' · 输出:' + outputBudget + ' tokens'),
|
|
1328
|
+
React.createElement('div', { className: 'iris-po-actions' },
|
|
1329
|
+
React.createElement('button', { className: 'iris-po-primary', disabled: busy || !draft || !draft.trim() || phase !== 'plain' || refCount > 0, onClick: optimize }, busy ? '优化中…' : '生成预览'),
|
|
1330
|
+
busy ? React.createElement('button', { className: 'iris-po-btn', onClick: cancel }, '取消') : null),
|
|
1331
|
+
result ? React.createElement('div', { className: 'iris-po-result' },
|
|
1332
|
+
React.createElement('div', { className: 'iris-po-result-label' }, '优化结果'),
|
|
1333
|
+
React.createElement('textarea', { readOnly: true, value: result.optimized }),
|
|
1334
|
+
React.createElement('div', { className: 'iris-po-route' }, '实际使用:' + result.route.provider + ' / ' + result.route.model + ' · 思考:' + (result.route.reasoningEffort === 'provider-default' ? '供应商默认' : result.route.reasoningEffort)),
|
|
1335
|
+
React.createElement('div', { className: 'iris-po-actions' },
|
|
1336
|
+
React.createElement('button', { className: 'iris-po-primary', onClick: function () { replaceDraft(result.optimized); } }, '写回输入框'),
|
|
1337
|
+
React.createElement('button', { className: 'iris-po-btn', onClick: copyResult }, '复制'),
|
|
1338
|
+
React.createElement('button', { className: 'iris-po-btn', onClick: optimize }, '再优化'),
|
|
1339
|
+
React.createElement('button', { className: 'iris-po-btn', onClick: function () { replaceDraft(result.original); } }, '恢复原文'))) : null,
|
|
1340
|
+
note ? React.createElement('div', { className: 'iris-po-note' }, note) : null,
|
|
1341
|
+
React.createElement('details', { className: 'iris-po-config' },
|
|
1342
|
+
React.createElement('summary', {}, 'JSON 配置'),
|
|
1343
|
+
React.createElement('div', { className: 'iris-po-muted' }, '可导出后修改 systemPrompt、targets、route 和 generation,再重新导入。'),
|
|
1344
|
+
React.createElement('div', { className: 'iris-po-actions' },
|
|
1345
|
+
React.createElement('button', { className: 'iris-po-btn', onClick: exportConfig }, '导出'),
|
|
1346
|
+
React.createElement('button', { className: 'iris-po-btn', onClick: function () { if (fileRef.current) fileRef.current.click(); } }, '导入'),
|
|
1347
|
+
React.createElement('button', { className: 'iris-po-btn danger', onClick: resetConfig }, '恢复默认'),
|
|
1348
|
+
React.createElement('input', { ref: fileRef, className: 'iris-po-file', type: 'file', accept: 'application/json,.json', onChange: importConfig })),
|
|
1349
|
+
React.createElement('div', { className: 'iris-po-muted' }, '当前:' + (configState && configState.source === 'custom' ? '用户 JSON' : 'Iris 默认'))),
|
|
1350
|
+
React.createElement('button', { className: 'iris-po-disable', disabled: busy, onClick: disableEntry }, '关闭此对话入口(工作台仍保留)')));
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
return React.createElement('div', { className: 'iris-po-wrap' },
|
|
1354
|
+
React.createElement('button', {
|
|
1355
|
+
className: 'iris-po-trigger',
|
|
1356
|
+
type: 'button',
|
|
1357
|
+
title: refCount ? '含结构化引用的草稿暂不支持优化' : '优化当前输入框提示词',
|
|
1358
|
+
'aria-expanded': open ? 'true' : 'false',
|
|
1359
|
+
onClick: function () { setOpen(!open); }
|
|
1360
|
+
}, '🫧'),
|
|
1361
|
+
panel);
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1021
1364
|
function ProgressDock() {
|
|
1022
1365
|
var state = useIrisState(5000);
|
|
1023
1366
|
var running = (state && state.tasks && state.tasks.running) || [];
|
|
@@ -1158,6 +1501,15 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
1158
1501
|
}, WorkbenchPanel);
|
|
1159
1502
|
});
|
|
1160
1503
|
|
|
1504
|
+
ctx.slots.inject('conversation.input.right', function () {
|
|
1505
|
+
return ctx.slots.register({
|
|
1506
|
+
name: 'conversation.input.right',
|
|
1507
|
+
id: 'iris-prompt-optimizer',
|
|
1508
|
+
order: 40,
|
|
1509
|
+
label: function () { return 'Iris 提示词优化'; }
|
|
1510
|
+
}, PromptOptimizerControl);
|
|
1511
|
+
});
|
|
1512
|
+
|
|
1161
1513
|
ctx.slots.inject('conversation.input.dock', function () {
|
|
1162
1514
|
return ctx.slots.register({
|
|
1163
1515
|
name: 'conversation.input.dock',
|
|
@@ -1184,4 +1536,4 @@ window.__ModuleLoader__.load({ id: 'dsh-iris', factory: (require) => {
|
|
|
1184
1536
|
|
|
1185
1537
|
module.exports = { inject: inject, apply: apply };
|
|
1186
1538
|
return module.exports;
|
|
1187
|
-
}});
|
|
1539
|
+
}});
|