newmark-agent 0.4.0 → 0.4.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/dist/conversation-utility-host.bundle.cjs +112 -1
- package/dist/core/agent.js +2 -0
- package/dist/core/toolPolicy.d.ts +9 -0
- package/dist/core/toolPolicy.js +125 -0
- package/dist/toolchain/registry-seeder.js +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +28 -0
- 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 +152 -61
- package/dist/tui/src/state.js +83 -0
- package/dist/ui/index.html +172 -62
- package/dist/ui/lucide-sprite.svg +5 -0
- package/dist/wsl-agent-host.bundle.cjs +112 -1
- package/package.json +4 -10
- 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/tui/src/state.js
CHANGED
|
@@ -197,9 +197,14 @@ function createState(options = {}) {
|
|
|
197
197
|
inputCursor: 0,
|
|
198
198
|
conversationScroll: 0,
|
|
199
199
|
conversationMaxScroll: 0,
|
|
200
|
+
contentScroll: 0,
|
|
201
|
+
contentFocusLine: -1,
|
|
200
202
|
conversationHistoryFocus: false,
|
|
201
203
|
historySelectedIndex: -1,
|
|
202
204
|
historySelectedImageIndex: -1,
|
|
205
|
+
historyEventFocus: false,
|
|
206
|
+
historyEventIndex: -1,
|
|
207
|
+
collapsedBuildEvents: new Set(),
|
|
203
208
|
historyVisibleRunIds: [],
|
|
204
209
|
historyCursorDirection: 0,
|
|
205
210
|
expandedBuildRuns: new Set(
|
|
@@ -549,6 +554,8 @@ function switchView(state, id) {
|
|
|
549
554
|
state.input = "";
|
|
550
555
|
state.inputCursor = 0;
|
|
551
556
|
if (id === "chat") state.conversationScroll = 0;
|
|
557
|
+
state.contentScroll = 0;
|
|
558
|
+
state.contentFocusLine = -1;
|
|
552
559
|
}
|
|
553
560
|
|
|
554
561
|
function normalizedAutomation(item) {
|
|
@@ -1330,6 +1337,76 @@ function filteredCommands(state) {
|
|
|
1330
1337
|
return data.commands.filter((command) => command.label.toLowerCase().includes(query));
|
|
1331
1338
|
}
|
|
1332
1339
|
|
|
1340
|
+
function focusableEventsForRun(run) {
|
|
1341
|
+
return (run?.events || [])
|
|
1342
|
+
.filter((event) => {
|
|
1343
|
+
const type = String(event?.type || "").toLowerCase();
|
|
1344
|
+
return type && type !== "final_response" && !type.startsWith("guide");
|
|
1345
|
+
})
|
|
1346
|
+
.sort((left, right) => {
|
|
1347
|
+
const leftSeq = Number(left?.sequence);
|
|
1348
|
+
const rightSeq = Number(right?.sequence);
|
|
1349
|
+
if (Number.isFinite(leftSeq) && Number.isFinite(rightSeq) && leftSeq !== rightSeq) return leftSeq - rightSeq;
|
|
1350
|
+
const leftTime = new Date(left?.timestamp || left?.createdAt || "").getTime();
|
|
1351
|
+
const rightTime = new Date(right?.timestamp || right?.createdAt || "").getTime();
|
|
1352
|
+
return (Number.isFinite(leftTime) ? leftTime : 0) - (Number.isFinite(rightTime) ? rightTime : 0);
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
function buildEventKey(event, index) {
|
|
1357
|
+
return String(event?.id || event?.toolCallId || `${event?.type || "event"}:${event?.toolName || ""}:${index}`);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
function selectedHistoryRun(state) {
|
|
1361
|
+
const runs = [...(state.snapshot.workRuns || [])].sort((left, right) => Number(left.sequence || 0) - Number(right.sequence || 0));
|
|
1362
|
+
return runs[Number(state.historySelectedIndex) || 0];
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
function enterHistoryEventFocus(state) {
|
|
1366
|
+
const run = selectedHistoryRun(state);
|
|
1367
|
+
const events = focusableEventsForRun(run);
|
|
1368
|
+
if (!run || !state.expandedBuildRuns?.has(run.runId) || !events.length) return false;
|
|
1369
|
+
state.historyEventFocus = true;
|
|
1370
|
+
state.historyEventIndex = 0;
|
|
1371
|
+
state.historySelectedImageIndex = -1;
|
|
1372
|
+
state.notice = `History focus · ${events.length} item(s) · Enter expand · ← back`;
|
|
1373
|
+
return true;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
function exitHistoryEventFocus(state) {
|
|
1377
|
+
state.historyEventFocus = false;
|
|
1378
|
+
state.historyEventIndex = -1;
|
|
1379
|
+
state.notice = "History focus · Build Block · Enter expands";
|
|
1380
|
+
return true;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
function moveHistoryEventCursor(state, direction) {
|
|
1384
|
+
const run = selectedHistoryRun(state);
|
|
1385
|
+
const events = focusableEventsForRun(run);
|
|
1386
|
+
if (!events.length) return false;
|
|
1387
|
+
const count = events.length;
|
|
1388
|
+
state.historyEventIndex = ((Number(state.historyEventIndex) || 0) + direction + count) % count;
|
|
1389
|
+
state.notice = `History focus · item ${state.historyEventIndex + 1}/${count} · Enter expand`;
|
|
1390
|
+
return true;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
function toggleSelectedBuildEvent(state) {
|
|
1394
|
+
const run = selectedHistoryRun(state);
|
|
1395
|
+
const events = focusableEventsForRun(run);
|
|
1396
|
+
const index = Number(state.historyEventIndex) || 0;
|
|
1397
|
+
const event = events[index];
|
|
1398
|
+
if (!event) return false;
|
|
1399
|
+
const key = buildEventKey(event, index);
|
|
1400
|
+
if (state.collapsedBuildEvents.has(key)) {
|
|
1401
|
+
state.collapsedBuildEvents.delete(key);
|
|
1402
|
+
state.notice = "Event expanded";
|
|
1403
|
+
} else {
|
|
1404
|
+
state.collapsedBuildEvents.add(key);
|
|
1405
|
+
state.notice = "Event collapsed";
|
|
1406
|
+
}
|
|
1407
|
+
return true;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1333
1410
|
module.exports = {
|
|
1334
1411
|
activeConversationModelLabel,
|
|
1335
1412
|
INTELLIGENCE_TIERS,
|
|
@@ -1341,6 +1418,7 @@ module.exports = {
|
|
|
1341
1418
|
applyConversationResult,
|
|
1342
1419
|
beginAutomationCreate,
|
|
1343
1420
|
beginWorkflowCreate,
|
|
1421
|
+
buildEventKey,
|
|
1344
1422
|
conversationModelOptions,
|
|
1345
1423
|
createAutomationFromDraft,
|
|
1346
1424
|
createState,
|
|
@@ -1349,7 +1427,10 @@ module.exports = {
|
|
|
1349
1427
|
cycleMemoryComponent,
|
|
1350
1428
|
cycleSettingsTab,
|
|
1351
1429
|
enterConversation,
|
|
1430
|
+
enterHistoryEventFocus,
|
|
1431
|
+
exitHistoryEventFocus,
|
|
1352
1432
|
filteredCommands,
|
|
1433
|
+
focusableEventsForRun,
|
|
1353
1434
|
itemCount,
|
|
1354
1435
|
memoryColumnItems,
|
|
1355
1436
|
memoryTagOptions,
|
|
@@ -1358,6 +1439,7 @@ module.exports = {
|
|
|
1358
1439
|
moveMenuSelection,
|
|
1359
1440
|
moveFocusHorizontal,
|
|
1360
1441
|
moveConversationHistoryCursor,
|
|
1442
|
+
moveHistoryEventCursor,
|
|
1361
1443
|
moveInputCursorVertical,
|
|
1362
1444
|
moveSettingChoiceSelection,
|
|
1363
1445
|
moveSelection,
|
|
@@ -1378,6 +1460,7 @@ module.exports = {
|
|
|
1378
1460
|
toggleSelected,
|
|
1379
1461
|
toggleConversationPinned,
|
|
1380
1462
|
toggleSelectedBuildBlock,
|
|
1463
|
+
toggleSelectedBuildEvent,
|
|
1381
1464
|
validateSelectedModel,
|
|
1382
1465
|
workspaceMenuChildren
|
|
1383
1466
|
};
|
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,
|
|
@@ -5009,6 +5030,32 @@ html.newmark-memory-overview-viewer body {
|
|
|
5009
5030
|
.auto-input-group select:focus,
|
|
5010
5031
|
.auto-input-group textarea:focus { border-color: var(--accent); }
|
|
5011
5032
|
|
|
5033
|
+
.auto-input-group.checkbox-row {
|
|
5034
|
+
display: flex;
|
|
5035
|
+
padding: 9px 11px;
|
|
5036
|
+
border: 1px solid var(--border);
|
|
5037
|
+
border-radius: var(--radius-md);
|
|
5038
|
+
background: var(--glass-bg-1);
|
|
5039
|
+
}
|
|
5040
|
+
.auto-input-group.checkbox-row label {
|
|
5041
|
+
display: flex;
|
|
5042
|
+
align-items: center;
|
|
5043
|
+
gap: 8px;
|
|
5044
|
+
margin: 0;
|
|
5045
|
+
cursor: pointer;
|
|
5046
|
+
font-size: 12px;
|
|
5047
|
+
color: var(--text);
|
|
5048
|
+
}
|
|
5049
|
+
.auto-input-group.checkbox-row input[type="checkbox"] {
|
|
5050
|
+
width: 15px;
|
|
5051
|
+
height: 15px;
|
|
5052
|
+
flex-shrink: 0;
|
|
5053
|
+
accent-color: var(--accent);
|
|
5054
|
+
cursor: pointer;
|
|
5055
|
+
margin: 0;
|
|
5056
|
+
padding: 0;
|
|
5057
|
+
}
|
|
5058
|
+
|
|
5012
5059
|
.auto-conditions {
|
|
5013
5060
|
display: flex;
|
|
5014
5061
|
gap: 8px;
|
|
@@ -5328,6 +5375,11 @@ html.newmark-memory-overview-viewer body {
|
|
|
5328
5375
|
<symbol id="folder" viewBox="0 0 24 24">
|
|
5329
5376
|
<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
5377
|
</symbol>
|
|
5378
|
+
<symbol id="git-branch" viewBox="0 0 24 24">
|
|
5379
|
+
<path d="M15 6a9 9 0 0 0-9 9V3" />
|
|
5380
|
+
<circle cx="18" cy="6" r="3" />
|
|
5381
|
+
<circle cx="6" cy="18" r="3" />
|
|
5382
|
+
</symbol>
|
|
5331
5383
|
<symbol id="globe" viewBox="0 0 24 24">
|
|
5332
5384
|
<circle cx="12" cy="12" r="10" />
|
|
5333
5385
|
<path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" />
|
|
@@ -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',
|
|
@@ -7190,6 +7243,7 @@ var NEWMARK_I18N = {
|
|
|
7190
7243
|
'model.yes': '是',
|
|
7191
7244
|
'model.notChecked': '未校验',
|
|
7192
7245
|
'archive.current': '归档当前对话',
|
|
7246
|
+
'archive.archiving': '归档中...',
|
|
7193
7247
|
'archive.empty': '暂无归档。',
|
|
7194
7248
|
'archive.loading': '正在加载工作区归档...',
|
|
7195
7249
|
'archive.unavailable': '归档列表不可用',
|
|
@@ -15545,8 +15599,8 @@ window.refreshGlobalConfigFile = function() {
|
|
|
15545
15599
|
if (!api.reloadGlobalConfig) return;
|
|
15546
15600
|
api.reloadGlobalConfig().then(function(result) {
|
|
15547
15601
|
if (result && result.error) throw new Error(result.error);
|
|
15548
|
-
|
|
15549
|
-
|
|
15602
|
+
try { sessionStorage.setItem('newmark-config-reloading', '1'); } catch (_) {}
|
|
15603
|
+
window.location.reload();
|
|
15550
15604
|
}).catch(function(error) {
|
|
15551
15605
|
showUiNotice(error && error.message ? error.message : String(error), 'error', 'global-config-refresh');
|
|
15552
15606
|
});
|
|
@@ -16223,7 +16277,13 @@ window.validateAllModels = function() {
|
|
|
16223
16277
|
return state.modelValidationResults;
|
|
16224
16278
|
}).catch(function(err) {
|
|
16225
16279
|
document.body.classList.remove('model-evaluating');
|
|
16226
|
-
|
|
16280
|
+
var failedHtml = '<div style="color:#ff7777;font-size:12px;">' + esc(t('model.validationFailed')) + ': ' + esc(err.message) + '</div>';
|
|
16281
|
+
var body = document.getElementById('sub-win-body');
|
|
16282
|
+
if (body && document.getElementById('model-validation-progress') && els['sub-win-overlay'].classList.contains('open')) {
|
|
16283
|
+
body.innerHTML = failedHtml;
|
|
16284
|
+
} else {
|
|
16285
|
+
addMsg('assistant', redactSensitiveText('[Error] ' + t('model.validationFailed') + ': ' + err.message), 'error', '');
|
|
16286
|
+
}
|
|
16227
16287
|
return [];
|
|
16228
16288
|
}).finally(function() {
|
|
16229
16289
|
window.stopModelValidationProgressPolling();
|
|
@@ -16239,16 +16299,45 @@ window.renderModelValidationProgress = function(progress) {
|
|
|
16239
16299
|
var completedModels = Math.max(0, Number(progress.completedModels || 0));
|
|
16240
16300
|
var totalModels = Math.max(0, Number(progress.totalModels || 0));
|
|
16241
16301
|
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
|
-
|
|
16302
|
+
return '<div class="provider-card marquee-border" id="model-validation-progress">' +
|
|
16303
|
+
'<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>' +
|
|
16304
|
+
'<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>' +
|
|
16305
|
+
'<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>' +
|
|
16306
|
+
'<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
16307
|
'</div><div style="margin-top:6px;color:var(--text-dim);font-size:11px;">' + esc(t('model.validationBackgroundNote')) + '</div>';
|
|
16248
16308
|
};
|
|
16249
16309
|
|
|
16310
|
+
window.updateModelValidationProgress = function(progress) {
|
|
16311
|
+
progress = progress || {};
|
|
16312
|
+
var body = document.getElementById('sub-win-body');
|
|
16313
|
+
if (!body) return;
|
|
16314
|
+
var percent = Math.max(0, Math.min(100, Number(progress.percent || 0)));
|
|
16315
|
+
var completedChecks = Math.max(0, Number(progress.completedChecks || 0));
|
|
16316
|
+
var totalChecks = Math.max(0, Number(progress.totalChecks || 0));
|
|
16317
|
+
var completedModels = Math.max(0, Number(progress.completedModels || 0));
|
|
16318
|
+
var totalModels = Math.max(0, Number(progress.totalModels || 0));
|
|
16319
|
+
var current = [String(progress.currentModel || ''), String(progress.currentCheck || '')].filter(Boolean).join(' · ');
|
|
16320
|
+
var percentEl = document.getElementById('mv-percent');
|
|
16321
|
+
if (!percentEl) return;
|
|
16322
|
+
percentEl.textContent = String(percent) + '%';
|
|
16323
|
+
var barEl = document.getElementById('mv-bar');
|
|
16324
|
+
if (barEl) barEl.style.width = String(percent) + '%';
|
|
16325
|
+
var progressbarEl = document.getElementById('mv-progressbar');
|
|
16326
|
+
if (progressbarEl) progressbarEl.setAttribute('aria-valuenow', String(percent));
|
|
16327
|
+
var checksEl = document.getElementById('mv-checks');
|
|
16328
|
+
if (checksEl) checksEl.textContent = String(completedChecks) + '/' + String(totalChecks) + ' ' + t('model.validationChecks');
|
|
16329
|
+
var modelsEl = document.getElementById('mv-models');
|
|
16330
|
+
if (modelsEl) modelsEl.textContent = String(completedModels) + '/' + String(totalModels) + ' ' + t('model.validationModels');
|
|
16331
|
+
var currentEl = document.getElementById('mv-current');
|
|
16332
|
+
if (currentEl) {
|
|
16333
|
+
currentEl.textContent = t('model.validationCurrent') + ': ' + current;
|
|
16334
|
+
currentEl.style.display = current ? '' : 'none';
|
|
16335
|
+
}
|
|
16336
|
+
};
|
|
16337
|
+
|
|
16250
16338
|
window.showModelValidationProgress = function(progress) {
|
|
16251
16339
|
document.body.classList.add('model-evaluating');
|
|
16340
|
+
if (document.getElementById('model-validation-progress')) return;
|
|
16252
16341
|
window.openSubWin(t('model.validationTitle'), window.renderModelValidationProgress(progress));
|
|
16253
16342
|
};
|
|
16254
16343
|
|
|
@@ -16264,7 +16353,7 @@ window.startModelValidationProgressPolling = function() {
|
|
|
16264
16353
|
Promise.resolve(api.modelValidationStatus()).then(function(progress) {
|
|
16265
16354
|
if (!state.modelValidationPromise) return;
|
|
16266
16355
|
var body = document.getElementById('sub-win-body');
|
|
16267
|
-
if (body && els['sub-win-overlay'].classList.contains('open'))
|
|
16356
|
+
if (body && els['sub-win-overlay'].classList.contains('open')) window.updateModelValidationProgress(progress);
|
|
16268
16357
|
state.modelValidationProgressTimer = setTimeout(poll, 150);
|
|
16269
16358
|
}).catch(function() {
|
|
16270
16359
|
if (state.modelValidationPromise) state.modelValidationProgressTimer = setTimeout(poll, 300);
|
|
@@ -16291,7 +16380,21 @@ window.showModelEvaluationResults = function(results) {
|
|
|
16291
16380
|
}
|
|
16292
16381
|
}
|
|
16293
16382
|
html += '</div>';
|
|
16294
|
-
|
|
16383
|
+
var body = document.getElementById('sub-win-body');
|
|
16384
|
+
if (body && document.getElementById('model-validation-progress') && els['sub-win-overlay'].classList.contains('open')) {
|
|
16385
|
+
// The progress window is still visible: replace it in place so closing
|
|
16386
|
+
// the results restores whatever window was open before validation.
|
|
16387
|
+
body.innerHTML = html;
|
|
16388
|
+
return;
|
|
16389
|
+
}
|
|
16390
|
+
// The user closed the progress window or opened another window while
|
|
16391
|
+
// validation was running. Do not hijack the current window; summarize in chat.
|
|
16392
|
+
var okCount = 0;
|
|
16393
|
+
for (var j = 0; j < (results || []).length; j++) {
|
|
16394
|
+
var status = String((results[j] && results[j].status) || '');
|
|
16395
|
+
if (status === 'verified' || status === 'degraded' || status === 'available') okCount++;
|
|
16396
|
+
}
|
|
16397
|
+
addMsg('assistant', '[System] ' + t('model.validationTitle') + ': ' + okCount + '/' + (results || []).length + ' ' + t('model.validationModels'), okCount === (results || []).length ? 'success' : 'warning', '');
|
|
16295
16398
|
};
|
|
16296
16399
|
renderArchiveSettings = function() {
|
|
16297
16400
|
if (api.listArchives && !state._allArchiveSettingsLoading) {
|
|
@@ -18895,11 +18998,15 @@ function renderConversations() {
|
|
|
18895
18998
|
if (runtimeState && ['running', 'stopping', 'force_restarting'].indexOf(String(runtimeState.status || '')) >= 0) div.classList.add('marquee-border');
|
|
18896
18999
|
var runtimeBadge = runtimeState && runtimeState.status && runtimeState.status !== 'idle'
|
|
18897
19000
|
? '<span class="conv-runtime-badge ' + escAttr(String(runtimeState.status)) + '">' + esc(String(runtimeState.status)) + '</span>' : '';
|
|
18898
|
-
var
|
|
18899
|
-
? '<span class="conv-branch-comm-
|
|
18900
|
-
|
|
19001
|
+
var branchCommIcon = conv.branchCommunication
|
|
19002
|
+
? '<span class="conv-branch-comm-icon" title="' + escAttr(t('conversation.branchCommunicationBadge')) + '" aria-label="' + escAttr(t('conversation.branchCommunicationBadge')) + '">' + iconSvg('git-branch', t('conversation.branchCommunicationBadge')) + '</span>' : '';
|
|
19003
|
+
var archivePendingKey = currentWorkspaceKey() + '::' + String(conv.id);
|
|
19004
|
+
var archiveBtn = state.conversationArchivePending[archivePendingKey]
|
|
19005
|
+
? '<button class="conv-archive-btn archiving" title="' + escAttr(t('archive.archiving')) + '" disabled><span class="conv-archive-spinner"></span></button>'
|
|
19006
|
+
: '<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>';
|
|
19007
|
+
div.innerHTML = '<span class="conv-summary" title="' + escAttr(String(conv.id || '')) + '">' + esc(displaySummary) + (conv.messageCount ? ' (' + esc(String(conv.messageCount)) + ')' : '') + '</span>' + branchCommIcon + runtimeBadge +
|
|
18901
19008
|
'<button class="conv-rename-btn" onclick="event.stopPropagation();window.editConversationName(' + i + ')" title="' + escAttr(t('conversation.rename')) + '">' + iconOnly('pencil', t('conversation.rename')) + '</button>' +
|
|
18902
|
-
|
|
19009
|
+
archiveBtn +
|
|
18903
19010
|
'<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
19011
|
div.onclick = function(idx) { return function() { window.switchConversation(idx); }; }(i);
|
|
18905
19012
|
div.addEventListener('keydown', window.handleConversationKey);
|
|
@@ -19052,7 +19159,7 @@ window.showNewConversationPage = function() {
|
|
|
19052
19159
|
var html = '<div style="display:flex;flex-direction:column;gap:12px;padding:4px 2px;">' +
|
|
19053
19160
|
'<div style="font-size:12px;color:var(--text-dim);line-height:1.5;">' + esc(t('workspace.newConversationDesc')) + '</div>' +
|
|
19054
19161
|
'<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
|
|
19162
|
+
'<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
19163
|
'<div style="display:flex;gap:8px;">' +
|
|
19057
19164
|
'<button class="sec-btn primary" style="flex:1;" onclick="window.doNewConversationFromPage()">' + esc(t('workspace.createConversation')) + '</button>' +
|
|
19058
19165
|
'<button class="sec-btn" style="flex:1;" onclick="window.showNewWorkspaceDialog()">' + esc(t('workspace.createAction')) + '</button>' +
|
|
@@ -19196,45 +19303,45 @@ window.archiveConv = function(conversationId) {
|
|
|
19196
19303
|
orderIds: rollbackOrder,
|
|
19197
19304
|
chatHtml: priorActiveId === targetId && els['chat-area'] ? els['chat-area'].innerHTML : ''
|
|
19198
19305
|
};
|
|
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()));
|
|
19306
|
+
// 归档中:不立即剔除行,按钮转圈等待;后端完成归档后再剔除前端。
|
|
19232
19307
|
renderConversations();
|
|
19233
|
-
if (priorActiveId === targetId) scheduleConversationArchiveActiveSync(workspaceKey);
|
|
19234
19308
|
var archivePromise = api.archive ? api.archive(targetRuntime) : Promise.reject(new Error('Archive API unavailable'));
|
|
19235
19309
|
archivePromise.then(function(receipt) {
|
|
19236
19310
|
if (!receipt || receipt.ok !== true) throw new Error((receipt && receipt.error) || 'Archive failed');
|
|
19237
19311
|
delete state.conversationArchivePending[pendingKey];
|
|
19312
|
+
// 后端完成归档:现在才剔除前端行 + 切换 active + 清理 Flow takeover。
|
|
19313
|
+
var currentConvs = currentWorkspaceConversations();
|
|
19314
|
+
var currentIdx = currentConvs.findIndex(function(item) { return String(item && item.id || 'default') === targetId; });
|
|
19315
|
+
if (currentIdx >= 0) currentConvs.splice(currentIdx, 1);
|
|
19316
|
+
if (!currentConvs.length) currentConvs.push({ id: 'default', summary: t('workspace.defaultConversation'), archived: false, active: true });
|
|
19317
|
+
var nextActiveId = priorActiveId && priorActiveId !== targetId ? priorActiveId : String(currentConvs[Math.min(Math.max(currentIdx, 0), currentConvs.length - 1)].id || 'default');
|
|
19318
|
+
var nextActiveIndex = Math.max(0, currentConvs.findIndex(function(item) { return String(item && item.id || '') === nextActiveId; }));
|
|
19319
|
+
for (var i = 0; i < currentConvs.length; i++) currentConvs[i].active = i === nextActiveIndex;
|
|
19320
|
+
state.workspaceActiveConversation[workspaceKey] = nextActiveIndex;
|
|
19321
|
+
state.activeConversation = nextActiveIndex;
|
|
19322
|
+
state.conversations = currentConvs;
|
|
19323
|
+
if (priorActiveId === targetId) {
|
|
19324
|
+
state.activeBackendConversationId = nextActiveId;
|
|
19325
|
+
if (els['chat-area']) els['chat-area'].innerHTML = '';
|
|
19326
|
+
}
|
|
19327
|
+
if (state.flowTakeovers) {
|
|
19328
|
+
var archivedFlowKey = runtimeKeyFor(targetRuntime.workspaceId, targetRuntime.conversationId);
|
|
19329
|
+
var archivedFlowRecord = state.flowTakeovers[archivedFlowKey];
|
|
19330
|
+
if (archivedFlowRecord) {
|
|
19331
|
+
archivedFlowRecord.running = false;
|
|
19332
|
+
archivedFlowRecord.paused = false;
|
|
19333
|
+
archivedFlowRecord.runtimeLease = null;
|
|
19334
|
+
archivedFlowRecord.queueLease = null;
|
|
19335
|
+
delete state.flowTakeovers[archivedFlowKey];
|
|
19336
|
+
}
|
|
19337
|
+
if (priorActiveId === targetId && window.renderFlowTakeover) {
|
|
19338
|
+
window.renderFlowTakeover(false, '', { target: targetRuntime });
|
|
19339
|
+
}
|
|
19340
|
+
}
|
|
19341
|
+
setConversationRuntimeState(targetRuntime, 'idle', '');
|
|
19342
|
+
setWorking(!!runningConversationRecord(activeConversationId()));
|
|
19343
|
+
renderConversations();
|
|
19344
|
+
if (priorActiveId === targetId) scheduleConversationArchiveActiveSync(workspaceKey);
|
|
19238
19345
|
var optimisticArchive = {
|
|
19239
19346
|
id: receipt.fileName,
|
|
19240
19347
|
name: receipt.fileName,
|
|
@@ -19262,10 +19369,8 @@ window.archiveConv = function(conversationId) {
|
|
|
19262
19369
|
scheduleConversationArchiveRefresh(workspaceKey);
|
|
19263
19370
|
}).catch(function(err) {
|
|
19264
19371
|
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.
|
|
19372
|
+
// 归档失败:恢复按钮,保留行(不再乐观剔除)。
|
|
19373
|
+
renderConversations();
|
|
19269
19374
|
showUiNotice('[Archive] ' + t('workspace.saveFailed') + ': ' + (err.message || String(err)), 'error', 'archive-failed-' + targetId);
|
|
19270
19375
|
});
|
|
19271
19376
|
}
|
|
@@ -22511,6 +22616,11 @@ function schedulePostStartupUiRendering() {
|
|
|
22511
22616
|
// navigation surfaces render after promotion on cancellable browser tasks.
|
|
22512
22617
|
updateWorkspaceGate();
|
|
22513
22618
|
|
|
22619
|
+
if (document.documentElement.classList.contains('config-reloading')) {
|
|
22620
|
+
document.documentElement.classList.remove('config-reloading');
|
|
22621
|
+
try { sessionStorage.removeItem('newmark-config-reloading'); } catch (_) {}
|
|
22622
|
+
}
|
|
22623
|
+
|
|
22514
22624
|
// === Event Listeners ===
|
|
22515
22625
|
function escapeBelongsToFocusedControl(event) {
|
|
22516
22626
|
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" />
|