newmark-agent 0.4.2 → 0.4.4

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.
@@ -3523,8 +3523,6 @@ button.todo-item { background: transparent; }
3523
3523
  .context-inspector-head { display:flex; align-items:flex-start; gap:8px; margin-bottom:10px; }
3524
3524
  .context-inspector-title { flex:1; min-width:0; color:var(--text-bright); font-size:12px; font-weight:700; }
3525
3525
  .context-inspector-subtitle { margin-top:2px; color:var(--text-dim); font-size:9px; }
3526
- .context-inspector-close { width:22px; height:22px; padding:0; border:0; border-radius:var(--radius-sm); background:transparent; color:var(--text-dim); cursor:pointer; }
3527
- .context-inspector-close:hover, .context-inspector-close:focus-visible { color:var(--text-bright); background:var(--control-hover-bg); outline:none; }
3528
3526
  .context-inspector-meter { height:6px; margin:8px 0 10px; overflow:hidden; border-radius:var(--radius-full); background:rgba(168,168,168,.18); }
3529
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); }
3530
3528
  .context-inspector-grid { display:grid; grid-template-columns:1fr 1fr; gap:7px; }
@@ -6485,6 +6483,8 @@ var NEWMARK_I18N = {
6485
6483
  'model.contextSize': 'Context size',
6486
6484
  'model.vision': 'Vision',
6487
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).',
6488
6488
  'model.description': 'Description',
6489
6489
  'model.optionalDescription': 'Optional description',
6490
6490
  'model.fuzzyInput': 'API key / provider details',
