newmark-agent 0.4.0 → 0.4.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/config.example.json +5 -0
- package/dist/conversation-utility-host.bundle.cjs +419 -34
- package/dist/core/agent.d.ts +52 -4
- package/dist/core/agent.js +260 -23
- package/dist/core/agentKernelRunner.js +33 -16
- package/dist/core/config.d.ts +8 -0
- package/dist/core/conversationKernel.d.ts +16 -0
- package/dist/core/conversationKernel.js +34 -1
- package/dist/core/toolPolicy.d.ts +9 -0
- package/dist/core/toolPolicy.js +128 -0
- package/dist/llm/provider.d.ts +13 -1
- package/dist/llm/provider.js +42 -1
- package/dist/providers/provider-adapter.d.ts +3 -1
- package/dist/toolchain/registry-seeder.js +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +31 -1
- package/dist/tools/nativeTools.js +1 -0
- package/dist/tui/src/app.js +24 -0
- package/dist/tui/src/i18n.js +151 -0
- package/dist/tui/src/render.js +205 -90
- package/dist/tui/src/state.js +86 -0
- package/dist/ui/index.html +239 -71
- package/dist/ui/lucide-sprite.svg +5 -0
- package/dist/wsl-agent-host.bundle.cjs +419 -34
- package/package.json +7 -11
- package/Flow/Electron-Debug-Release.Flow.json +0 -43
- package/Flow/Flow.md +0 -9
- package/Flow/UI-Feature-Integration.Flow.json +0 -96
package/dist/ui/index.html
CHANGED
|
@@ -10,6 +10,9 @@ try {
|
|
|
10
10
|
if (startupQuery.get('startupPrewarm') === '1' && Number(startupQuery.get('startupAttempt') || 0) > 0) {
|
|
11
11
|
document.documentElement.classList.add('startup-prewarm');
|
|
12
12
|
}
|
|
13
|
+
if (sessionStorage.getItem('newmark-config-reloading') === '1') {
|
|
14
|
+
document.documentElement.classList.add('config-reloading');
|
|
15
|
+
}
|
|
13
16
|
} catch {}
|
|
14
17
|
</script>
|
|
15
18
|
<style>
|
|
@@ -279,6 +282,7 @@ html, body {
|
|
|
279
282
|
}
|
|
280
283
|
|
|
281
284
|
.startup-prewarm #startup-cover { display: flex; }
|
|
285
|
+
.config-reloading #startup-cover { display: flex; }
|
|
282
286
|
|
|
283
287
|
.startup-cover-shell {
|
|
284
288
|
width: min(520px, calc(100vw - 48px));
|
|
@@ -1059,6 +1063,19 @@ button.left-ws-item {
|
|
|
1059
1063
|
.conv-archive-btn:hover,
|
|
1060
1064
|
.conv-rename-btn:hover { background: rgba(255,255,255,0.1); color: var(--text-bright); }
|
|
1061
1065
|
|
|
1066
|
+
.conv-archive-btn.archiving { cursor: default; border-color: var(--accent); }
|
|
1067
|
+
.conv-archive-spinner {
|
|
1068
|
+
width: 11px;
|
|
1069
|
+
height: 11px;
|
|
1070
|
+
border: 2px solid var(--border);
|
|
1071
|
+
border-top-color: var(--accent);
|
|
1072
|
+
border-radius: 50%;
|
|
1073
|
+
animation: conv-archive-spin 0.7s linear infinite;
|
|
1074
|
+
}
|
|
1075
|
+
@keyframes conv-archive-spin {
|
|
1076
|
+
to { transform: rotate(360deg); }
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1062
1079
|
.conv-item.dragging { opacity: 0.58; }
|
|
1063
1080
|
.conv-item.drag-over { border-color: var(--accent); background: rgba(91,120,255,0.14); }
|
|
1064
1081
|
.conv-rename-input {
|
|
@@ -2432,9 +2449,9 @@ button.left-ws-item {
|
|
|
2432
2449
|
.conversation-work-event.error { color: #ff8888; }
|
|
2433
2450
|
.conversation-work-event-content { min-width: 0; white-space: pre-wrap; word-break: break-word; }
|
|
2434
2451
|
.conversation-work-event.narrative { display: block; color: var(--text); font-size: 13px; line-height: 1.65; padding: 3px 1px 7px; }
|
|
2435
|
-
.conversation-work-event.activity-summary { font-size:
|
|
2452
|
+
.conversation-work-event.activity-summary { font-size: 11px; font-weight: 400; color: var(--text-dim); padding: 2px 0; }
|
|
2436
2453
|
.conversation-work-activity { margin: 0; padding: 0; }
|
|
2437
|
-
.conversation-work-activity > summary { display: grid; grid-template-columns: 17px minmax(0,1fr) 10px; gap: 8px; align-items: center; min-height: 28px; cursor: pointer; list-style: none; color: var(--text); font-size:
|
|
2454
|
+
.conversation-work-activity > summary { display: grid; grid-template-columns: 17px minmax(0,1fr) 10px; gap: 8px; align-items: center; min-height: 28px; cursor: pointer; list-style: none; color: var(--text-dim); font-size: 11px; font-weight: 400; }
|
|
2438
2455
|
.conversation-work-activity > summary::-webkit-details-marker { display: none; }
|
|
2439
2456
|
.conversation-work-activity > summary .nm-icon { color: var(--text-dim); }
|
|
2440
2457
|
.conversation-work-activity-chevron { width: 7px; height: 7px; border-right: 1px solid var(--text-dim); border-bottom: 1px solid var(--text-dim); transform: rotate(-45deg); transition: transform 140ms ease; }
|
|
@@ -3137,15 +3154,19 @@ button.todo-item { background: transparent; }
|
|
|
3137
3154
|
font: 9px var(--font-mono);
|
|
3138
3155
|
}
|
|
3139
3156
|
|
|
3140
|
-
.conv-branch-comm-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
border-radius:
|
|
3144
|
-
|
|
3157
|
+
.conv-branch-comm-icon {
|
|
3158
|
+
width: 20px;
|
|
3159
|
+
height: 20px;
|
|
3160
|
+
border-radius: var(--radius-sm);
|
|
3161
|
+
border: 1px solid var(--border);
|
|
3162
|
+
background: transparent;
|
|
3145
3163
|
color: var(--accent);
|
|
3146
|
-
|
|
3147
|
-
|
|
3164
|
+
display: flex;
|
|
3165
|
+
align-items: center;
|
|
3166
|
+
justify-content: center;
|
|
3167
|
+
flex-shrink: 0;
|
|
3148
3168
|
}
|
|
3169
|
+
.conv-branch-comm-icon .nm-icon { width: 11px; height: 11px; }
|
|
3149
3170
|
|
|
3150
3171
|
.conv-runtime-badge.running { color: var(--accent2); }
|
|
3151
3172
|
.conv-runtime-badge.stopping,
|
|
@@ -3502,8 +3523,6 @@ button.todo-item { background: transparent; }
|
|
|
3502
3523
|
.context-inspector-head { display:flex; align-items:flex-start; gap:8px; margin-bottom:10px; }
|
|
3503
3524
|
.context-inspector-title { flex:1; min-width:0; color:var(--text-bright); font-size:12px; font-weight:700; }
|
|
3504
3525
|
.context-inspector-subtitle { margin-top:2px; color:var(--text-dim); font-size:9px; }
|
|
3505
|
-
.context-inspector-close { width:22px; height:22px; padding:0; border:0; border-radius:var(--radius-sm); background:transparent; color:var(--text-dim); cursor:pointer; }
|
|
3506
|
-
.context-inspector-close:hover, .context-inspector-close:focus-visible { color:var(--text-bright); background:var(--control-hover-bg); outline:none; }
|
|
3507
3526
|
.context-inspector-meter { height:6px; margin:8px 0 10px; overflow:hidden; border-radius:var(--radius-full); background:rgba(168,168,168,.18); }
|
|
3508
3527
|
.context-inspector-meter-fill { height:100%; border-radius:inherit; background:var(--accent); transition:width var(--duration-normal) var(--ease-out-expo), background var(--duration-fast) var(--ease-out-expo); }
|
|
3509
3528
|
.context-inspector-grid { display:grid; grid-template-columns:1fr 1fr; gap:7px; }
|
|
@@ -5009,6 +5028,32 @@ html.newmark-memory-overview-viewer body {
|
|
|
5009
5028
|
.auto-input-group select:focus,
|
|
5010
5029
|
.auto-input-group textarea:focus { border-color: var(--accent); }
|
|
5011
5030
|
|
|
5031
|
+
.auto-input-group.checkbox-row {
|
|
5032
|
+
display: flex;
|
|
5033
|
+
padding: 9px 11px;
|
|
5034
|
+
border: 1px solid var(--border);
|
|
5035
|
+
border-radius: var(--radius-md);
|
|
5036
|
+
background: var(--glass-bg-1);
|
|
5037
|
+
}
|
|
5038
|
+
.auto-input-group.checkbox-row label {
|
|
5039
|
+
display: flex;
|
|
5040
|
+
align-items: center;
|
|
5041
|
+
gap: 8px;
|
|
5042
|
+
margin: 0;
|
|
5043
|
+
cursor: pointer;
|
|
5044
|
+
font-size: 12px;
|
|
5045
|
+
color: var(--text);
|
|
5046
|
+
}
|
|
5047
|
+
.auto-input-group.checkbox-row input[type="checkbox"] {
|
|
5048
|
+
width: 15px;
|
|
5049
|
+
height: 15px;
|
|
5050
|
+
flex-shrink: 0;
|
|
5051
|
+
accent-color: var(--accent);
|
|
5052
|
+
cursor: pointer;
|
|
5053
|
+
margin: 0;
|
|
5054
|
+
padding: 0;
|
|
5055
|
+
}
|
|
5056
|
+
|
|
5012
5057
|
.auto-conditions {
|
|
5013
5058
|
display: flex;
|
|
5014
5059
|
gap: 8px;
|
|
@@ -5328,6 +5373,11 @@ html.newmark-memory-overview-viewer body {
|
|
|
5328
5373
|
<symbol id="folder" viewBox="0 0 24 24">
|
|
5329
5374
|
<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />
|
|
5330
5375
|
</symbol>
|
|
5376
|
+
<symbol id="git-branch" viewBox="0 0 24 24">
|
|
5377
|
+
<path d="M15 6a9 9 0 0 0-9 9V3" />
|
|
5378
|
+
<circle cx="18" cy="6" r="3" />
|
|
5379
|
+
<circle cx="6" cy="18" r="3" />
|
|
5380
|
+
</symbol>
|
|
5331
5381
|
<symbol id="globe" viewBox="0 0 24 24">
|
|
5332
5382
|
<circle cx="12" cy="12" r="10" />
|
|
5333
5383
|
<path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" />
|
|
@@ -6433,6 +6483,8 @@ var NEWMARK_I18N = {
|
|
|
6433
6483
|
'model.contextSize': 'Context size',
|
|
6434
6484
|
'model.vision': 'Vision',
|
|
6435
6485
|
'model.thinking': 'Thinking',
|
|
6486
|
+
'model.thinkingTierMap': 'Thinking tier map',
|
|
6487
|
+
'model.thinkingTierMapHelp': 'Map native model effort tiers to Newmark tiers. One "native=Newmark" per line (e.g. minimal=low, balanced=medium, deep=high). Leave empty to keep the default mapping (Newmark tier names are sent as-is).',
|
|
6436
6488
|
'model.description': 'Description',
|
|
6437
6489
|
'model.optionalDescription': 'Optional description',
|
|
6438
6490
|
'model.fuzzyInput': 'API key / provider details',
|
|
@@ -6489,6 +6541,7 @@ var NEWMARK_I18N = {
|
|
|
6489
6541
|
'model.yes': 'yes',
|
|
6490
6542
|
'model.notChecked': 'not checked',
|
|
6491
6543
|
'archive.current': 'Archive current chat',
|
|
6544
|
+
'archive.archiving': 'Archiving...',
|
|
6492
6545
|
'archive.empty': 'No archives yet.',
|
|
6493
6546
|
'archive.loading': 'Loading workspace archives...',
|
|
6494
6547
|
'archive.unavailable': 'Archive list unavailable',
|
|
@@ -6794,6 +6847,8 @@ var NEWMARK_I18N = {
|
|
|
6794
6847
|
'status.contextCompressed': 'Context compressed',
|
|
6795
6848
|
'status.contextCompression': 'Context compression',
|
|
6796
6849
|
'status.contextTokens': 'Context tokens',
|
|
6850
|
+
'status.conversationTokens': 'Conversation tokens',
|
|
6851
|
+
'status.cacheHitRate': 'Cache hit rate',
|
|
6797
6852
|
'status.contextNearLimit': 'Context near limit',
|
|
6798
6853
|
'status.contextOverLimit': 'Context over limit',
|
|
6799
6854
|
'status.contextModeFallback': 'fallback',
|
|
@@ -6801,7 +6856,7 @@ var NEWMARK_I18N = {
|
|
|
6801
6856
|
'status.messages': 'messages',
|
|
6802
6857
|
'status.noCompression': 'No compression event in this conversation',
|
|
6803
6858
|
'status.contextInspector': 'Context management',
|
|
6804
|
-
'status.contextInspectorHint': '
|
|
6859
|
+
'status.contextInspectorHint': 'Live context budget; visible chat history stays unchanged.',
|
|
6805
6860
|
'status.activeBuild': 'Active Build',
|
|
6806
6861
|
'status.longHistory': 'Long history',
|
|
6807
6862
|
'status.trigger': 'Trigger',
|
|
@@ -7134,6 +7189,8 @@ var NEWMARK_I18N = {
|
|
|
7134
7189
|
'model.contextSize': '上下文规模',
|
|
7135
7190
|
'model.vision': '视觉',
|
|
7136
7191
|
'model.thinking': '思考',
|
|
7192
|
+
'model.thinkingTierMap': '思考强度档位映射',
|
|
7193
|
+
'model.thinkingTierMapHelp': '将模型原生思考强度档位映射到 Newmark 档位。每行一个「原生档位=Newmark档位」(如 minimal=low、balanced=medium、deep=high)。留空表示不变动映射(按 Newmark 档位名原样发送)。',
|
|
7137
7194
|
'model.description': '描述',
|
|
7138
7195
|
'model.optionalDescription': '可选描述',
|
|
7139
7196
|
'model.fuzzyInput': 'API key / 供应商信息',
|
|
@@ -7190,6 +7247,7 @@ var NEWMARK_I18N = {
|
|
|
7190
7247
|
'model.yes': '是',
|
|
7191
7248
|
'model.notChecked': '未校验',
|
|
7192
7249
|
'archive.current': '归档当前对话',
|
|
7250
|
+
'archive.archiving': '归档中...',
|
|
7193
7251
|
'archive.empty': '暂无归档。',
|
|
7194
7252
|
'archive.loading': '正在加载工作区归档...',
|
|
7195
7253
|
'archive.unavailable': '归档列表不可用',
|
|
@@ -7495,6 +7553,8 @@ var NEWMARK_I18N = {
|
|
|
7495
7553
|
'status.contextCompressed': '上下文已压缩',
|
|
7496
7554
|
'status.contextCompression': '上下文压缩',
|
|
7497
7555
|
'status.contextTokens': '上下文 token',
|
|
7556
|
+
'status.conversationTokens': '全对话 token',
|
|
7557
|
+
'status.cacheHitRate': '缓存命中率',
|
|
7498
7558
|
'status.contextNearLimit': '上下文接近上限',
|
|
7499
7559
|
'status.contextOverLimit': '上下文已超限',
|
|
7500
7560
|
'status.contextModeFallback': 'fallback',
|
|
@@ -7502,7 +7562,7 @@ var NEWMARK_I18N = {
|
|
|
7502
7562
|
'status.messages': '条消息',
|
|
7503
7563
|
'status.noCompression': '当前对话暂无压缩事件',
|
|
7504
7564
|
'status.contextInspector': '上下文管理',
|
|
7505
|
-
'status.contextInspectorHint': '
|
|
7565
|
+
'status.contextInspectorHint': '实时上下文预算;可见对话历史不会被改写。',
|
|
7506
7566
|
'status.activeBuild': '当前 Build',
|
|
7507
7567
|
'status.longHistory': '长期历史',
|
|
7508
7568
|
'status.trigger': '触发线',
|
|
@@ -10120,7 +10180,7 @@ function renderWorkToolGroup(event, eventIndex) {
|
|
|
10120
10180
|
var edited = workToolEditedFile(item);
|
|
10121
10181
|
if (edited) {
|
|
10122
10182
|
var editKey = 'edit:' + String(item.id || item.toolCallId || itemIndex) + ':' + edited.path;
|
|
10123
|
-
return '<details class="conversation-work-file conversation-work-file-inline"
|
|
10183
|
+
return '<details class="conversation-work-file conversation-work-file-inline" data-work-detail-key="' + escAttr(editKey) + '"><summary>' +
|
|
10124
10184
|
iconSvg('pencil', 'edited', 'tiny') +
|
|
10125
10185
|
'<span class="conversation-work-file-name" title="' + escAttr(edited.path) + '">' + esc(currentLang() === 'zh' ? '已编辑 ' : 'Edited ') + esc(edited.name) + '</span>' +
|
|
10126
10186
|
'<span class="conversation-work-file-stats"><span class="conversation-work-file-add">+' + edited.added + '</span><span class="conversation-work-file-del">-' + edited.deleted + '</span></span>' +
|
|
@@ -12021,6 +12081,12 @@ window.renderContextInspector = function() {
|
|
|
12021
12081
|
var historyTrigger = contextInspectorValue(c.longHistoryTriggerTokens);
|
|
12022
12082
|
var activeRetention = contextInspectorValue(c.buildBlockRetentionTokens);
|
|
12023
12083
|
var historyRetention = contextInspectorValue(c.longHistoryRetentionTokens);
|
|
12084
|
+
var providerTotalTokens = contextInspectorValue(c.providerTotalTokens);
|
|
12085
|
+
var providerInputTokens = contextInspectorValue(c.providerInputTokens);
|
|
12086
|
+
var providerOutputTokens = contextInspectorValue(c.providerOutputTokens);
|
|
12087
|
+
var providerCacheReadTokens = contextInspectorValue(c.providerCacheReadTokens);
|
|
12088
|
+
var providerCacheReadRatio = Math.max(0, Math.min(1, Number(c.providerCacheReadRatio) || 0));
|
|
12089
|
+
var cacheHitPercent = Math.round(providerCacheReadRatio * 1000) / 10;
|
|
12024
12090
|
var percent = Math.min(100, Math.round((used / max) * 100));
|
|
12025
12091
|
var fillColor = c.warning === 'over_limit' ? 'var(--nm-state-danger)' : (c.warning === 'near_limit' ? 'var(--nm-state-warning)' : 'var(--accent)');
|
|
12026
12092
|
var compression = state.contextCompression || null;
|
|
@@ -12029,12 +12095,13 @@ window.renderContextInspector = function() {
|
|
|
12029
12095
|
: t('status.noCompressionShort');
|
|
12030
12096
|
var busy = !!state.contextMutationPending;
|
|
12031
12097
|
var running = typeof isCurrentConversationRunning === 'function' && isCurrentConversationRunning();
|
|
12032
|
-
panel.innerHTML = '<div class="context-inspector-head"><div><div class="context-inspector-title">' + esc(t('status.contextInspector')) + '</div><div class="context-inspector-subtitle">' + esc(t('status.contextInspectorHint')) + '</div></div>' +
|
|
12033
|
-
'<button type="button" class="context-inspector-close" onclick="window.closeContextInspector()" aria-label="' + esc(t('common.close') || 'Close') + '">×</button></div>' +
|
|
12098
|
+
panel.innerHTML = '<div class="context-inspector-head"><div><div class="context-inspector-title">' + esc(t('status.contextInspector')) + '</div><div class="context-inspector-subtitle">' + esc(t('status.contextInspectorHint')) + '</div></div></div>' +
|
|
12034
12099
|
'<div class="context-inspector-meter"><div class="context-inspector-meter-fill" style="width:' + percent + '%;background:' + fillColor + '"></div></div>' +
|
|
12035
12100
|
'<div class="context-inspector-grid">' +
|
|
12036
12101
|
contextInspectorCell(t('status.contextTokens'), used + ' / ' + max) +
|
|
12102
|
+
contextInspectorCell(t('status.conversationTokens'), providerTotalTokens + ' · ' + providerInputTokens + ' in / ' + providerOutputTokens + ' out') +
|
|
12037
12103
|
contextInspectorCell(t('status.activeBuild'), active + ' / ' + activeTrigger) +
|
|
12104
|
+
contextInspectorCell(t('status.cacheHitRate'), cacheHitPercent + '% · ' + providerCacheReadTokens + ' cached') +
|
|
12038
12105
|
contextInspectorCell(t('status.longHistory'), history + ' / ' + historyTrigger) +
|
|
12039
12106
|
contextInspectorCell(t('status.retention'), activeRetention + ' + ' + historyRetention) +
|
|
12040
12107
|
contextInspectorCell(t('status.hotCache'), contextInspectorValue(c.cacheEntries) + ' entries') +
|
|
@@ -12050,6 +12117,17 @@ window.closeContextInspector = function() {
|
|
|
12050
12117
|
window.renderContextInspector();
|
|
12051
12118
|
};
|
|
12052
12119
|
|
|
12120
|
+
(function() {
|
|
12121
|
+
document.addEventListener('click', function(event) {
|
|
12122
|
+
if (!state.contextInspectorOpen) return;
|
|
12123
|
+
var ring = document.getElementById('context-token-ring');
|
|
12124
|
+
var panel = document.getElementById('context-inspector');
|
|
12125
|
+
if (!ring || !panel) return;
|
|
12126
|
+
if (panel.contains(event.target) || ring.contains(event.target)) return;
|
|
12127
|
+
window.closeContextInspector();
|
|
12128
|
+
});
|
|
12129
|
+
})();
|
|
12130
|
+
|
|
12053
12131
|
window.toggleContextInspector = function() {
|
|
12054
12132
|
state.contextInspectorOpen = !state.contextInspectorOpen;
|
|
12055
12133
|
window.hideContextWindowTooltip();
|
|
@@ -15275,9 +15353,11 @@ function renderModelSettings() {
|
|
|
15275
15353
|
: (normalizedStatus === 'not checked' ? 'model-eval-pending' : 'model-eval-bad');
|
|
15276
15354
|
var details = '';
|
|
15277
15355
|
if (typeof modelEntry !== 'string') {
|
|
15356
|
+
var tierMapCount = modelEntry.thinking_tier_map && typeof modelEntry.thinking_tier_map === 'object' ? Object.keys(modelEntry.thinking_tier_map).length : 0;
|
|
15278
15357
|
details = '<span class="model-eval-line">ctx ' + esc(modelEntry.max_tokens || '') +
|
|
15279
15358
|
' | ' + esc(t('model.vision')) + ' ' + (modelEntry.vision ? t('common.on') : t('common.off')) +
|
|
15280
15359
|
' | ' + esc(t('model.thinking')) + ' ' + (modelEntry.thinking ? t('common.on') : t('common.off')) +
|
|
15360
|
+
(tierMapCount ? ' | ' + esc(t('model.thinkingTierMap')) + ' ' + tierMapCount : '') +
|
|
15281
15361
|
' | ' + esc(t('model.cost')) + ' ' + esc(evaluation ? evaluation.cost_rating : '-') +
|
|
15282
15362
|
' | ' + esc(t('model.performanceShort')) + ' ' + esc(modelEntry.capability_rating || '-') +
|
|
15283
15363
|
' | ' + esc(t('model.speed')) + ' ' + esc(modelEntry.speed_rating || '-') + '</span>';
|
|
@@ -15545,8 +15625,8 @@ window.refreshGlobalConfigFile = function() {
|
|
|
15545
15625
|
if (!api.reloadGlobalConfig) return;
|
|
15546
15626
|
api.reloadGlobalConfig().then(function(result) {
|
|
15547
15627
|
if (result && result.error) throw new Error(result.error);
|
|
15548
|
-
|
|
15549
|
-
|
|
15628
|
+
try { sessionStorage.setItem('newmark-config-reloading', '1'); } catch (_) {}
|
|
15629
|
+
window.location.reload();
|
|
15550
15630
|
}).catch(function(error) {
|
|
15551
15631
|
showUiNotice(error && error.message ? error.message : String(error), 'error', 'global-config-refresh');
|
|
15552
15632
|
});
|
|
@@ -15986,9 +16066,31 @@ window.addModel = function() {
|
|
|
15986
16066
|
'<div style="display:flex;gap:10px;margin-bottom:10px;"><label style="font-size:11px;color:var(--text-dim);"><input type="checkbox" id="new-model-vision"> ' + esc(t('model.vision')) + '</label>' +
|
|
15987
16067
|
'<label style="font-size:11px;color:var(--text-dim);"><input type="checkbox" id="new-model-thinking"> ' + esc(t('model.thinking')) + '</label></div>' +
|
|
15988
16068
|
'<div class="auto-input-group"><label>' + esc(t('model.description')) + '</label><textarea id="new-model-desc" rows="2" placeholder="' + escAttr(t('model.optionalDescription')) + '"></textarea></div>' +
|
|
16069
|
+
'<div class="auto-input-group"><label>' + esc(t('model.thinkingTierMap')) + '</label><textarea id="new-model-tier-map" rows="3" placeholder="minimal=low balanced=medium deep=high"></textarea>' +
|
|
16070
|
+
'<div style="margin-top:10px;font-size:11px;color:var(--text-dim);">' + esc(t('model.thinkingTierMapHelp')) + '</div></div>' +
|
|
15989
16071
|
'<div style="margin-top:10px;"><button class="sec-btn primary" onclick="window.saveNewModel()">' + esc(t('common.save')) + '</button></div>');
|
|
15990
16072
|
};
|
|
15991
16073
|
|
|
16074
|
+
window.parseThinkingTierMap = function(text) {
|
|
16075
|
+
var map = {};
|
|
16076
|
+
if (!text) return map;
|
|
16077
|
+
String(text).split('\n').forEach(function(line) {
|
|
16078
|
+
var trimmed = line.trim();
|
|
16079
|
+
if (!trimmed) return;
|
|
16080
|
+
var eq = trimmed.indexOf('=');
|
|
16081
|
+
if (eq <= 0) return;
|
|
16082
|
+
var native = trimmed.slice(0, eq).trim();
|
|
16083
|
+
var newmark = trimmed.slice(eq + 1).trim();
|
|
16084
|
+
if (native && newmark) map[native] = newmark;
|
|
16085
|
+
});
|
|
16086
|
+
return map;
|
|
16087
|
+
};
|
|
16088
|
+
|
|
16089
|
+
window.serializeThinkingTierMap = function(map) {
|
|
16090
|
+
if (!map || typeof map !== 'object') return '';
|
|
16091
|
+
return Object.keys(map).map(function(k) { return k + '=' + map[k]; }).join('\n');
|
|
16092
|
+
};
|
|
16093
|
+
|
|
15992
16094
|
window.saveNewModel = function() {
|
|
15993
16095
|
var name = document.getElementById('new-model-name').value;
|
|
15994
16096
|
var provIdx = parseInt(document.getElementById('new-model-provider').value);
|
|
@@ -15996,9 +16098,11 @@ window.saveNewModel = function() {
|
|
|
15996
16098
|
var visionEl = document.getElementById('new-model-vision');
|
|
15997
16099
|
var thinkingEl = document.getElementById('new-model-thinking');
|
|
15998
16100
|
var descEl = document.getElementById('new-model-desc');
|
|
16101
|
+
var tierMapEl = document.getElementById('new-model-tier-map');
|
|
15999
16102
|
if (name && !isNaN(provIdx) && state.providers[provIdx]) {
|
|
16000
16103
|
if (!state.providers[provIdx].models) state.providers[provIdx].models = [];
|
|
16001
|
-
|
|
16104
|
+
var tierMap = window.parseThinkingTierMap(tierMapEl ? tierMapEl.value : '');
|
|
16105
|
+
var entry = {
|
|
16002
16106
|
name: name,
|
|
16003
16107
|
display: name,
|
|
16004
16108
|
description: descEl ? descEl.value : '',
|
|
@@ -16015,7 +16119,9 @@ window.saveNewModel = function() {
|
|
|
16015
16119
|
xhigh: { description: 'xhigh' },
|
|
16016
16120
|
max: { description: 'max' }
|
|
16017
16121
|
}
|
|
16018
|
-
}
|
|
16122
|
+
};
|
|
16123
|
+
if (Object.keys(tierMap).length) entry.thinking_tier_map = tierMap;
|
|
16124
|
+
state.providers[provIdx].models.push(entry);
|
|
16019
16125
|
api.saveConfig({providers: state.providers});
|
|
16020
16126
|
window.refreshModelSelect();
|
|
16021
16127
|
}
|
|
@@ -16035,6 +16141,8 @@ window.editModel = function(provIdx, modelIdx) {
|
|
|
16035
16141
|
'<div style="display:flex;gap:10px;margin-bottom:10px;"><label style="font-size:11px;color:var(--text-dim);"><input type="checkbox" id="edit-model-vision"' + (model.vision ? ' checked' : '') + '> ' + esc(t('model.vision')) + '</label>' +
|
|
16036
16142
|
'<label style="font-size:11px;color:var(--text-dim);"><input type="checkbox" id="edit-model-thinking"' + (model.thinking ? ' checked' : '') + '> ' + esc(t('model.thinking')) + '</label></div>' +
|
|
16037
16143
|
'<div class="auto-input-group"><label>' + esc(t('model.description')) + '</label><textarea id="edit-model-desc" rows="2">' + esc(model.description || '') + '</textarea></div>' +
|
|
16144
|
+
'<div class="auto-input-group"><label>' + esc(t('model.thinkingTierMap')) + '</label><textarea id="edit-model-tier-map" rows="3">' + esc(window.serializeThinkingTierMap(model.thinking_tier_map)) + '</textarea>' +
|
|
16145
|
+
'<div style="margin-top:10px;font-size:11px;color:var(--text-dim);">' + esc(t('model.thinkingTierMapHelp')) + '</div></div>' +
|
|
16038
16146
|
'<div style="margin-top:10px;"><button class="sec-btn primary" onclick="window.saveModelEdit(' + provIdx + ',' + modelIdx + ')">' + esc(t('common.save')) + '</button></div>');
|
|
16039
16147
|
};
|
|
16040
16148
|
|
|
@@ -16047,11 +16155,13 @@ window.saveModelEdit = function(oldProvIdx, modelIdx) {
|
|
|
16047
16155
|
var visionEl = document.getElementById('edit-model-vision');
|
|
16048
16156
|
var thinkingEl = document.getElementById('edit-model-thinking');
|
|
16049
16157
|
var descEl = document.getElementById('edit-model-desc');
|
|
16158
|
+
var tierMapEl = document.getElementById('edit-model-tier-map');
|
|
16050
16159
|
var name = nameEl ? nameEl.value.trim() : '';
|
|
16051
16160
|
var newProvIdx = provEl ? parseInt(provEl.value) : oldProvIdx;
|
|
16052
16161
|
if (!name || isNaN(newProvIdx) || !state.providers[newProvIdx]) return;
|
|
16053
16162
|
var previous = oldProvider.models[modelIdx];
|
|
16054
16163
|
if (typeof previous === 'string') previous = { name: previous, display: previous };
|
|
16164
|
+
var tierMap = window.parseThinkingTierMap(tierMapEl ? tierMapEl.value : '');
|
|
16055
16165
|
var updated = Object.assign({}, previous, {
|
|
16056
16166
|
name: name,
|
|
16057
16167
|
display: name,
|
|
@@ -16060,6 +16170,8 @@ window.saveModelEdit = function(oldProvIdx, modelIdx) {
|
|
|
16060
16170
|
vision: !!(visionEl && visionEl.checked),
|
|
16061
16171
|
thinking: !!(thinkingEl && thinkingEl.checked)
|
|
16062
16172
|
});
|
|
16173
|
+
if (Object.keys(tierMap).length) updated.thinking_tier_map = tierMap;
|
|
16174
|
+
else delete updated.thinking_tier_map;
|
|
16063
16175
|
oldProvider.models.splice(modelIdx, 1);
|
|
16064
16176
|
if (!state.providers[newProvIdx].models) state.providers[newProvIdx].models = [];
|
|
16065
16177
|
state.providers[newProvIdx].models.push(updated);
|
|
@@ -16223,7 +16335,13 @@ window.validateAllModels = function() {
|
|
|
16223
16335
|
return state.modelValidationResults;
|
|
16224
16336
|
}).catch(function(err) {
|
|
16225
16337
|
document.body.classList.remove('model-evaluating');
|
|
16226
|
-
|
|
16338
|
+
var failedHtml = '<div style="color:#ff7777;font-size:12px;">' + esc(t('model.validationFailed')) + ': ' + esc(err.message) + '</div>';
|
|
16339
|
+
var body = document.getElementById('sub-win-body');
|
|
16340
|
+
if (body && document.getElementById('model-validation-progress') && els['sub-win-overlay'].classList.contains('open')) {
|
|
16341
|
+
body.innerHTML = failedHtml;
|
|
16342
|
+
} else {
|
|
16343
|
+
addMsg('assistant', redactSensitiveText('[Error] ' + t('model.validationFailed') + ': ' + err.message), 'error', '');
|
|
16344
|
+
}
|
|
16227
16345
|
return [];
|
|
16228
16346
|
}).finally(function() {
|
|
16229
16347
|
window.stopModelValidationProgressPolling();
|
|
@@ -16239,16 +16357,45 @@ window.renderModelValidationProgress = function(progress) {
|
|
|
16239
16357
|
var completedModels = Math.max(0, Number(progress.completedModels || 0));
|
|
16240
16358
|
var totalModels = Math.max(0, Number(progress.totalModels || 0));
|
|
16241
16359
|
var current = [String(progress.currentModel || ''), String(progress.currentCheck || '')].filter(Boolean).join(' · ');
|
|
16242
|
-
return '<div class="provider-card marquee-border">' +
|
|
16243
|
-
'<div style="display:flex;justify-content:space-between;gap:10px;"><span>' + esc(t('model.validating')) + '</span><strong>' + esc(String(percent)) + '%</strong></div>' +
|
|
16244
|
-
'<div role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="' + esc(String(percent)) + '" style="height:7px;margin-top:10px;border-radius:999px;background:var(--surface-strong);overflow:hidden;"><div style="height:100%;width:' + esc(String(percent)) + '%;background:var(--accent);transition:width .18s ease;"></div></div>' +
|
|
16245
|
-
'<div style="margin-top:8px;color:var(--text-dim);font-size:11px;display:flex;justify-content:space-between;gap:8px;"><span>' + esc(String(completedChecks)) + '/' + esc(String(totalChecks)) + ' ' + esc(t('model.validationChecks')) + '</span><span>' + esc(String(completedModels)) + '/' + esc(String(totalModels)) + ' ' + esc(t('model.validationModels')) + '</span></div>' +
|
|
16246
|
-
|
|
16360
|
+
return '<div class="provider-card marquee-border" id="model-validation-progress">' +
|
|
16361
|
+
'<div style="display:flex;justify-content:space-between;gap:10px;"><span>' + esc(t('model.validating')) + '</span><strong id="mv-percent">' + esc(String(percent)) + '%</strong></div>' +
|
|
16362
|
+
'<div id="mv-progressbar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="' + esc(String(percent)) + '" style="height:7px;margin-top:10px;border-radius:999px;background:var(--surface-strong);overflow:hidden;"><div id="mv-bar" style="height:100%;width:' + esc(String(percent)) + '%;background:var(--accent);transition:width .18s ease;"></div></div>' +
|
|
16363
|
+
'<div style="margin-top:8px;color:var(--text-dim);font-size:11px;display:flex;justify-content:space-between;gap:8px;"><span id="mv-checks">' + esc(String(completedChecks)) + '/' + esc(String(totalChecks)) + ' ' + esc(t('model.validationChecks')) + '</span><span id="mv-models">' + esc(String(completedModels)) + '/' + esc(String(totalModels)) + ' ' + esc(t('model.validationModels')) + '</span></div>' +
|
|
16364
|
+
'<div id="mv-current" style="margin-top:6px;color:var(--text-dim);font-size:11px;overflow-wrap:anywhere;' + (current ? '' : 'display:none;') + '">' + esc(t('model.validationCurrent')) + ': ' + esc(current) + '</div>' +
|
|
16247
16365
|
'</div><div style="margin-top:6px;color:var(--text-dim);font-size:11px;">' + esc(t('model.validationBackgroundNote')) + '</div>';
|
|
16248
16366
|
};
|
|
16249
16367
|
|
|
16368
|
+
window.updateModelValidationProgress = function(progress) {
|
|
16369
|
+
progress = progress || {};
|
|
16370
|
+
var body = document.getElementById('sub-win-body');
|
|
16371
|
+
if (!body) return;
|
|
16372
|
+
var percent = Math.max(0, Math.min(100, Number(progress.percent || 0)));
|
|
16373
|
+
var completedChecks = Math.max(0, Number(progress.completedChecks || 0));
|
|
16374
|
+
var totalChecks = Math.max(0, Number(progress.totalChecks || 0));
|
|
16375
|
+
var completedModels = Math.max(0, Number(progress.completedModels || 0));
|
|
16376
|
+
var totalModels = Math.max(0, Number(progress.totalModels || 0));
|
|
16377
|
+
var current = [String(progress.currentModel || ''), String(progress.currentCheck || '')].filter(Boolean).join(' · ');
|
|
16378
|
+
var percentEl = document.getElementById('mv-percent');
|
|
16379
|
+
if (!percentEl) return;
|
|
16380
|
+
percentEl.textContent = String(percent) + '%';
|
|
16381
|
+
var barEl = document.getElementById('mv-bar');
|
|
16382
|
+
if (barEl) barEl.style.width = String(percent) + '%';
|
|
16383
|
+
var progressbarEl = document.getElementById('mv-progressbar');
|
|
16384
|
+
if (progressbarEl) progressbarEl.setAttribute('aria-valuenow', String(percent));
|
|
16385
|
+
var checksEl = document.getElementById('mv-checks');
|
|
16386
|
+
if (checksEl) checksEl.textContent = String(completedChecks) + '/' + String(totalChecks) + ' ' + t('model.validationChecks');
|
|
16387
|
+
var modelsEl = document.getElementById('mv-models');
|
|
16388
|
+
if (modelsEl) modelsEl.textContent = String(completedModels) + '/' + String(totalModels) + ' ' + t('model.validationModels');
|
|
16389
|
+
var currentEl = document.getElementById('mv-current');
|
|
16390
|
+
if (currentEl) {
|
|
16391
|
+
currentEl.textContent = t('model.validationCurrent') + ': ' + current;
|
|
16392
|
+
currentEl.style.display = current ? '' : 'none';
|
|
16393
|
+
}
|
|
16394
|
+
};
|
|
16395
|
+
|
|
16250
16396
|
window.showModelValidationProgress = function(progress) {
|
|
16251
16397
|
document.body.classList.add('model-evaluating');
|
|
16398
|
+
if (document.getElementById('model-validation-progress')) return;
|
|
16252
16399
|
window.openSubWin(t('model.validationTitle'), window.renderModelValidationProgress(progress));
|
|
16253
16400
|
};
|
|
16254
16401
|
|
|
@@ -16264,7 +16411,7 @@ window.startModelValidationProgressPolling = function() {
|
|
|
16264
16411
|
Promise.resolve(api.modelValidationStatus()).then(function(progress) {
|
|
16265
16412
|
if (!state.modelValidationPromise) return;
|
|
16266
16413
|
var body = document.getElementById('sub-win-body');
|
|
16267
|
-
if (body && els['sub-win-overlay'].classList.contains('open'))
|
|
16414
|
+
if (body && els['sub-win-overlay'].classList.contains('open')) window.updateModelValidationProgress(progress);
|
|
16268
16415
|
state.modelValidationProgressTimer = setTimeout(poll, 150);
|
|
16269
16416
|
}).catch(function() {
|
|
16270
16417
|
if (state.modelValidationPromise) state.modelValidationProgressTimer = setTimeout(poll, 300);
|
|
@@ -16291,7 +16438,21 @@ window.showModelEvaluationResults = function(results) {
|
|
|
16291
16438
|
}
|
|
16292
16439
|
}
|
|
16293
16440
|
html += '</div>';
|
|
16294
|
-
|
|
16441
|
+
var body = document.getElementById('sub-win-body');
|
|
16442
|
+
if (body && document.getElementById('model-validation-progress') && els['sub-win-overlay'].classList.contains('open')) {
|
|
16443
|
+
// The progress window is still visible: replace it in place so closing
|
|
16444
|
+
// the results restores whatever window was open before validation.
|
|
16445
|
+
body.innerHTML = html;
|
|
16446
|
+
return;
|
|
16447
|
+
}
|
|
16448
|
+
// The user closed the progress window or opened another window while
|
|
16449
|
+
// validation was running. Do not hijack the current window; summarize in chat.
|
|
16450
|
+
var okCount = 0;
|
|
16451
|
+
for (var j = 0; j < (results || []).length; j++) {
|
|
16452
|
+
var status = String((results[j] && results[j].status) || '');
|
|
16453
|
+
if (status === 'verified' || status === 'degraded' || status === 'available') okCount++;
|
|
16454
|
+
}
|
|
16455
|
+
addMsg('assistant', '[System] ' + t('model.validationTitle') + ': ' + okCount + '/' + (results || []).length + ' ' + t('model.validationModels'), okCount === (results || []).length ? 'success' : 'warning', '');
|
|
16295
16456
|
};
|
|
16296
16457
|
renderArchiveSettings = function() {
|
|
16297
16458
|
if (api.listArchives && !state._allArchiveSettingsLoading) {
|
|
@@ -18895,11 +19056,15 @@ function renderConversations() {
|
|
|
18895
19056
|
if (runtimeState && ['running', 'stopping', 'force_restarting'].indexOf(String(runtimeState.status || '')) >= 0) div.classList.add('marquee-border');
|
|
18896
19057
|
var runtimeBadge = runtimeState && runtimeState.status && runtimeState.status !== 'idle'
|
|
18897
19058
|
? '<span class="conv-runtime-badge ' + escAttr(String(runtimeState.status)) + '">' + esc(String(runtimeState.status)) + '</span>' : '';
|
|
18898
|
-
var
|
|
18899
|
-
? '<span class="conv-branch-comm-
|
|
18900
|
-
|
|
19059
|
+
var branchCommIcon = conv.branchCommunication
|
|
19060
|
+
? '<span class="conv-branch-comm-icon" title="' + escAttr(t('conversation.branchCommunicationBadge')) + '" aria-label="' + escAttr(t('conversation.branchCommunicationBadge')) + '">' + iconSvg('git-branch', t('conversation.branchCommunicationBadge')) + '</span>' : '';
|
|
19061
|
+
var archivePendingKey = currentWorkspaceKey() + '::' + String(conv.id);
|
|
19062
|
+
var archiveBtn = state.conversationArchivePending[archivePendingKey]
|
|
19063
|
+
? '<button class="conv-archive-btn archiving" title="' + escAttr(t('archive.archiving')) + '" disabled><span class="conv-archive-spinner"></span></button>'
|
|
19064
|
+
: '<button class="conv-archive-btn" onclick="event.stopPropagation();window.archiveConv(this.closest(".conv-item").getAttribute("data-conversation-id"))" title="' + escAttr(t('conversation.archive')) + '">' + iconOnly('archive', t('conversation.archive')) + '</button>';
|
|
19065
|
+
div.innerHTML = '<span class="conv-summary" title="' + escAttr(String(conv.id || '')) + '">' + esc(displaySummary) + (conv.messageCount ? ' (' + esc(String(conv.messageCount)) + ')' : '') + '</span>' + branchCommIcon + runtimeBadge +
|
|
18901
19066
|
'<button class="conv-rename-btn" onclick="event.stopPropagation();window.editConversationName(' + i + ')" title="' + escAttr(t('conversation.rename')) + '">' + iconOnly('pencil', t('conversation.rename')) + '</button>' +
|
|
18902
|
-
|
|
19067
|
+
archiveBtn +
|
|
18903
19068
|
'<button class="conv-pin-btn' + (conv.pinned ? ' active' : '') + '" onclick="event.stopPropagation();window.toggleConversationPinned(' + i + ')" title="' + escAttr(conv.pinned ? t('conversation.unpin') : t('conversation.pin')) + '">' + iconOnly('pin', conv.pinned ? t('conversation.unpin') : t('conversation.pin')) + '</button>';
|
|
18904
19069
|
div.onclick = function(idx) { return function() { window.switchConversation(idx); }; }(i);
|
|
18905
19070
|
div.addEventListener('keydown', window.handleConversationKey);
|
|
@@ -19052,7 +19217,7 @@ window.showNewConversationPage = function() {
|
|
|
19052
19217
|
var html = '<div style="display:flex;flex-direction:column;gap:12px;padding:4px 2px;">' +
|
|
19053
19218
|
'<div style="font-size:12px;color:var(--text-dim);line-height:1.5;">' + esc(t('workspace.newConversationDesc')) + '</div>' +
|
|
19054
19219
|
'<div class="auto-input-group"><label>' + esc(t('status.workspace')) + '</label><select id="new-conv-ws">' + options + '</select></div>' +
|
|
19055
|
-
'<div class="auto-input-group
|
|
19220
|
+
'<div class="auto-input-group checkbox-row"><label><input type="checkbox" id="new-conv-branch-comm"><span>' + esc(t('conversation.branchCommunication')) + '</span></label></div>' +
|
|
19056
19221
|
'<div style="display:flex;gap:8px;">' +
|
|
19057
19222
|
'<button class="sec-btn primary" style="flex:1;" onclick="window.doNewConversationFromPage()">' + esc(t('workspace.createConversation')) + '</button>' +
|
|
19058
19223
|
'<button class="sec-btn" style="flex:1;" onclick="window.showNewWorkspaceDialog()">' + esc(t('workspace.createAction')) + '</button>' +
|
|
@@ -19196,45 +19361,45 @@ window.archiveConv = function(conversationId) {
|
|
|
19196
19361
|
orderIds: rollbackOrder,
|
|
19197
19362
|
chatHtml: priorActiveId === targetId && els['chat-area'] ? els['chat-area'].innerHTML : ''
|
|
19198
19363
|
};
|
|
19199
|
-
|
|
19200
|
-
if (!convs.length) convs.push({ id: 'default', summary: t('workspace.defaultConversation'), archived: false, active: true });
|
|
19201
|
-
var nextActiveId = priorActiveId && priorActiveId !== targetId ? priorActiveId : String(convs[Math.min(idx, convs.length - 1)].id || 'default');
|
|
19202
|
-
var nextActiveIndex = Math.max(0, convs.findIndex(function(item) { return String(item && item.id || '') === nextActiveId; }));
|
|
19203
|
-
for (var i = 0; i < convs.length; i++) convs[i].active = i === nextActiveIndex;
|
|
19204
|
-
state.workspaceActiveConversation[workspaceKey] = nextActiveIndex;
|
|
19205
|
-
state.activeConversation = nextActiveIndex;
|
|
19206
|
-
state.conversations = convs;
|
|
19207
|
-
if (priorActiveId === targetId) {
|
|
19208
|
-
state.activeBackendConversationId = nextActiveId;
|
|
19209
|
-
if (els['chat-area']) els['chat-area'].innerHTML = '';
|
|
19210
|
-
}
|
|
19211
|
-
// Archiving is a destructive handoff: remove the target's Flow takeover
|
|
19212
|
-
// locally at click time as well as removing its conversation row. The
|
|
19213
|
-
// backend cancellation/manifest write is asynchronous; a late Flow
|
|
19214
|
-
// promise must not leave a visible running bubble over the replacement
|
|
19215
|
-
// conversation while the archive is already in flight.
|
|
19216
|
-
if (state.flowTakeovers) {
|
|
19217
|
-
var archivedFlowKey = runtimeKeyFor(targetRuntime.workspaceId, targetRuntime.conversationId);
|
|
19218
|
-
var archivedFlowRecord = state.flowTakeovers[archivedFlowKey];
|
|
19219
|
-
if (archivedFlowRecord) {
|
|
19220
|
-
archivedFlowRecord.running = false;
|
|
19221
|
-
archivedFlowRecord.paused = false;
|
|
19222
|
-
archivedFlowRecord.runtimeLease = null;
|
|
19223
|
-
archivedFlowRecord.queueLease = null;
|
|
19224
|
-
delete state.flowTakeovers[archivedFlowKey];
|
|
19225
|
-
}
|
|
19226
|
-
if (priorActiveId === targetId && window.renderFlowTakeover) {
|
|
19227
|
-
window.renderFlowTakeover(false, '', { target: targetRuntime });
|
|
19228
|
-
}
|
|
19229
|
-
}
|
|
19230
|
-
setConversationRuntimeState(targetRuntime, 'idle', '');
|
|
19231
|
-
setWorking(!!runningConversationRecord(activeConversationId()));
|
|
19364
|
+
// 归档中:不立即剔除行,按钮转圈等待;后端完成归档后再剔除前端。
|
|
19232
19365
|
renderConversations();
|
|
19233
|
-
if (priorActiveId === targetId) scheduleConversationArchiveActiveSync(workspaceKey);
|
|
19234
19366
|
var archivePromise = api.archive ? api.archive(targetRuntime) : Promise.reject(new Error('Archive API unavailable'));
|
|
19235
19367
|
archivePromise.then(function(receipt) {
|
|
19236
19368
|
if (!receipt || receipt.ok !== true) throw new Error((receipt && receipt.error) || 'Archive failed');
|
|
19237
19369
|
delete state.conversationArchivePending[pendingKey];
|
|
19370
|
+
// 后端完成归档:现在才剔除前端行 + 切换 active + 清理 Flow takeover。
|
|
19371
|
+
var currentConvs = currentWorkspaceConversations();
|
|
19372
|
+
var currentIdx = currentConvs.findIndex(function(item) { return String(item && item.id || 'default') === targetId; });
|
|
19373
|
+
if (currentIdx >= 0) currentConvs.splice(currentIdx, 1);
|
|
19374
|
+
if (!currentConvs.length) currentConvs.push({ id: 'default', summary: t('workspace.defaultConversation'), archived: false, active: true });
|
|
19375
|
+
var nextActiveId = priorActiveId && priorActiveId !== targetId ? priorActiveId : String(currentConvs[Math.min(Math.max(currentIdx, 0), currentConvs.length - 1)].id || 'default');
|
|
19376
|
+
var nextActiveIndex = Math.max(0, currentConvs.findIndex(function(item) { return String(item && item.id || '') === nextActiveId; }));
|
|
19377
|
+
for (var i = 0; i < currentConvs.length; i++) currentConvs[i].active = i === nextActiveIndex;
|
|
19378
|
+
state.workspaceActiveConversation[workspaceKey] = nextActiveIndex;
|
|
19379
|
+
state.activeConversation = nextActiveIndex;
|
|
19380
|
+
state.conversations = currentConvs;
|
|
19381
|
+
if (priorActiveId === targetId) {
|
|
19382
|
+
state.activeBackendConversationId = nextActiveId;
|
|
19383
|
+
if (els['chat-area']) els['chat-area'].innerHTML = '';
|
|
19384
|
+
}
|
|
19385
|
+
if (state.flowTakeovers) {
|
|
19386
|
+
var archivedFlowKey = runtimeKeyFor(targetRuntime.workspaceId, targetRuntime.conversationId);
|
|
19387
|
+
var archivedFlowRecord = state.flowTakeovers[archivedFlowKey];
|
|
19388
|
+
if (archivedFlowRecord) {
|
|
19389
|
+
archivedFlowRecord.running = false;
|
|
19390
|
+
archivedFlowRecord.paused = false;
|
|
19391
|
+
archivedFlowRecord.runtimeLease = null;
|
|
19392
|
+
archivedFlowRecord.queueLease = null;
|
|
19393
|
+
delete state.flowTakeovers[archivedFlowKey];
|
|
19394
|
+
}
|
|
19395
|
+
if (priorActiveId === targetId && window.renderFlowTakeover) {
|
|
19396
|
+
window.renderFlowTakeover(false, '', { target: targetRuntime });
|
|
19397
|
+
}
|
|
19398
|
+
}
|
|
19399
|
+
setConversationRuntimeState(targetRuntime, 'idle', '');
|
|
19400
|
+
setWorking(!!runningConversationRecord(activeConversationId()));
|
|
19401
|
+
renderConversations();
|
|
19402
|
+
if (priorActiveId === targetId) scheduleConversationArchiveActiveSync(workspaceKey);
|
|
19238
19403
|
var optimisticArchive = {
|
|
19239
19404
|
id: receipt.fileName,
|
|
19240
19405
|
name: receipt.fileName,
|
|
@@ -19262,10 +19427,8 @@ window.archiveConv = function(conversationId) {
|
|
|
19262
19427
|
scheduleConversationArchiveRefresh(workspaceKey);
|
|
19263
19428
|
}).catch(function(err) {
|
|
19264
19429
|
delete state.conversationArchivePending[pendingKey];
|
|
19265
|
-
//
|
|
19266
|
-
|
|
19267
|
-
// the user's pointer; the next explicit workspace refresh is the only
|
|
19268
|
-
// path allowed to reconcile a failed destructive operation.
|
|
19430
|
+
// 归档失败:恢复按钮,保留行(不再乐观剔除)。
|
|
19431
|
+
renderConversations();
|
|
19269
19432
|
showUiNotice('[Archive] ' + t('workspace.saveFailed') + ': ' + (err.message || String(err)), 'error', 'archive-failed-' + targetId);
|
|
19270
19433
|
});
|
|
19271
19434
|
}
|
|
@@ -22511,6 +22674,11 @@ function schedulePostStartupUiRendering() {
|
|
|
22511
22674
|
// navigation surfaces render after promotion on cancellable browser tasks.
|
|
22512
22675
|
updateWorkspaceGate();
|
|
22513
22676
|
|
|
22677
|
+
if (document.documentElement.classList.contains('config-reloading')) {
|
|
22678
|
+
document.documentElement.classList.remove('config-reloading');
|
|
22679
|
+
try { sessionStorage.removeItem('newmark-config-reloading'); } catch (_) {}
|
|
22680
|
+
}
|
|
22681
|
+
|
|
22514
22682
|
// === Event Listeners ===
|
|
22515
22683
|
function escapeBelongsToFocusedControl(event) {
|
|
22516
22684
|
var target = event && event.target;
|
|
@@ -112,6 +112,11 @@
|
|
|
112
112
|
<symbol id="folder" viewBox="0 0 24 24">
|
|
113
113
|
<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />
|
|
114
114
|
</symbol>
|
|
115
|
+
<symbol id="git-branch" viewBox="0 0 24 24">
|
|
116
|
+
<path d="M15 6a9 9 0 0 0-9 9V3" />
|
|
117
|
+
<circle cx="18" cy="6" r="3" />
|
|
118
|
+
<circle cx="6" cy="18" r="3" />
|
|
119
|
+
</symbol>
|
|
115
120
|
<symbol id="globe" viewBox="0 0 24 24">
|
|
116
121
|
<circle cx="12" cy="12" r="10" />
|
|
117
122
|
<path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" />
|