newmark-agent 0.4.7 → 0.4.9

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.
@@ -4221,6 +4221,44 @@ textarea.mcp-input { min-height:76px; resize:vertical; font-family:var(--font-mo
4221
4221
  .setting-control { flex: 1; }
4222
4222
  .settings-load-error { color: var(--notice-error-text); }
4223
4223
 
4224
+ .remote-touch-copy {
4225
+ flex: 1;
4226
+ min-width: 0;
4227
+ display: flex;
4228
+ flex-direction: column;
4229
+ gap: 2px;
4230
+ }
4231
+ .remote-touch-copy-title {
4232
+ color: var(--text);
4233
+ font-size: 11px;
4234
+ font-weight: 700;
4235
+ line-height: 1.25;
4236
+ }
4237
+ .remote-touch-copy-desc {
4238
+ color: var(--text-dim);
4239
+ font-size: 10px;
4240
+ font-weight: 400;
4241
+ line-height: 1.35;
4242
+ }
4243
+ .remote-touch-action {
4244
+ flex: 0 0 120px;
4245
+ width: 120px;
4246
+ min-width: 120px;
4247
+ min-height: 28px;
4248
+ box-sizing: border-box;
4249
+ }
4250
+ .remote-touch-status {
4251
+ background: transparent !important;
4252
+ border-color: currentColor;
4253
+ box-shadow: 0 0 0 1px currentColor, 0 0 10px color-mix(in srgb, currentColor 42%, transparent);
4254
+ }
4255
+ .remote-touch-status:hover { background: transparent !important; }
4256
+ .remote-touch-status.listening { color: var(--accent2); }
4257
+ .remote-touch-status.error,
4258
+ .remote-touch-status.checking { color: #ffb454; }
4259
+ .remote-touch-status.off { color: var(--notice-error-text); }
4260
+ .remote-touch-status[aria-busy="true"] { cursor: wait; }
4261
+
4224
4262
  .segmented-control {
4225
4263
  display: grid;
4226
4264
  grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -6302,6 +6340,9 @@ var state = {
6302
6340
  configuredAgentBackend: 'windows',
6303
6341
  agentBackendRestartRequired: false,
6304
6342
  remoteTouchEnabled: true,
6343
+ remoteTouchServer: { enabled: true, listening: false, reachable: false, state: 'checking', host: '', port: 47890, error: '', checkedAt: '', startedAt: 0 },
6344
+ remoteTouchStatusBusy: false,
6345
+ _remoteTouchStatusTimer: null,
6305
6346
  wslAvailable: false,
6306
6347
  wslDistros: [],
6307
6348
  defaultTerminalShell: 'powershell',
@@ -6484,6 +6525,10 @@ var NEWMARK_I18N = {
6484
6525
  'settings.runInWslDesc': 'Keeps the Windows UI and native desktop tools local while running the persistent Agent kernel, model calls, shell, and file tools inside WSL.',
6485
6526
  'settings.remoteTouch': 'Mobile remote-touch',
6486
6527
  'settings.remoteTouchDesc': 'Allow mobile access on the same LAN / Tailscale network',
6528
+ 'settings.remoteTouchListening': 'Listening',
6529
+ 'settings.remoteTouchError': 'Unreachable',
6530
+ 'settings.remoteTouchOff': 'Off',
6531
+ 'settings.remoteTouchChecking': 'Checking',
6487
6532
  'settings.remoteBehavior': 'Remote behavior',
6488
6533
  'settings.remoteConnect': 'Start connection',
6489
6534
  'settings.remoteConnectDesc': 'Show pairing QR',
@@ -7211,6 +7256,10 @@ var NEWMARK_I18N = {
7211
7256
  'settings.runInWslDesc': 'Windows UI 与桌面原生工具保留在本机,持续 Agent 内核、模型请求、Shell 和文件工具运行在 WSL。',
7212
7257
  'settings.remoteTouch': '移动端远程触及',
7213
7258
  'settings.remoteTouchDesc': '允许移动端通过同一内网 / Tailscale 连接',
7259
+ 'settings.remoteTouchListening': '监听中',
7260
+ 'settings.remoteTouchError': '不可触及',
7261
+ 'settings.remoteTouchOff': '已关闭',
7262
+ 'settings.remoteTouchChecking': '检测中',
7214
7263
  'settings.remoteBehavior': '远程行为',
7215
7264
  'settings.remoteConnect': '发起连接',
7216
7265
  'settings.remoteConnectDesc': '显示配对二维码',
@@ -7389,7 +7438,7 @@ var NEWMARK_I18N = {
7389
7438
  'model.unavailable': '不可用',
7390
7439
  'model.no': '否',
7391
7440
  'model.yes': '是',
7392
- 'model.notChecked': '未校验',
7441
+ 'model.notChecked': '未检测',
7393
7442
  'archive.current': '归档当前对话',
7394
7443
  'archive.archiving': '归档中...',
7395
7444
  'archive.empty': '暂无归档。',
@@ -15464,7 +15513,7 @@ function formatModelStatus(status) {
15464
15513
  if (raw === 'available' || raw === 'verified') return t('model.available');
15465
15514
  if (raw === 'degraded') return t('model.degraded');
15466
15515
  if (raw === 'unavailable' || raw === 'failed' || raw === 'error') return t('model.unavailable');
15467
- if (raw === 'not checked' || raw === 'not_checked' || raw === 'pending') return t('model.notChecked');
15516
+ if (raw === 'not checked' || raw === 'not_checked' || raw === 'unvalidated' || raw === 'pending') return t('model.notChecked');
15468
15517
  return status || t('model.notChecked');
15469
15518
  }
15470
15519
 
@@ -15476,6 +15525,7 @@ function effectiveUiModelStatus(modelEntry) {
15476
15525
  var textEvidence = capabilities.text === true || capabilities.text_input === true || capabilities.text_output === true
15477
15526
  || !!(modelEntry.evaluation && (modelEntry.evaluation.text_input || modelEntry.evaluation.text_output));
15478
15527
  if (rawValidation === 'auth_error' || rawValidation === 'invalid_config') return rawValidation;
15528
+ if (String((modelEntry.validation && modelEntry.validation.level) || '').toLowerCase() === 'discovered') return 'unvalidated';
15479
15529
  if (textEvidence && rawValidation === 'unavailable') return 'degraded';
15480
15530
  return rawValidation || rawEvaluation;
15481
15531
  }
@@ -15539,15 +15589,15 @@ function renderGeneralSettings() {
15539
15589
  '<div class="setting-desc" id="agent-wsl-status">' + esc(state.agentBackend && state.agentBackend.connected ? t('settings.wslConnected') : t('settings.wslDisconnected')) + '</div></div></div>' : '';
15540
15590
  return wslHtml + '<div class="setting-subsection">' +
15541
15591
  '<div class="setting-subsection-title">' + esc(t('settings.remoteBehavior')) + '</div>' +
15542
- '<div class="setting-row">' +
15543
- '<label class="setting-label" for="remote-touch-enabled" style="display:inline-flex;align-items:center;gap:6px;min-width:120px;">' +
15544
- '<input type="checkbox" id="remote-touch-enabled"' + (state.remoteTouchEnabled ? ' checked' : '') + ' onchange="window.setRemoteTouchEnabled(this.checked)">' +
15545
- '<span>' + esc(t('settings.remoteTouch')) + '</span></label>' +
15546
- '<span class="setting-desc" style="flex:1;min-width:140px;">' + esc(t('settings.remoteTouchDesc')) + '</span>' +
15592
+ '<div class="setting-row remote-touch-row">' +
15593
+ '<button type="button" id="remote-touch-status-button" class="sec-btn remote-touch-action remote-touch-status ' + esc(remoteTouchStatusClass()) + '" aria-pressed="' + (state.remoteTouchEnabled ? 'true' : 'false') + '" aria-busy="' + (state.remoteTouchStatusBusy ? 'true' : 'false') + '" onclick="window.setRemoteTouchEnabled(!state.remoteTouchEnabled)" title="' + esc(remoteTouchStatusTitle()) + '"' + (state.remoteTouchStatusBusy ? ' disabled' : '') + '>' + esc(remoteTouchStatusText()) + '</button>' +
15594
+ '<div class="remote-touch-copy"><div class="remote-touch-copy-title">' + esc(t('settings.remoteTouch')) + '</div>' +
15595
+ '<div class="remote-touch-copy-desc">' + esc(t('settings.remoteTouchDesc')) + '</div></div>' +
15547
15596
  '</div>' +
15548
- '<div class="setting-row" style="border-bottom:none;">' +
15549
- '<button type="button" class="sec-btn primary" onclick="window.showMobilePairing()">' + esc(t('settings.remoteConnect')) + '</button>' +
15550
- '<span class="setting-desc" style="flex:1;">' + esc(t('settings.remoteConnectDesc')) + '</span>' +
15597
+ '<div class="setting-row remote-touch-row" style="border-bottom:none;">' +
15598
+ '<button type="button" id="remote-touch-connect-button" class="sec-btn primary remote-touch-action" onclick="window.showMobilePairing()">' + esc(t('settings.remoteConnect')) + '</button>' +
15599
+ '<div class="remote-touch-copy"><div class="remote-touch-copy-title">' + esc(t('mobile.pair')) + '</div>' +
15600
+ '<div class="remote-touch-copy-desc">' + esc(t('settings.remoteConnectDesc')) + '</div></div>' +
15551
15601
  '</div>' +
15552
15602
  '</div>' +
15553
15603
  '<div class="setting-row">' +
@@ -15656,7 +15706,7 @@ function renderModelSettings() {
15656
15706
  var normalizedStatus = String(statusRaw || '').toLowerCase();
15657
15707
  var statusClass = normalizedStatus === 'available' || normalizedStatus === 'verified' || normalizedStatus === 'degraded'
15658
15708
  ? 'model-eval-ok'
15659
- : (normalizedStatus === 'not checked' ? 'model-eval-pending' : 'model-eval-bad');
15709
+ : (normalizedStatus === 'not checked' || normalizedStatus === 'unvalidated' ? 'model-eval-pending' : 'model-eval-bad');
15660
15710
  var details = '';
15661
15711
  if (typeof modelEntry !== 'string') {
15662
15712
  var tierMapCount = modelEntry.thinking_tier_map && typeof modelEntry.thinking_tier_map === 'object' ? Object.keys(modelEntry.thinking_tier_map).length : 0;
@@ -16225,13 +16275,96 @@ window.setAgentBackendMode = async function(mode) {
16225
16275
  return true;
16226
16276
  };
16227
16277
 
16278
+ function remoteTouchStatusClass() {
16279
+ if (state.remoteTouchStatusBusy) return 'checking';
16280
+ var status = state.remoteTouchServer || {};
16281
+ if (!state.remoteTouchEnabled || status.state === 'off') return 'off';
16282
+ return status.state === 'listening' && status.listening && status.reachable ? 'listening' : 'error';
16283
+ }
16284
+
16285
+ function remoteTouchStatusText() {
16286
+ var statusClass = remoteTouchStatusClass();
16287
+ if (statusClass === 'checking') return t('settings.remoteTouchChecking');
16288
+ if (statusClass === 'listening') return t('settings.remoteTouchListening');
16289
+ if (statusClass === 'error') return t('settings.remoteTouchError');
16290
+ return t('settings.remoteTouchOff');
16291
+ }
16292
+
16293
+ function remoteTouchStatusTitle() {
16294
+ var status = state.remoteTouchServer || {};
16295
+ var endpoint = status.host ? status.host + ':' + (status.port || 47890) : '';
16296
+ return [remoteTouchStatusText(), endpoint, status.error || ''].filter(Boolean).join(' · ');
16297
+ }
16298
+
16299
+ window.updateRemoteTouchStatusButton = function() {
16300
+ var button = document.getElementById('remote-touch-status-button');
16301
+ if (!button) return;
16302
+ button.className = 'sec-btn remote-touch-action remote-touch-status ' + remoteTouchStatusClass();
16303
+ button.textContent = remoteTouchStatusText();
16304
+ button.setAttribute('aria-pressed', state.remoteTouchEnabled ? 'true' : 'false');
16305
+ button.setAttribute('aria-busy', state.remoteTouchStatusBusy ? 'true' : 'false');
16306
+ button.title = remoteTouchStatusTitle();
16307
+ button.disabled = !!state.remoteTouchStatusBusy;
16308
+ };
16309
+
16310
+ window.refreshRemoteTouchServerStatus = async function() {
16311
+ if (!api.mobileServerStatus) return state.remoteTouchServer;
16312
+ try {
16313
+ var result = await api.mobileServerStatus();
16314
+ if (result && result.state) {
16315
+ state.remoteTouchServer = result;
16316
+ state.remoteTouchEnabled = !!result.enabled;
16317
+ }
16318
+ } catch (error) {
16319
+ state.remoteTouchServer = {
16320
+ enabled: state.remoteTouchEnabled,
16321
+ listening: false,
16322
+ reachable: false,
16323
+ state: state.remoteTouchEnabled ? 'error' : 'off',
16324
+ host: '',
16325
+ port: 47890,
16326
+ error: error && error.message ? error.message : String(error || ''),
16327
+ checkedAt: new Date().toISOString(),
16328
+ startedAt: 0
16329
+ };
16330
+ }
16331
+ window.updateRemoteTouchStatusButton();
16332
+ return state.remoteTouchServer;
16333
+ };
16334
+
16335
+ window.startRemoteTouchStatusPolling = function() {
16336
+ if (state._remoteTouchStatusTimer) clearInterval(state._remoteTouchStatusTimer);
16337
+ window.refreshRemoteTouchServerStatus().catch(function(){});
16338
+ state._remoteTouchStatusTimer = setInterval(function() {
16339
+ window.refreshRemoteTouchServerStatus().catch(function(){});
16340
+ }, 5000);
16341
+ };
16342
+
16228
16343
  window.setRemoteTouchEnabled = async function(value) {
16229
16344
  var next = !!value;
16230
16345
  state.remoteTouchEnabled = next;
16231
- if (api.saveSetting) {
16232
- try { await api.saveSetting('remote', 'touch_enabled', next); } catch (e) {}
16346
+ state.remoteTouchStatusBusy = true;
16347
+ window.updateRemoteTouchStatusButton();
16348
+ try {
16349
+ var result = api.setRemoteTouchEnabled
16350
+ ? await api.setRemoteTouchEnabled(next)
16351
+ : (api.saveSetting ? await api.saveSetting('remote', 'touch_enabled', next) : null);
16352
+ if (result && result.state) state.remoteTouchServer = result;
16353
+ } catch (error) {
16354
+ state.remoteTouchServer = {
16355
+ enabled: next,
16356
+ listening: false,
16357
+ reachable: false,
16358
+ state: next ? 'error' : 'off',
16359
+ host: '', port: 47890,
16360
+ error: error && error.message ? error.message : String(error || ''),
16361
+ checkedAt: new Date().toISOString(), startedAt: 0
16362
+ };
16363
+ } finally {
16364
+ state.remoteTouchStatusBusy = false;
16233
16365
  }
16234
- window.settingsTab('general');
16366
+ await window.refreshRemoteTouchServerStatus();
16367
+ window.updateRemoteTouchStatusButton();
16235
16368
  };
16236
16369
 
16237
16370
  window.setAgentWslDistro = async function(value) {
@@ -16477,6 +16610,7 @@ window.saveModelEdit = function(oldProvIdx, modelIdx) {
16477
16610
  if (typeof previous === 'string') previous = { name: previous, display: previous };
16478
16611
  var tierMap = window.parseThinkingTierMap(tierMapEl ? tierMapEl.value : '');
16479
16612
  var updated = Object.assign({}, previous, {
16613
+ _previous_name: previous.name || name,
16480
16614
  name: name,
16481
16615
  display: name,
16482
16616
  description: descEl ? descEl.value : '',
@@ -23088,6 +23222,7 @@ function schedulePostStartupUiRendering() {
23088
23222
  }
23089
23223
 
23090
23224
  updateMarqueeFromConfig();
23225
+ window.startRemoteTouchStatusPolling();
23091
23226
 
23092
23227
  // Populate selects
23093
23228
  if (els['mode-select']) els['mode-select'].value = state.mode;
@@ -23351,6 +23486,7 @@ function schedulePostStartupUiRendering() {
23351
23486
 
23352
23487
  window.addEventListener('beforeunload', function() {
23353
23488
  if (state._postStartupUiRendering && state._postStartupUiRendering.cancel) state._postStartupUiRendering.cancel();
23489
+ if (state._remoteTouchStatusTimer) clearInterval(state._remoteTouchStatusTimer);
23354
23490
  cancelBrowserGuestIdleDestroy();
23355
23491
  flushPendingConversationDraftPersists();
23356
23492
  }, { once: true });