@@ -6847,6 +6847,8 @@ var NEWMARK_I18N = {
6847
6847
  'status.contextCompressed': 'Context compressed',
6848
6848
  'status.contextCompression': 'Context compression',
6849
6849
  'status.contextTokens': 'Context tokens',
6850
+ 'status.conversationTokens': 'Conversation tokens',
6851
+ 'status.cacheHitRate': 'Cache hit rate',
6850
6852
  'status.contextNearLimit': 'Context near limit',
6851
6853
  'status.contextOverLimit': 'Context over limit',
6852
6854
  'status.contextModeFallback': 'fallback',
@@ -6854,7 +6856,7 @@ var NEWMARK_I18N = {
6854
6856
  'status.messages': 'messages',
6855
6857
  'status.noCompression': 'No compression event in this conversation',
6856
6858
  'status.contextInspector': 'Context management',
6857
- 'status.contextInspectorHint': 'DSH-inspired live budget; visible chat history stays unchanged.',
6859
+ 'status.contextInspectorHint': 'Live context budget; visible chat history stays unchanged.',
6858
6860
  'status.activeBuild': 'Active Build',
6859
6861
  'status.longHistory': 'Long history',
6860
6862
  'status.trigger': 'Trigger',
@@ -7187,6 +7189,8 @@ var NEWMARK_I18N = {
7187
7189
  'model.contextSize': '上下文规模',
7188
7190
  'model.vision': '视觉',
7189
7191
  'model.thinking': '思考',
7192
+ 'model.thinkingTierMap': '思考强度档位映射',
7193
+ 'model.thinkingTierMapHelp': '将模型原生思考强度档位映射到 Newmark 档位。每行一个「原生档位=Newmark档位」(如 minimal=low、balanced=medium、deep=high)。留空表示不变动映射(按 Newmark 档位名原样发送)。',
7190
7194
  'model.description': '描述',
7191
7195
  'model.optionalDescription': '可选描述',
7192
7196
  'model.fuzzyInput': 'API key / 供应商信息',
@@ -7549,6 +7553,8 @@ var NEWMARK_I18N = {
7549
7553
  'status.contextCompressed': '上下文已压缩',
7550
7554
  'status.contextCompression': '上下文压缩',
7551
7555
  'status.contextTokens': '上下文 token',
7556
+ 'status.conversationTokens': '全对话 token',
7557
+ 'status.cacheHitRate': '缓存命中率',
7552
7558
  'status.contextNearLimit': '上下文接近上限',
7553
7559
  'status.contextOverLimit': '上下文已超限',
7554
7560
  'status.contextModeFallback': 'fallback',
@@ -7556,7 +7562,7 @@ var NEWMARK_I18N = {
7556
7562
  'status.messages': '条消息',
7557
7563
  'status.noCompression': '当前对话暂无压缩事件',
7558
7564
  'status.contextInspector': '上下文管理',
7559
- 'status.contextInspectorHint': '借鉴 DSH 的动态预算;可见对话历史不会被改写。',
7565
+ 'status.contextInspectorHint': '实时上下文预算;可见对话历史不会被改写。',
7560
7566
  'status.activeBuild': '当前 Build',
7561
7567
  'status.longHistory': '长期历史',
7562
7568
  'status.trigger': '触发线',
@@ -10174,7 +10180,7 @@ function renderWorkToolGroup(event, eventIndex) {
10174
10180
  var edited = workToolEditedFile(item);
10175
10181
  if (edited) {
10176
10182
  var editKey = 'edit:' + String(item.id || item.toolCallId || itemIndex) + ':' + edited.path;
10177
- return '<details class="conversation-work-file conversation-work-file-inline" open data-work-detail-key="' + escAttr(editKey) + '"><summary>' +
10183
+ return '<details class="conversation-work-file conversation-work-file-inline" data-work-detail-key="' + escAttr(editKey) + '"><summary>' +
10178
10184
  iconSvg('pencil', 'edited', 'tiny') +
10179
10185
  '<span class="conversation-work-file-name" title="' + escAttr(edited.path) + '">' + esc(currentLang() === 'zh' ? '已编辑 ' : 'Edited ') + esc(edited.name) + '</span>' +
10180
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>' +
@@ -12075,6 +12081,12 @@ window.renderContextInspector = function() {
12075
12081
  var historyTrigger = contextInspectorValue(c.longHistoryTriggerTokens);
12076
12082
  var activeRetention = contextInspectorValue(c.buildBlockRetentionTokens);
12077
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;
12078
12090
  var percent = Math.min(100, Math.round((used / max) * 100));
12079
12091
  var fillColor = c.warning === 'over_limit' ? 'var(--nm-state-danger)' : (c.warning === 'near_limit' ? 'var(--nm-state-warning)' : 'var(--accent)');
12080
12092
  var compression = state.contextCompression || null;
@@ -12083,12 +12095,13 @@ window.renderContextInspector = function() {
12083
12095
  : t('status.noCompressionShort');
12084
12096
  var busy = !!state.contextMutationPending;
12085
12097
  var running = typeof isCurrentConversationRunning === 'function' && isCurrentConversationRunning();
12086
- 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>' +
12087
- '<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>' +
12088
12099
  '<div class="context-inspector-meter"><div class="context-inspector-meter-fill" style="width:' + percent + '%;background:' + fillColor + '"></div></div>' +
12089
12100
  '<div class="context-inspector-grid">' +
12090
12101
  contextInspectorCell(t('status.contextTokens'), used + ' / ' + max) +
12102
+ contextInspectorCell(t('status.conversationTokens'), providerTotalTokens + ' · ' + providerInputTokens + ' in / ' + providerOutputTokens + ' out') +
12091
12103
  contextInspectorCell(t('status.activeBuild'), active + ' / ' + activeTrigger) +
12104
+ contextInspectorCell(t('status.cacheHitRate'), cacheHitPercent + '% · ' + providerCacheReadTokens + ' cached') +
12092
12105
  contextInspectorCell(t('status.longHistory'), history + ' / ' + historyTrigger) +
12093
12106
  contextInspectorCell(t('status.retention'), activeRetention + ' + ' + historyRetention) +
12094
12107
  contextInspectorCell(t('status.hotCache'), contextInspectorValue(c.cacheEntries) + ' entries') +
@@ -12104,6 +12117,17 @@ window.closeContextInspector = function() {
12104
12117
  window.renderContextInspector();
12105
12118
  };
12106
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
+
12107
12131
  window.toggleContextInspector = function() {
12108
12132
  state.contextInspectorOpen = !state.contextInspectorOpen;
12109
12133
  window.hideContextWindowTooltip();
@@ -15329,9 +15353,11 @@ function renderModelSettings() {
15329
15353
  : (normalizedStatus === 'not checked' ? 'model-eval-pending' : 'model-eval-bad');
15330
15354
  var details = '';
15331
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;
15332
15357
  details = '<span class="model-eval-line">ctx ' + esc(modelEntry.max_tokens || '') +
15333
15358
  ' | ' + esc(t('model.vision')) + ' ' + (modelEntry.vision ? t('common.on') : t('common.off')) +
15334
15359
  ' | ' + esc(t('model.thinking')) + ' ' + (modelEntry.thinking ? t('common.on') : t('common.off')) +
15360
+ (tierMapCount ? ' | ' + esc(t('model.thinkingTierMap')) + ' ' + tierMapCount : '') +
15335
15361
  ' | ' + esc(t('model.cost')) + ' ' + esc(evaluation ? evaluation.cost_rating : '-') +
15336
15362
  ' | ' + esc(t('model.performanceShort')) + ' ' + esc(modelEntry.capability_rating || '-') +
15337
15363
  ' | ' + esc(t('model.speed')) + ' ' + esc(modelEntry.speed_rating || '-') + '</span>';
@@ -16040,9 +16066,31 @@ window.addModel = function() {
16040
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>' +
16041
16067
  '<label style="font-size:11px;color:var(--text-dim);"><input type="checkbox" id="new-model-thinking"> ' + esc(t('model.thinking')) + '</label></div>' +
16042
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&#10;balanced=medium&#10;deep=high"></textarea>' +
16070
+ '<div style="margin-top:10px;font-size:11px;color:var(--text-dim);">' + esc(t('model.thinkingTierMapHelp')) + '</div></div>' +
16043
16071
  '<div style="margin-top:10px;"><button class="sec-btn primary" onclick="window.saveNewModel()">' + esc(t('common.save')) + '</button></div>');
16044
16072
  };
16045
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
+
16046
16094
  window.saveNewModel = function() {
16047
16095
  var name = document.getElementById('new-model-name').value;
16048
16096
  var provIdx = parseInt(document.getElementById('new-model-provider').value);
@@ -16050,9 +16098,11 @@ window.saveNewModel = function() {
16050
16098
  var visionEl = document.getElementById('new-model-vision');
16051
16099
  var thinkingEl = document.getElementById('new-model-thinking');
16052
16100
  var descEl = document.getElementById('new-model-desc');
16101
+ var tierMapEl = document.getElementById('new-model-tier-map');
16053
16102
  if (name && !isNaN(provIdx) && state.providers[provIdx]) {
16054
16103
  if (!state.providers[provIdx].models) state.providers[provIdx].models = [];
16055
- state.providers[provIdx].models.push({
16104
+ var tierMap = window.parseThinkingTierMap(tierMapEl ? tierMapEl.value : '');
16105
+ var entry = {
16056
16106
  name: name,
16057
16107
  display: name,
16058
16108
  description: descEl ? descEl.value : '',
@@ -16069,7 +16119,9 @@ window.saveNewModel = function() {
16069
16119
  xhigh: { description: 'xhigh' },
16070
16120
  max: { description: 'max' }
16071
16121
  }
16072
- });
16122
+ };
16123
+ if (Object.keys(tierMap).length) entry.thinking_tier_map = tierMap;
16124
+ state.providers[provIdx].models.push(entry);
16073
16125
  api.saveConfig({providers: state.providers});
16074
16126
  window.refreshModelSelect();
16075
16127
  }
@@ -16089,6 +16141,8 @@ window.editModel = function(provIdx, modelIdx) {
16089
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>' +
16090
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>' +
16091
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>' +
16092
16146
  '<div style="margin-top:10px;"><button class="sec-btn primary" onclick="window.saveModelEdit(' + provIdx + ',' + modelIdx + ')">' + esc(t('common.save')) + '</button></div>');
16093
16147
  };
16094
16148
 
@@ -16101,11 +16155,13 @@ window.saveModelEdit = function(oldProvIdx, modelIdx) {
16101
16155
  var visionEl = document.getElementById('edit-model-vision');
16102
16156
  var thinkingEl = document.getElementById('edit-model-thinking');
16103
16157
  var descEl = document.getElementById('edit-model-desc');
16158
+ var tierMapEl = document.getElementById('edit-model-tier-map');
16104
16159
  var name = nameEl ? nameEl.value.trim() : '';
16105
16160
  var newProvIdx = provEl ? parseInt(provEl.value) : oldProvIdx;
16106
16161
  if (!name || isNaN(newProvIdx) || !state.providers[newProvIdx]) return;
16107
16162
  var previous = oldProvider.models[modelIdx];
16108
16163
  if (typeof previous === 'string') previous = { name: previous, display: previous };
16164
+ var tierMap = window.parseThinkingTierMap(tierMapEl ? tierMapEl.value : '');
16109
16165
  var updated = Object.assign({}, previous, {
16110
16166
  name: name,
16111
16167
  display: name,
@@ -16114,6 +16170,8 @@ window.saveModelEdit = function(oldProvIdx, modelIdx) {
16114
16170
  vision: !!(visionEl && visionEl.checked),
16115
16171
  thinking: !!(thinkingEl && thinkingEl.checked)
16116
16172
  });
16173
+ if (Object.keys(tierMap).length) updated.thinking_tier_map = tierMap;
16174
+ else delete updated.thinking_tier_map;
16117
16175
  oldProvider.models.splice(modelIdx, 1);
16118
16176
  if (!state.providers[newProvIdx].models) state.providers[newProvIdx].models = [];
16119
16177
  state.providers[newProvIdx].models.push(updated);
@@ -22767,6 +22825,17 @@ function schedulePostStartupUiRendering() {
22767
22825
  var modelResult = await api.setModel(state.model);
22768
22826
  if (modelResult != null) state._syncedModel = state.model;
22769
22827
  }
22828
+ // The context ring/inspector must immediately reflect the newly selected
22829
+ // model's configured context window rather than waiting for the next send.
22830
+ if (api.getState) {
22831
+ var ctxTarget = currentConversationTarget();
22832
+ api.getState(ctxTarget).then(function(s) {
22833
+ if (s && s.contextWindow !== undefined && isActiveConversationTarget(ctxTarget) && isViewingRuntimeConversationBranch(ctxTarget)) {
22834
+ state.contextWindow = s.contextWindow;
22835
+ window.renderContextWindow();
22836
+ }
22837
+ }).catch(function(){});
22838
+ }
22770
22839
  });
22771
22840
  }
22772
22841