newmark-agent 0.4.5 → 0.4.7
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/assets/app-icon-dark.svg +6 -0
- package/dist/assets/app-icon-dark.svg +6 -0
- package/dist/cli-commands.d.ts +1 -1
- package/dist/cli-commands.js +90 -7
- package/dist/cli-discovery.js +10 -0
- package/dist/conversation-utility-host.bundle.cjs +293 -148
- package/dist/core/agent.d.ts +38 -4
- package/dist/core/agent.js +231 -49
- package/dist/core/agentKernelRunner.d.ts +3 -0
- package/dist/core/agentKernelRunner.js +49 -83
- package/dist/core/config.js +3 -0
- package/dist/core/dshCompatibility.d.ts +23 -6
- package/dist/core/dshCompatibility.js +99 -1
- package/dist/core/installUpdate.d.ts +67 -0
- package/dist/core/installUpdate.js +268 -0
- package/dist/core/mobilePairing.d.ts +47 -0
- package/dist/core/mobilePairing.js +221 -0
- package/dist/core/subagent.d.ts +10 -3
- package/dist/core/subagent.js +23 -8
- package/dist/core/toolPolicy.js +11 -3
- package/dist/launcher.js +14 -11
- package/dist/main.js +64 -3
- package/dist/preload.js +5 -0
- package/dist/providers/chat-completions.adapter.js +6 -2
- package/dist/providers/responses.adapter.js +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +721 -3
- package/dist/toolchain/registry-seeder.js +3 -1
- package/dist/tools/index.js +11 -5
- package/dist/tools/nativeTools.js +1 -1
- package/dist/tui/src/adapters/core-runtime-adapter.js +17 -1
- package/dist/tui/src/app.js +41 -0
- package/dist/tui/src/data.js +1 -0
- package/dist/tui/src/render.js +11 -0
- package/dist/tui/src/settings-schema.js +3 -1
- package/dist/tui/src/state.js +21 -1
- package/dist/ui/index.html +530 -101
- package/dist/ui/lucide-sprite.svg +10 -0
- package/dist/wsl-agent-host.bundle.cjs +293 -148
- package/package.json +14 -8
package/dist/ui/index.html
CHANGED
|
@@ -428,38 +428,15 @@ button:focus, select:focus, input:focus, textarea:focus, [contenteditable]:focus
|
|
|
428
428
|
}
|
|
429
429
|
|
|
430
430
|
#topbar .logo {
|
|
431
|
-
position: relative;
|
|
432
431
|
display: inline-flex;
|
|
433
432
|
width: 26px;
|
|
434
433
|
height: 26px;
|
|
435
|
-
padding: 1px;
|
|
436
|
-
border-radius: 8px;
|
|
437
434
|
align-items: center;
|
|
438
435
|
justify-content: center;
|
|
439
|
-
overflow: hidden;
|
|
440
|
-
box-shadow: 0 0 12px var(--accent-glow);
|
|
441
436
|
flex-shrink: 0;
|
|
442
437
|
}
|
|
443
438
|
|
|
444
|
-
#topbar .logo::before {
|
|
445
|
-
content: "";
|
|
446
|
-
position: absolute;
|
|
447
|
-
inset: calc(-2 * var(--marquee-width));
|
|
448
|
-
background: conic-gradient(from var(--marquee-angle, 0deg), var(--g1), var(--g2), var(--g3), var(--g4), var(--g1));
|
|
449
|
-
animation: marquee-rotate var(--marquee-speed) linear infinite;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
#topbar .logo::after {
|
|
453
|
-
content: "";
|
|
454
|
-
position: absolute;
|
|
455
|
-
inset: 2px;
|
|
456
|
-
border-radius: 7px;
|
|
457
|
-
background: var(--bg2);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
439
|
#topbar .logo img {
|
|
461
|
-
position: relative;
|
|
462
|
-
z-index: 1;
|
|
463
440
|
display: block;
|
|
464
441
|
width: 22px;
|
|
465
442
|
height: 22px;
|
|
@@ -1115,6 +1092,74 @@ button.left-ws-item {
|
|
|
1115
1092
|
border-color: var(--accent);
|
|
1116
1093
|
}
|
|
1117
1094
|
|
|
1095
|
+
.conv-more-btn {
|
|
1096
|
+
width: 20px;
|
|
1097
|
+
height: 20px;
|
|
1098
|
+
margin-left: auto;
|
|
1099
|
+
border: 0;
|
|
1100
|
+
border-radius: var(--radius-sm);
|
|
1101
|
+
background: transparent;
|
|
1102
|
+
color: var(--text-dim);
|
|
1103
|
+
cursor: pointer;
|
|
1104
|
+
display: flex;
|
|
1105
|
+
align-items: center;
|
|
1106
|
+
justify-content: center;
|
|
1107
|
+
transition: background var(--duration-fast) var(--ease-out-expo), color var(--duration-fast) var(--ease-out-expo);
|
|
1108
|
+
flex-shrink: 0;
|
|
1109
|
+
}
|
|
1110
|
+
.conv-more-btn:hover,
|
|
1111
|
+
.conv-more-btn[aria-expanded="true"] {
|
|
1112
|
+
background: var(--control-hover-bg);
|
|
1113
|
+
color: var(--text-bright);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
.conv-action-menu {
|
|
1117
|
+
position: fixed;
|
|
1118
|
+
inset: auto;
|
|
1119
|
+
margin: 0;
|
|
1120
|
+
z-index: 560;
|
|
1121
|
+
display: none;
|
|
1122
|
+
min-width: 168px;
|
|
1123
|
+
max-height: min(56vh, 320px);
|
|
1124
|
+
overflow: auto;
|
|
1125
|
+
padding: 6px;
|
|
1126
|
+
border: 1px solid var(--glass-border-2);
|
|
1127
|
+
border-radius: var(--radius-lg);
|
|
1128
|
+
background: var(--modal-surface);
|
|
1129
|
+
box-shadow: var(--shadow-lg);
|
|
1130
|
+
backdrop-filter: blur(var(--glass-blur-3)) saturate(1.08);
|
|
1131
|
+
}
|
|
1132
|
+
.conv-action-menu:popover-open { display: block; animation: model-menu-in 150ms var(--ease-out-expo); }
|
|
1133
|
+
|
|
1134
|
+
.conv-action-menu-item {
|
|
1135
|
+
width: 100%;
|
|
1136
|
+
min-height: 32px;
|
|
1137
|
+
display: flex;
|
|
1138
|
+
align-items: center;
|
|
1139
|
+
gap: 8px;
|
|
1140
|
+
padding: 6px 10px;
|
|
1141
|
+
border: 0;
|
|
1142
|
+
border-radius: var(--radius-md);
|
|
1143
|
+
background: transparent;
|
|
1144
|
+
color: var(--text);
|
|
1145
|
+
text-align: left;
|
|
1146
|
+
white-space: nowrap;
|
|
1147
|
+
font: 12px var(--font-ui);
|
|
1148
|
+
cursor: pointer;
|
|
1149
|
+
}
|
|
1150
|
+
.conv-action-menu-item:hover,
|
|
1151
|
+
.conv-action-menu-item:focus-visible {
|
|
1152
|
+
background: var(--control-hover-bg);
|
|
1153
|
+
color: var(--text-bright);
|
|
1154
|
+
outline: none;
|
|
1155
|
+
}
|
|
1156
|
+
.conv-action-menu-item:disabled { opacity: 0.55; cursor: default; }
|
|
1157
|
+
.conv-action-menu-item .nm-icon { color: var(--text-dim); flex-shrink: 0; }
|
|
1158
|
+
.conv-action-menu-item:hover .nm-icon,
|
|
1159
|
+
.conv-action-menu-item:focus-visible .nm-icon { color: var(--text-bright); }
|
|
1160
|
+
.conv-action-menu-item.active { color: var(--text-accent); }
|
|
1161
|
+
.conv-action-menu-item.active .nm-icon { color: var(--text-accent); }
|
|
1162
|
+
|
|
1118
1163
|
/* ============================================================
|
|
1119
1164
|
RESIZE HANDLES
|
|
1120
1165
|
============================================================ */
|
|
@@ -2715,15 +2760,18 @@ button.todo-item { background: transparent; }
|
|
|
2715
2760
|
}
|
|
2716
2761
|
|
|
2717
2762
|
.option-btn {
|
|
2718
|
-
|
|
2763
|
+
display: block;
|
|
2764
|
+
width: 100%;
|
|
2765
|
+
padding: 6px 14px;
|
|
2719
2766
|
border: 1px solid var(--border);
|
|
2720
2767
|
border-radius: var(--radius-md);
|
|
2721
2768
|
background: var(--glass-bg-1);
|
|
2722
2769
|
color: var(--text);
|
|
2723
2770
|
font-size: 12px;
|
|
2724
2771
|
font-family: var(--font-ui);
|
|
2772
|
+
text-align: left;
|
|
2725
2773
|
cursor: pointer;
|
|
2726
|
-
margin:
|
|
2774
|
+
margin: 3px 0;
|
|
2727
2775
|
transition: background var(--duration-fast) var(--ease-out-expo), border-color var(--duration-fast) var(--ease-out-expo);
|
|
2728
2776
|
}
|
|
2729
2777
|
|
|
@@ -2739,6 +2787,45 @@ button.todo-item { background: transparent; }
|
|
|
2739
2787
|
font-size: 11px;
|
|
2740
2788
|
}
|
|
2741
2789
|
|
|
2790
|
+
.option-manual {
|
|
2791
|
+
display: flex;
|
|
2792
|
+
align-items: center;
|
|
2793
|
+
gap: 6px;
|
|
2794
|
+
margin-top: 8px;
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
.option-manual-input {
|
|
2798
|
+
flex: 1;
|
|
2799
|
+
min-width: 0;
|
|
2800
|
+
height: 30px;
|
|
2801
|
+
padding: 3px 9px;
|
|
2802
|
+
border: 1px solid var(--border);
|
|
2803
|
+
border-radius: var(--radius-md);
|
|
2804
|
+
background: var(--glass-bg-1);
|
|
2805
|
+
color: var(--text);
|
|
2806
|
+
font: 12px var(--font-ui);
|
|
2807
|
+
outline: none;
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
.option-manual-input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-glow); }
|
|
2811
|
+
.option-manual-input:disabled { opacity: .55; cursor: default; }
|
|
2812
|
+
|
|
2813
|
+
.option-manual-submit {
|
|
2814
|
+
flex-shrink: 0;
|
|
2815
|
+
height: 30px;
|
|
2816
|
+
padding: 0 12px;
|
|
2817
|
+
border: 1px solid var(--accent);
|
|
2818
|
+
border-radius: var(--radius-md);
|
|
2819
|
+
background: rgba(91,120,255,0.14);
|
|
2820
|
+
color: var(--text-bright);
|
|
2821
|
+
font: 12px var(--font-ui);
|
|
2822
|
+
cursor: pointer;
|
|
2823
|
+
transition: background var(--duration-fast) var(--ease-out-expo);
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
.option-manual-submit:hover { background: rgba(91,120,255,0.24); }
|
|
2827
|
+
.option-manual-submit:disabled { opacity: .55; cursor: default; }
|
|
2828
|
+
|
|
2742
2829
|
/* ============================================================
|
|
2743
2830
|
INPUT STACK
|
|
2744
2831
|
============================================================ */
|
|
@@ -3722,11 +3809,15 @@ button.todo-item { background: transparent; }
|
|
|
3722
3809
|
linear-gradient(#fff 0 0) content-box,
|
|
3723
3810
|
linear-gradient(#fff 0 0);
|
|
3724
3811
|
mask-composite: exclude;
|
|
3725
|
-
|
|
3812
|
+
/* A masked conic-gradient whose custom angle changes every frame forces a
|
|
3813
|
+
full GPU repaint. Several simultaneous Agent/SubAgent surfaces made that
|
|
3814
|
+
repaint saturate the renderer and GPU, starving ordinary text input. Keep
|
|
3815
|
+
the shared status border visually present, but static; live progress is
|
|
3816
|
+
already communicated by status text, duration, and event updates. */
|
|
3817
|
+
animation: none;
|
|
3726
3818
|
z-index: -1;
|
|
3727
3819
|
pointer-events: none;
|
|
3728
3820
|
transform: translateZ(0);
|
|
3729
|
-
will-change: transform;
|
|
3730
3821
|
}
|
|
3731
3822
|
|
|
3732
3823
|
@supports not (background: conic-gradient(from 0deg, red, blue)) {
|
|
@@ -3734,11 +3825,11 @@ button.todo-item { background: transparent; }
|
|
|
3734
3825
|
background: linear-gradient(var(--marquee-angle, 0deg), var(--g1), var(--g2), var(--g3), var(--g4), var(--g1));
|
|
3735
3826
|
}
|
|
3736
3827
|
@keyframes marquee-rotate-fallback { 0% { filter: hue-rotate(0deg); } 100% { filter: hue-rotate(360deg); } }
|
|
3737
|
-
.marquee-border::before { animation:
|
|
3828
|
+
.marquee-border::before { animation: none; }
|
|
3738
3829
|
}
|
|
3739
3830
|
|
|
3740
3831
|
.working-glow {
|
|
3741
|
-
animation:
|
|
3832
|
+
animation: none;
|
|
3742
3833
|
box-shadow: 0 0 16px var(--accent-glow), 0 0 40px rgba(91,120,255,0.1);
|
|
3743
3834
|
border-color: rgba(91,120,255,0.4) !important;
|
|
3744
3835
|
}
|
|
@@ -4098,6 +4189,21 @@ textarea.mcp-input { min-height:76px; resize:vertical; font-family:var(--font-mo
|
|
|
4098
4189
|
transition: none !important;
|
|
4099
4190
|
}
|
|
4100
4191
|
|
|
4192
|
+
.setting-subsection {
|
|
4193
|
+
margin-top: 14px;
|
|
4194
|
+
padding: 12px 14px;
|
|
4195
|
+
border: 1px solid var(--glass-border-1);
|
|
4196
|
+
border-radius: var(--radius-md);
|
|
4197
|
+
background: var(--glass-bg-1);
|
|
4198
|
+
}
|
|
4199
|
+
|
|
4200
|
+
.setting-subsection-title {
|
|
4201
|
+
margin-bottom: 6px;
|
|
4202
|
+
color: var(--text-bright);
|
|
4203
|
+
font-size: 12px;
|
|
4204
|
+
font-weight: 650;
|
|
4205
|
+
}
|
|
4206
|
+
|
|
4101
4207
|
.setting-row {
|
|
4102
4208
|
display: flex;
|
|
4103
4209
|
align-items: center;
|
|
@@ -5340,6 +5446,11 @@ html.newmark-memory-overview-viewer body {
|
|
|
5340
5446
|
<path d="m15 10 5 5-5 5" />
|
|
5341
5447
|
<path d="M4 4v7a4 4 0 0 0 4 4h12" />
|
|
5342
5448
|
</symbol>
|
|
5449
|
+
<symbol id="ellipsis" viewBox="0 0 24 24">
|
|
5450
|
+
<circle cx="12" cy="12" r="1" />
|
|
5451
|
+
<circle cx="19" cy="12" r="1" />
|
|
5452
|
+
<circle cx="5" cy="12" r="1" />
|
|
5453
|
+
</symbol>
|
|
5343
5454
|
<symbol id="file-diff" viewBox="0 0 24 24">
|
|
5344
5455
|
<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" />
|
|
5345
5456
|
<path d="M9 10h6" />
|
|
@@ -5448,6 +5559,11 @@ html.newmark-memory-overview-viewer body {
|
|
|
5448
5559
|
<path d="M3 16v3a2 2 0 0 0 2 2h3" />
|
|
5449
5560
|
<path d="M16 21h3a2 2 0 0 0 2-2v-3" />
|
|
5450
5561
|
</symbol>
|
|
5562
|
+
<symbol id="menu" viewBox="0 0 24 24">
|
|
5563
|
+
<path d="M4 5h16" />
|
|
5564
|
+
<path d="M4 12h16" />
|
|
5565
|
+
<path d="M4 19h16" />
|
|
5566
|
+
</symbol>
|
|
5451
5567
|
<symbol id="merge" viewBox="0 0 24 24">
|
|
5452
5568
|
<path d="m8 6 4-4 4 4" />
|
|
5453
5569
|
<path d="M12 2v10.3a4 4 0 0 1-1.172 2.872L4 22" />
|
|
@@ -5698,7 +5814,7 @@ html.newmark-memory-overview-viewer body {
|
|
|
5698
5814
|
<div id="topbar">
|
|
5699
5815
|
<span class="title" id="title-text">
|
|
5700
5816
|
<span class="logo" id="title-app-logo">
|
|
5701
|
-
<img id="title-app-icon" src="../assets/app-icon-dark
|
|
5817
|
+
<img id="title-app-icon" src="../assets/app-icon-dark.svg" alt="" aria-hidden="true">
|
|
5702
5818
|
</span>
|
|
5703
5819
|
Newmark Agent
|
|
5704
5820
|
</span>
|
|
@@ -5841,6 +5957,7 @@ html.newmark-memory-overview-viewer body {
|
|
|
5841
5957
|
<button type="button" class="tool-select model-select-button" id="model-select-button" aria-haspopup="listbox" aria-expanded="false" onclick="window.toggleModelSelectMenu()" onkeydown="window.handleModelSelectButtonKey(event)"><span class="model-select-button-label" id="model-select-label"></span><svg class="nm-icon tiny" aria-hidden="true" focusable="false"><use href="#chevron-down"></use></svg></button>
|
|
5842
5958
|
<div class="model-select-menu" id="model-select-menu" role="listbox" aria-label="Model" popover="manual"></div>
|
|
5843
5959
|
</div>
|
|
5960
|
+
<div class="conv-action-menu" id="conversation-action-menu" role="menu" aria-label="Conversation actions" popover="manual"></div>
|
|
5844
5961
|
<div class="context-token-wrap">
|
|
5845
5962
|
<button type="button" id="context-token-ring" title="Context tokens" aria-haspopup="dialog" aria-expanded="false" onclick="window.toggleContextInspector()" onmouseenter="window.showContextWindowTooltip()" onmouseleave="window.hideContextWindowTooltip()" onfocus="window.showContextWindowTooltip()" onblur="window.hideContextWindowTooltip()"><span class="icon-only-label">Context tokens</span></button>
|
|
5846
5963
|
<div id="context-token-tooltip"></div>
|
|
@@ -6184,6 +6301,7 @@ var state = {
|
|
|
6184
6301
|
agentBackend: { enabled: false, connected: true, distro: '', pid: 0, error: '' },
|
|
6185
6302
|
configuredAgentBackend: 'windows',
|
|
6186
6303
|
agentBackendRestartRequired: false,
|
|
6304
|
+
remoteTouchEnabled: true,
|
|
6187
6305
|
wslAvailable: false,
|
|
6188
6306
|
wslDistros: [],
|
|
6189
6307
|
defaultTerminalShell: 'powershell',
|
|
@@ -6364,6 +6482,11 @@ var NEWMARK_I18N = {
|
|
|
6364
6482
|
'settings.configReloaded': 'config.json refreshed',
|
|
6365
6483
|
'settings.runInWsl': 'Agent runtime environment',
|
|
6366
6484
|
'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
|
+
'settings.remoteTouch': 'Mobile remote-touch',
|
|
6486
|
+
'settings.remoteTouchDesc': 'Allow mobile access on the same LAN / Tailscale network',
|
|
6487
|
+
'settings.remoteBehavior': 'Remote behavior',
|
|
6488
|
+
'settings.remoteConnect': 'Start connection',
|
|
6489
|
+
'settings.remoteConnectDesc': 'Show pairing QR',
|
|
6367
6490
|
'settings.wslDistro': 'WSL distribution',
|
|
6368
6491
|
'settings.wslConnected': 'WSL backend connected',
|
|
6369
6492
|
'settings.wslDisconnected': 'WSL backend unavailable',
|
|
@@ -6632,6 +6755,8 @@ var NEWMARK_I18N = {
|
|
|
6632
6755
|
'plugins.management': 'Skills Management',
|
|
6633
6756
|
'plugins.market': 'Skills Market',
|
|
6634
6757
|
'plugins.github': 'GitHub CLI',
|
|
6758
|
+
'plugins.refreshGh': 'Refresh',
|
|
6759
|
+
'plugins.connectGh': 'Connect GitHub',
|
|
6635
6760
|
'plugins.noInstalled': 'No installed skills.',
|
|
6636
6761
|
'plugins.projectSkill': 'project skill',
|
|
6637
6762
|
'plugins.discovering': 'Discovering local and portable skills...',
|
|
@@ -6724,6 +6849,14 @@ var NEWMARK_I18N = {
|
|
|
6724
6849
|
'plugins.retry': 'Retry',
|
|
6725
6850
|
'plugins.dshTitle': 'DSH Plugin compatibility',
|
|
6726
6851
|
'plugins.dshHelp': 'Developer preview: inspect the locally available official DSH CLI and package configuration. Discovery is read-only and never installs, executes, updates, or rewrites DSH.',
|
|
6852
|
+
'plugins.dshInstall': 'Install into Newmark',
|
|
6853
|
+
'plugins.dshInstalled': 'Installed',
|
|
6854
|
+
'plugins.dshUninstall': 'Uninstall',
|
|
6855
|
+
'plugins.dshEnable': 'Enable',
|
|
6856
|
+
'plugins.dshDisable': 'Disable',
|
|
6857
|
+
'plugins.dshInstallOk': 'DSH plugin installed into local .Newmark.',
|
|
6858
|
+
'plugins.dshUninstallOk': 'DSH plugin removed.',
|
|
6859
|
+
'plugins.dshSetOk': 'DSH plugin setting saved.',
|
|
6727
6860
|
'plugins.dshPreview': 'Developer preview',
|
|
6728
6861
|
'plugins.dshRescan': 'Rescan',
|
|
6729
6862
|
'plugins.dshScanning': 'Scanning DSH compatibility...',
|
|
@@ -6875,6 +7008,11 @@ var NEWMARK_I18N = {
|
|
|
6875
7008
|
'status.pendingOptions': 'Pending options',
|
|
6876
7009
|
'status.noPendingOptions': 'No option question is waiting for user input.',
|
|
6877
7010
|
'status.question': 'Question',
|
|
7011
|
+
'option.manualPlaceholder': 'Or type your own answer...',
|
|
7012
|
+
'option.manualSubmit': 'Submit',
|
|
7013
|
+
'mobile.pair': 'Pair mobile device',
|
|
7014
|
+
'mobile.pairDesc': 'Scan this QR code with the Newmark mobile app on the same LAN / Tailscale network. The pairing token is saved after the first bind.',
|
|
7015
|
+
'mobile.pairTokenFile': 'Token file',
|
|
6878
7016
|
'subagent.empty': 'No retained subagent records',
|
|
6879
7017
|
'subagent.openHistory': 'Open subagent history',
|
|
6880
7018
|
'subagent.historyTitle': 'Subagent history',
|
|
@@ -6885,6 +7023,7 @@ var NEWMARK_I18N = {
|
|
|
6885
7023
|
'subagent.noMessages': 'No messages recorded.',
|
|
6886
7024
|
'subagent.unread': '{count} unread',
|
|
6887
7025
|
'conversation.archive': 'Archive',
|
|
7026
|
+
'conversation.more': 'More conversation actions',
|
|
6888
7027
|
'conversation.rename': 'Rename conversation',
|
|
6889
7028
|
'conversation.renameFailed': 'Could not rename the conversation.',
|
|
6890
7029
|
'conversation.reorderFailed': 'Could not save the conversation order.',
|
|
@@ -7070,6 +7209,11 @@ var NEWMARK_I18N = {
|
|
|
7070
7209
|
'settings.configReloaded': '已刷新 config.json',
|
|
7071
7210
|
'settings.runInWsl': 'Agent 运行环境',
|
|
7072
7211
|
'settings.runInWslDesc': 'Windows UI 与桌面原生工具保留在本机,持续 Agent 内核、模型请求、Shell 和文件工具运行在 WSL。',
|
|
7212
|
+
'settings.remoteTouch': '移动端远程触及',
|
|
7213
|
+
'settings.remoteTouchDesc': '允许移动端通过同一内网 / Tailscale 连接',
|
|
7214
|
+
'settings.remoteBehavior': '远程行为',
|
|
7215
|
+
'settings.remoteConnect': '发起连接',
|
|
7216
|
+
'settings.remoteConnectDesc': '显示配对二维码',
|
|
7073
7217
|
'settings.wslDistro': 'WSL 发行版',
|
|
7074
7218
|
'settings.wslConnected': 'WSL 后端已连接',
|
|
7075
7219
|
'settings.wslDisconnected': 'WSL 后端不可用',
|
|
@@ -7338,6 +7482,8 @@ var NEWMARK_I18N = {
|
|
|
7338
7482
|
'plugins.management': 'Skills 管理',
|
|
7339
7483
|
'plugins.market': 'Skills Market',
|
|
7340
7484
|
'plugins.github': 'GitHub CLI',
|
|
7485
|
+
'plugins.refreshGh': '刷新',
|
|
7486
|
+
'plugins.connectGh': '连接 GitHub',
|
|
7341
7487
|
'plugins.noInstalled': '暂无已安装 skill。',
|
|
7342
7488
|
'plugins.projectSkill': '项目 skill',
|
|
7343
7489
|
'plugins.discovering': '正在发现本地和便携 skill...',
|
|
@@ -7430,6 +7576,14 @@ var NEWMARK_I18N = {
|
|
|
7430
7576
|
'plugins.retry': '重试',
|
|
7431
7577
|
'plugins.dshTitle': 'DSH Plugin 兼容',
|
|
7432
7578
|
'plugins.dshHelp': '开发者预览:检查本地官方 DSH CLI 与包配置。发现过程严格只读,绝不会安装、执行、更新或改写 DSH。',
|
|
7579
|
+
'plugins.dshInstall': '安装到 Newmark',
|
|
7580
|
+
'plugins.dshInstalled': '已安装',
|
|
7581
|
+
'plugins.dshUninstall': '卸载',
|
|
7582
|
+
'plugins.dshEnable': '启用',
|
|
7583
|
+
'plugins.dshDisable': '禁用',
|
|
7584
|
+
'plugins.dshInstallOk': 'DSH 插件已安装到本地 .Newmark。',
|
|
7585
|
+
'plugins.dshUninstallOk': 'DSH 插件已移除。',
|
|
7586
|
+
'plugins.dshSetOk': 'DSH 插件设置已保存。',
|
|
7433
7587
|
'plugins.dshPreview': '开发者预览',
|
|
7434
7588
|
'plugins.dshRescan': '重新扫描',
|
|
7435
7589
|
'plugins.dshScanning': '正在扫描 DSH 兼容信息...',
|
|
@@ -7581,6 +7735,11 @@ var NEWMARK_I18N = {
|
|
|
7581
7735
|
'status.pendingOptions': '待处理选项',
|
|
7582
7736
|
'status.noPendingOptions': '暂无等待用户输入的选项问题。',
|
|
7583
7737
|
'status.question': '问题',
|
|
7738
|
+
'option.manualPlaceholder': '或输入自己的答案...',
|
|
7739
|
+
'option.manualSubmit': '提交',
|
|
7740
|
+
'mobile.pair': '配对移动设备',
|
|
7741
|
+
'mobile.pairDesc': '使用 Newmark 移动端在同一内网 / Tailscale 网络下扫描二维码。首次绑定后保存配对令牌。',
|
|
7742
|
+
'mobile.pairTokenFile': '令牌文件',
|
|
7584
7743
|
'subagent.empty': '暂无保留的 subagent 记录',
|
|
7585
7744
|
'subagent.openHistory': '打开 subagent 历史',
|
|
7586
7745
|
'subagent.historyTitle': 'Subagent 历史',
|
|
@@ -7591,6 +7750,7 @@ var NEWMARK_I18N = {
|
|
|
7591
7750
|
'subagent.noMessages': '没有记录消息。',
|
|
7592
7751
|
'subagent.unread': '{count} 条未读',
|
|
7593
7752
|
'conversation.archive': '归档',
|
|
7753
|
+
'conversation.more': '更多对话操作',
|
|
7594
7754
|
'conversation.rename': '编辑对话名称',
|
|
7595
7755
|
'conversation.renameFailed': '无法保存对话名称。',
|
|
7596
7756
|
'conversation.reorderFailed': '无法保存对话顺序。',
|
|
@@ -9993,7 +10153,7 @@ function workEventIcon(type) {
|
|
|
9993
10153
|
|
|
9994
10154
|
function workToolActivity(event) {
|
|
9995
10155
|
var name = publicToolNameForUi(event && event.toolName).toLowerCase();
|
|
9996
|
-
if (name
|
|
10156
|
+
if (isSubagentCreateToolName(name) || name.indexOf('subagent_') === 0) return { key: 'subagents', type: 'tool_subagent' };
|
|
9997
10157
|
if (name === 'skill' || name === 'skill_load' || name === 'skill_read' || name === 'skill_download') return { key: 'skills', type: 'tool_skill' };
|
|
9998
10158
|
if (name === 'mcp' || name.indexOf('mcp__') === 0 || /^mcp[:._-]/.test(name) || /[:._-]mcp[:._-]/.test(name)) return { key: 'mcp', type: 'tool_mcp' };
|
|
9999
10159
|
if (name === 'context_compression' || name === 'context_compress' || name === 'context_history_manage') return { key: 'context_compression', type: 'tool_context_compression' };
|
|
@@ -10034,8 +10194,8 @@ function workToolCommandLabel(item) {
|
|
|
10034
10194
|
var args = workToolArgsObject(item);
|
|
10035
10195
|
var toolName = publicToolNameForUi(item && item.toolName);
|
|
10036
10196
|
var normalizedName = toolName.toLowerCase();
|
|
10037
|
-
if (normalizedName
|
|
10038
|
-
return (currentLang() === 'zh' ? '调用 Subagent · ' : 'Called Subagent · ') + String(args.
|
|
10197
|
+
if (isSubagentCreateToolName(normalizedName)) {
|
|
10198
|
+
return (currentLang() === 'zh' ? '调用 Subagent · ' : 'Called Subagent · ') + String(args.name || args.nature || args.agent || 'Subagent').trim();
|
|
10039
10199
|
}
|
|
10040
10200
|
if (normalizedName.indexOf('subagent_') === 0) {
|
|
10041
10201
|
return (currentLang() === 'zh' ? 'Subagent 操作 · ' : 'Subagent action · ') + String(args.name || args.id || normalizedName.replace(/^subagent_/, '')).trim();
|
|
@@ -10074,14 +10234,19 @@ function workToolCommandLabel(item) {
|
|
|
10074
10234
|
|
|
10075
10235
|
function workToolRowIcon(item) {
|
|
10076
10236
|
var name = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10077
|
-
if (name
|
|
10237
|
+
if (isSubagentCreateToolName(name) || name.indexOf('subagent_') === 0) return 'bot';
|
|
10078
10238
|
if (name === 'skill' || name === 'skill_download') return 'sparkles';
|
|
10079
10239
|
if (name === 'mcp' || /^mcp[:._-]/.test(name) || /[:._-]mcp[:._-]/.test(name)) return 'plug';
|
|
10080
10240
|
return 'square-terminal';
|
|
10081
10241
|
}
|
|
10082
10242
|
|
|
10083
|
-
function
|
|
10243
|
+
function isSubagentCreateToolName(name) {
|
|
10084
10244
|
var normalized = String(name || '').trim().toLowerCase();
|
|
10245
|
+
return normalized === 'subagent' || normalized === 'subagent_create' || normalized === 'task';
|
|
10246
|
+
}
|
|
10247
|
+
|
|
10248
|
+
function findSubagentUiRecord(identity) {
|
|
10249
|
+
var normalized = String(identity || '').trim().toLowerCase();
|
|
10085
10250
|
return (state.subagents || []).find(function(item) {
|
|
10086
10251
|
return [item.id, item.name, item.displayName, item.qualifiedName].some(function(value) {
|
|
10087
10252
|
var candidate = String(value || '').trim().toLowerCase();
|
|
@@ -10125,7 +10290,7 @@ function workToolGroupLabel(items, completed) {
|
|
|
10125
10290
|
var name = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10126
10291
|
if (name === 'skill' || name === 'skill_load' || name === 'skill_read' || name === 'skill_download') skills.push(workToolCommandLabel(item));
|
|
10127
10292
|
else if (name === 'mcp' || name.indexOf('mcp__') === 0 || /^mcp[:._-]/.test(name) || /[:._-]mcp[:._-]/.test(name)) mcps.push(workToolCommandLabel(item));
|
|
10128
|
-
else if (name
|
|
10293
|
+
else if (isSubagentCreateToolName(name) || name.indexOf('subagent_') === 0) subagents.push(workToolCommandLabel(item));
|
|
10129
10294
|
});
|
|
10130
10295
|
var commands = Math.max(0, (items || []).length - files - skills.length - mcps.length - subagents.length);
|
|
10131
10296
|
var parts = [];
|
|
@@ -10158,24 +10323,8 @@ function renderWorkToolGroup(event, eventIndex) {
|
|
|
10158
10323
|
var hasFiles = items.some(function(item) { return !!workToolEditedFile(item); });
|
|
10159
10324
|
var onlySubagents = items.length > 0 && items.every(function(item) {
|
|
10160
10325
|
var name = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10161
|
-
return name
|
|
10326
|
+
return isSubagentCreateToolName(name);
|
|
10162
10327
|
});
|
|
10163
|
-
// A Build Block that spawns several SubAgents is summarized as one chip
|
|
10164
|
-
// ("operated N SubAgents") instead of flooding the block with one chip per
|
|
10165
|
-
// SubAgent. Each name stays available in the tooltip.
|
|
10166
|
-
var subagentTasks = items.map(function(item, itemIndex) {
|
|
10167
|
-
var name = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10168
|
-
if (name !== 'task') return null;
|
|
10169
|
-
var subagentArgs = workToolArgsObject(item);
|
|
10170
|
-
var subagentName = String(subagentArgs.nature || subagentArgs.name || subagentArgs.agent || 'Subagent').trim();
|
|
10171
|
-
var subagentRecord = findSubagentUiRecord(subagentName);
|
|
10172
|
-
return {
|
|
10173
|
-
key: String(item.id || item.toolCallId || ('task-' + itemIndex)),
|
|
10174
|
-
subagentName: subagentName || 'Subagent',
|
|
10175
|
-
status: String(subagentRecord && subagentRecord.status || 'accepted'),
|
|
10176
|
-
};
|
|
10177
|
-
}).filter(Boolean);
|
|
10178
|
-
var collapseSubagents = subagentTasks.length > 1;
|
|
10179
10328
|
var activityRows = items.map(function(item, itemIndex) {
|
|
10180
10329
|
var edited = workToolEditedFile(item);
|
|
10181
10330
|
if (edited) {
|
|
@@ -10188,26 +10337,22 @@ function renderWorkToolGroup(event, eventIndex) {
|
|
|
10188
10337
|
'<div class="conversation-work-file-diff">' + renderWorkFileDiff(edited) + '</div></details>';
|
|
10189
10338
|
}
|
|
10190
10339
|
var toolName = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10191
|
-
if (toolName
|
|
10192
|
-
if (collapseSubagents) return '';
|
|
10340
|
+
if (isSubagentCreateToolName(toolName)) {
|
|
10193
10341
|
var subagentArgs = workToolArgsObject(item);
|
|
10194
|
-
var
|
|
10195
|
-
var subagentRecord = findSubagentUiRecord(
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
|
|
10342
|
+
var requestedName = String(subagentArgs.name || subagentArgs.nature || subagentArgs.agent || 'Subagent').trim();
|
|
10343
|
+
var subagentRecord = findSubagentUiRecord(requestedName);
|
|
10344
|
+
if (!subagentRecord || !subagentRecord.id) {
|
|
10345
|
+
return '<div class="conversation-work-activity-item">' + iconSvg('square-terminal', 'tool', 'tiny') +
|
|
10346
|
+
'<div><div class="conversation-work-command-label" title="' + escAttr(workToolCommandLabel(item)) + '">' + esc(workToolCommandLabel(item)) + '</div></div></div>';
|
|
10347
|
+
}
|
|
10348
|
+
var subagentStatus = String(subagentRecord.status || 'accepted');
|
|
10349
|
+
var createdName = String(subagentRecord.name || subagentRecord.displayName || 'Subagent');
|
|
10350
|
+
return '<button type="button" class="conversation-work-subagent-chip' + (subagentStatus === 'completed' ? ' completed' : '') + '" data-subagent-id="' + escAttr(subagentRecord.id) + '" onclick="window.openSubagentFromBuild(this.getAttribute(\'data-subagent-id\'))" title="' + escAttr(currentLang() === 'zh' ? '查看 Subagent 工作情况' : 'View Subagent work') + '">' +
|
|
10351
|
+
iconSvg('bot', 'Subagent', 'tiny') + '<span class="conversation-work-subagent-name">' + esc(createdName) + '</span><span class="conversation-work-subagent-status">' + esc(subagentUiStatusLabel(subagentStatus)) + '</span></button>';
|
|
10199
10352
|
}
|
|
10200
10353
|
return '<div class="conversation-work-activity-item">' + iconSvg(workToolRowIcon(item), 'tool', 'tiny') +
|
|
10201
10354
|
'<div><div class="conversation-work-command-label" title="' + escAttr(workToolCommandLabel(item)) + '">' + esc(workToolCommandLabel(item)) + '</div>' + renderWorkDisplayImage(item.displayImage) + '</div></div>';
|
|
10202
10355
|
}).join('');
|
|
10203
|
-
if (collapseSubagents) {
|
|
10204
|
-
var allCompleted = subagentTasks.every(function(task) { return task.status === 'completed'; });
|
|
10205
|
-
var names = subagentTasks.map(function(task) { return task.subagentName; });
|
|
10206
|
-
activityRows += '<button type="button" class="conversation-work-subagent-chip conversation-work-subagent-chip-multi' + (allCompleted ? ' completed' : '') + '" title="' + escAttr(names.join(',')) + '">' +
|
|
10207
|
-
iconSvg('bot', 'Subagent', 'tiny') + '<span class="conversation-work-subagent-name">' +
|
|
10208
|
-
esc(currentLang() === 'zh' ? '操作了 ' + subagentTasks.length + ' 个 SubAgent' : 'Operated ' + subagentTasks.length + ' SubAgents') +
|
|
10209
|
-
'</span><span class="conversation-work-subagent-status">' + esc(subagentUiStatusLabel(allCompleted ? 'completed' : subagentTasks[0].status)) + '</span></button>';
|
|
10210
|
-
}
|
|
10211
10356
|
return '<details class="conversation-work-activity" data-activity-key="' + escAttr(activityDomKey) + '"><summary>' +
|
|
10212
10357
|
iconSvg(hasFiles ? 'pencil' : 'square-terminal', 'tools', 'tiny') + '<span>' + esc(workToolGroupLabel(items, !!event.completed)) + '</span>' +
|
|
10213
10358
|
'<span class="conversation-work-activity-chevron" aria-hidden="true"></span></summary><div class="conversation-work-activity-list' + (onlySubagents ? ' conversation-work-subagent-list' : '') + '">' +
|
|
@@ -10509,17 +10654,32 @@ function renderConversationWorkRuns(runs, target) {
|
|
|
10509
10654
|
// every delta can starve Chromium's renderer/CDP event loop.
|
|
10510
10655
|
var pendingConversationWorkRunRenders = {};
|
|
10511
10656
|
var scheduledConversationWorkRunRenders = {};
|
|
10657
|
+
var lastConversationWorkRunRenderAt = {};
|
|
10658
|
+
var WORK_RUN_RENDER_MIN_INTERVAL_MS = 100;
|
|
10659
|
+
function flushConversationWorkRunRender(key) {
|
|
10660
|
+
var latest = pendingConversationWorkRunRenders[key];
|
|
10661
|
+
delete pendingConversationWorkRunRenders[key];
|
|
10662
|
+
delete scheduledConversationWorkRunRenders[key];
|
|
10663
|
+
if (!latest || !isActiveConversationTarget(latest.target)) return;
|
|
10664
|
+
lastConversationWorkRunRenderAt[key] = performance.now();
|
|
10665
|
+
renderConversationWorkRun(latest);
|
|
10666
|
+
}
|
|
10512
10667
|
function scheduleConversationWorkRunRender(run) {
|
|
10513
10668
|
var key = runtimeKeyFor(run.target && run.target.workspaceId, run.target && run.target.conversationId) + '::' + String(run.runId || '');
|
|
10514
10669
|
pendingConversationWorkRunRenders[key] = run;
|
|
10515
10670
|
if (scheduledConversationWorkRunRenders[key]) return;
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
|
|
10521
|
-
|
|
10522
|
-
|
|
10671
|
+
var elapsed = performance.now() - Number(lastConversationWorkRunRenderAt[key] || 0);
|
|
10672
|
+
var delay = Math.max(0, WORK_RUN_RENDER_MIN_INTERVAL_MS - elapsed);
|
|
10673
|
+
scheduledConversationWorkRunRenders[key] = setTimeout(function() {
|
|
10674
|
+
requestAnimationFrame(function() { flushConversationWorkRunRender(key); });
|
|
10675
|
+
}, delay);
|
|
10676
|
+
}
|
|
10677
|
+
|
|
10678
|
+
function renderConversationWorkRunImmediately(run) {
|
|
10679
|
+
var key = runtimeKeyFor(run.target && run.target.workspaceId, run.target && run.target.conversationId) + '::' + String(run.runId || '');
|
|
10680
|
+
pendingConversationWorkRunRenders[key] = run;
|
|
10681
|
+
if (scheduledConversationWorkRunRenders[key]) clearTimeout(scheduledConversationWorkRunRenders[key]);
|
|
10682
|
+
flushConversationWorkRunRender(key);
|
|
10523
10683
|
}
|
|
10524
10684
|
|
|
10525
10685
|
function applyAgentWorkEventToRun(event) {
|
|
@@ -10582,7 +10742,9 @@ function applyAgentWorkEventToRun(event) {
|
|
|
10582
10742
|
if (isActiveConversationTarget(target) && (!branchIds.viewed || !eventBranchId || branchIds.viewed === eventBranchId)) {
|
|
10583
10743
|
state.workRunsByTarget[runtimeKeyFor(target.workspaceId, target.conversationId)] = runs;
|
|
10584
10744
|
var existingElement = findWorkRunElement(run);
|
|
10745
|
+
var terminalRender = ['done', 'error', 'interrupted', 'force_interrupted', 'final_response'].indexOf(type) >= 0;
|
|
10585
10746
|
if (!existingElement || type === 'start') renderConversationWorkRun(run);
|
|
10747
|
+
else if (terminalRender) renderConversationWorkRunImmediately(run);
|
|
10586
10748
|
else scheduleConversationWorkRunRender(run);
|
|
10587
10749
|
}
|
|
10588
10750
|
return run;
|
|
@@ -11320,7 +11482,7 @@ function appendAgentWorkEvent(event) {
|
|
|
11320
11482
|
setWorking(!!runningConversationRecord(activeConversationId()) || currentFlowRunning());
|
|
11321
11483
|
updateSubmitButtonState();
|
|
11322
11484
|
}
|
|
11323
|
-
if (active && event.type === 'tool_result' && ['linked_plan', 'task', 'subagent_send', 'subagent_read', 'subagent_close'].indexOf(String(event.toolName || '')) >= 0 && api.getState) {
|
|
11485
|
+
if (active && event.type === 'tool_result' && ['linked_plan', 'task_read', 'task_create', 'task', 'subagent_create', 'SubAgent', 'subagent_send', 'subagent_read', 'subagent_close'].indexOf(String(event.toolName || '')) >= 0 && api.getState) {
|
|
11324
11486
|
var eventWorkspaceKey = currentWorkspaceKey();
|
|
11325
11487
|
api.getState(target).then(function(snapshot) {
|
|
11326
11488
|
if (!isActiveConversationTarget(target) || eventWorkspaceKey !== currentWorkspaceKey()) return;
|
|
@@ -11521,6 +11683,10 @@ function addOptionBlock(question, options, questionKey) {
|
|
|
11521
11683
|
html += '<button class="option-btn" data-option-question-key="' + escAttr(encodeURIComponent(questionKey)) + '" data-option-label="' + escAttr(label) + '" onclick="window.optionSelected(decodeURIComponent(this.dataset.optionQuestionKey),this.dataset.optionLabel,this)">' +
|
|
11522
11684
|
esc(label) + (desc ? '<span class="option-desc">' + esc(desc) + '</span>' : '') + '</button>';
|
|
11523
11685
|
}
|
|
11686
|
+
html += '<div class="option-manual">' +
|
|
11687
|
+
'<input class="option-manual-input" data-option-question-key="' + escAttr(encodeURIComponent(questionKey)) + '" placeholder="' + escAttr(t('option.manualPlaceholder')) + '" onkeydown="if(event.key===\'Enter\'){event.preventDefault();window.optionManualSubmitted(this);}" />' +
|
|
11688
|
+
'<button class="option-manual-submit" onclick="window.optionManualSubmitted(this)">' + esc(t('option.manualSubmit')) + '</button>' +
|
|
11689
|
+
'</div>';
|
|
11524
11690
|
html += '</div>';
|
|
11525
11691
|
div.innerHTML = html;
|
|
11526
11692
|
els['chat-area'].appendChild(div);
|
|
@@ -11637,6 +11803,20 @@ window.optionSelected = function(questionKey, opt, button) {
|
|
|
11637
11803
|
window.sendMessage();
|
|
11638
11804
|
};
|
|
11639
11805
|
|
|
11806
|
+
window.optionManualSubmitted = function(element) {
|
|
11807
|
+
var manual = element && element.closest ? element.closest('.option-manual') : null;
|
|
11808
|
+
if (!manual) return;
|
|
11809
|
+
var input = manual.querySelector('.option-manual-input');
|
|
11810
|
+
if (!input) return;
|
|
11811
|
+
var value = String(input.value || '').trim();
|
|
11812
|
+
if (!value) { input.focus(); return; }
|
|
11813
|
+
var key = input.getAttribute('data-option-question-key') || '';
|
|
11814
|
+
var decoded;
|
|
11815
|
+
try { decoded = decodeURIComponent(key); } catch (e) { decoded = key; }
|
|
11816
|
+
window.optionSelected(decoded, value, input);
|
|
11817
|
+
Array.from(manual.querySelectorAll('input, button')).forEach(function(control) { control.disabled = true; });
|
|
11818
|
+
};
|
|
11819
|
+
|
|
11640
11820
|
// === Working State ===
|
|
11641
11821
|
function setWorking(working) {
|
|
11642
11822
|
state.isWorking = working;
|
|
@@ -12230,6 +12410,119 @@ window.selectModelFromMenu = function(value) {
|
|
|
12230
12410
|
window.closeModelSelectMenu({ focus: true });
|
|
12231
12411
|
};
|
|
12232
12412
|
|
|
12413
|
+
window.closeConversationActionMenu = function(options) {
|
|
12414
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12415
|
+
var anchor = state.conversationActionAnchor;
|
|
12416
|
+
if (menu && typeof menu.hidePopover === 'function' && menu.matches(':popover-open')) menu.hidePopover();
|
|
12417
|
+
document.querySelectorAll('.conv-more-btn[aria-expanded="true"]').forEach(function(item) { item.setAttribute('aria-expanded', 'false'); });
|
|
12418
|
+
state.conversationActionAnchor = null;
|
|
12419
|
+
if (options && options.focus && anchor && anchor.focus) anchor.focus();
|
|
12420
|
+
};
|
|
12421
|
+
|
|
12422
|
+
window.positionConversationActionMenu = function(anchor, menu, pos) {
|
|
12423
|
+
if (!menu) return;
|
|
12424
|
+
var width = 168;
|
|
12425
|
+
var margin = 8;
|
|
12426
|
+
menu.style.width = width + 'px';
|
|
12427
|
+
var rect = anchor && anchor.getBoundingClientRect ? anchor.getBoundingClientRect() : null;
|
|
12428
|
+
var desiredHeight = Math.min(320, menu.scrollHeight || menu.offsetHeight || 0);
|
|
12429
|
+
var left, top, below, above, openAbove;
|
|
12430
|
+
if (pos && typeof pos.x === 'number' && typeof pos.y === 'number') {
|
|
12431
|
+
left = Math.max(margin, Math.min(window.innerWidth - width - margin, pos.x));
|
|
12432
|
+
below = Math.max(0, window.innerHeight - pos.y - margin);
|
|
12433
|
+
above = Math.max(0, pos.y - margin);
|
|
12434
|
+
openAbove = below < desiredHeight && above > below;
|
|
12435
|
+
top = openAbove ? Math.max(margin, pos.y - Math.min(desiredHeight, above) - margin) : pos.y + margin;
|
|
12436
|
+
} else if (rect) {
|
|
12437
|
+
left = Math.max(margin, Math.min(window.innerWidth - width - margin, rect.right - width));
|
|
12438
|
+
below = Math.max(0, window.innerHeight - rect.bottom - margin);
|
|
12439
|
+
above = Math.max(0, rect.top - margin);
|
|
12440
|
+
openAbove = below < desiredHeight && above > below;
|
|
12441
|
+
top = openAbove ? Math.max(margin, rect.top - Math.min(desiredHeight, above) - margin) : rect.bottom + margin;
|
|
12442
|
+
} else {
|
|
12443
|
+
left = Math.max(margin, Math.round((window.innerWidth - width) / 2));
|
|
12444
|
+
top = Math.round(window.innerHeight / 3);
|
|
12445
|
+
}
|
|
12446
|
+
menu.style.left = left + 'px';
|
|
12447
|
+
menu.style.top = top + 'px';
|
|
12448
|
+
};
|
|
12449
|
+
|
|
12450
|
+
window.openConversationActionMenu = function(anchor, conversationId, pos) {
|
|
12451
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12452
|
+
if (!menu) return;
|
|
12453
|
+
var convs = currentWorkspaceConversations();
|
|
12454
|
+
var idx = convs.findIndex(function(item) { return String(item && item.id || 'default') === String(conversationId || ''); });
|
|
12455
|
+
var conv = convs[idx];
|
|
12456
|
+
if (!conv) return;
|
|
12457
|
+
window.closeModelSelectMenu();
|
|
12458
|
+
document.querySelectorAll('.newmark-select-shell.open').forEach(function(item) { window.closeNewmarkSelect(item); });
|
|
12459
|
+
var pendingKey = currentWorkspaceKey() + '::' + String(conv.id);
|
|
12460
|
+
var pending = !!state.conversationArchivePending[pendingKey];
|
|
12461
|
+
var pinLabel = conv.pinned ? t('conversation.unpin') : t('conversation.pin');
|
|
12462
|
+
var archiveHtml = pending
|
|
12463
|
+
? '<button type="button" class="conv-action-menu-item" disabled><span class="conv-archive-spinner"></span><span>' + esc(t('archive.archiving')) + '</span></button>'
|
|
12464
|
+
: '<button type="button" class="conv-action-menu-item" data-action="archive" onclick="window.runConversationAction(this, \'archive\')">' + iconSvg('archive', '', 'small') + '<span>' + esc(t('conversation.archive')) + '</span></button>';
|
|
12465
|
+
menu.innerHTML =
|
|
12466
|
+
'<button type="button" class="conv-action-menu-item" data-action="edit" onclick="window.runConversationAction(this, \'edit\')">' + iconSvg('pencil', '', 'small') + '<span>' + esc(t('conversation.rename')) + '</span></button>' +
|
|
12467
|
+
archiveHtml +
|
|
12468
|
+
'<button type="button" class="conv-action-menu-item' + (conv.pinned ? ' active' : '') + '" data-action="pin" onclick="window.runConversationAction(this, \'pin\')">' + iconSvg('pin', '', 'small') + '<span>' + esc(pinLabel) + '</span></button>';
|
|
12469
|
+
menu.setAttribute('data-index', String(idx));
|
|
12470
|
+
var moreBtn = anchor && anchor.classList && anchor.classList.contains('conv-more-btn') ? anchor : (anchor && anchor.querySelector ? anchor.querySelector('.conv-more-btn') : null);
|
|
12471
|
+
document.querySelectorAll('.conv-more-btn[aria-expanded="true"]').forEach(function(item) { item.setAttribute('aria-expanded', 'false'); });
|
|
12472
|
+
if (moreBtn) moreBtn.setAttribute('aria-expanded', 'true');
|
|
12473
|
+
state.conversationActionAnchor = anchor || moreBtn || null;
|
|
12474
|
+
if (typeof menu.showPopover === 'function' && !menu.matches(':popover-open')) menu.showPopover();
|
|
12475
|
+
requestAnimationFrame(function() {
|
|
12476
|
+
window.positionConversationActionMenu(state.conversationActionAnchor || moreBtn, menu, pos);
|
|
12477
|
+
var item = menu.querySelector('.conv-action-menu-item:not(:disabled)');
|
|
12478
|
+
if (item) item.focus({ preventScroll: true });
|
|
12479
|
+
});
|
|
12480
|
+
};
|
|
12481
|
+
|
|
12482
|
+
window.runConversationAction = function(button, action) {
|
|
12483
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12484
|
+
var idx = Number(menu && menu.getAttribute('data-index') || '-1');
|
|
12485
|
+
window.closeConversationActionMenu();
|
|
12486
|
+
var convs = currentWorkspaceConversations();
|
|
12487
|
+
var conv = convs[idx];
|
|
12488
|
+
if (!conv) return;
|
|
12489
|
+
if (action === 'edit') window.editConversationName(idx);
|
|
12490
|
+
else if (action === 'archive') window.archiveConv(String(conv.id || 'default'));
|
|
12491
|
+
else if (action === 'pin') window.toggleConversationPinned(idx);
|
|
12492
|
+
};
|
|
12493
|
+
|
|
12494
|
+
document.addEventListener('pointerdown', function(event) {
|
|
12495
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12496
|
+
if (!menu || !menu.matches || !menu.matches(':popover-open')) return;
|
|
12497
|
+
var anchor = state.conversationActionAnchor;
|
|
12498
|
+
if (anchor && anchor.contains && anchor.contains(event.target)) return;
|
|
12499
|
+
if (menu.contains(event.target)) return;
|
|
12500
|
+
window.closeConversationActionMenu();
|
|
12501
|
+
});
|
|
12502
|
+
|
|
12503
|
+
document.addEventListener('keydown', function(event) {
|
|
12504
|
+
if (event.key === 'Escape') window.closeConversationActionMenu();
|
|
12505
|
+
});
|
|
12506
|
+
|
|
12507
|
+
(function() {
|
|
12508
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12509
|
+
if (!menu) return;
|
|
12510
|
+
menu.addEventListener('keydown', function(event) {
|
|
12511
|
+
if (event.key === 'Escape') {
|
|
12512
|
+
event.preventDefault();
|
|
12513
|
+
window.closeConversationActionMenu({ focus: true });
|
|
12514
|
+
return;
|
|
12515
|
+
}
|
|
12516
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;
|
|
12517
|
+
event.preventDefault();
|
|
12518
|
+
var items = Array.prototype.slice.call(menu.querySelectorAll('.conv-action-menu-item:not(:disabled)'));
|
|
12519
|
+
if (!items.length) return;
|
|
12520
|
+
var current = items.indexOf(document.activeElement);
|
|
12521
|
+
var next = event.key === 'ArrowDown' ? items[(current + 1) % items.length] : items[(current - 1 + items.length) % items.length];
|
|
12522
|
+
if (next) next.focus();
|
|
12523
|
+
});
|
|
12524
|
+
})();
|
|
12525
|
+
|
|
12233
12526
|
window.handleModelSelectButtonKey = function(event) {
|
|
12234
12527
|
if (!event) return;
|
|
12235
12528
|
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
@@ -15244,7 +15537,20 @@ function renderGeneralSettings() {
|
|
|
15244
15537
|
'<div class="setting-row"><span class="setting-label">' + esc(t('settings.wslDistro')) + '</span>' +
|
|
15245
15538
|
'<div class="setting-control"><select id="agent-wsl-distro" onchange="window.setAgentWslDistro(this.value)"' + (state.wslAvailable ? '' : ' disabled') + '>' + (wslOptions || '<option>Ubuntu-24.04</option>') + '</select>' +
|
|
15246
15539
|
'<div class="setting-desc" id="agent-wsl-status">' + esc(state.agentBackend && state.agentBackend.connected ? t('settings.wslConnected') : t('settings.wslDisconnected')) + '</div></div></div>' : '';
|
|
15247
|
-
return wslHtml + '<div class="setting-
|
|
15540
|
+
return wslHtml + '<div class="setting-subsection">' +
|
|
15541
|
+
'<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>' +
|
|
15547
|
+
'</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>' +
|
|
15551
|
+
'</div>' +
|
|
15552
|
+
'</div>' +
|
|
15553
|
+
'<div class="setting-row">' +
|
|
15248
15554
|
'<span class="setting-label">' + esc(t('settings.configFile')) + '</span>' +
|
|
15249
15555
|
'<div class="setting-control"><div style="display:flex;align-items:center;gap:7px;flex-wrap:wrap;">' +
|
|
15250
15556
|
'<button type="button" class="sec-btn" onclick="window.openGlobalConfigFile()">' + esc(t('settings.openConfig')) + '</button>' +
|
|
@@ -15898,8 +16204,7 @@ var systemColorScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
15898
16204
|
window.refreshTitlebarThemeIcon = function() {
|
|
15899
16205
|
var icon = document.getElementById('title-app-icon');
|
|
15900
16206
|
if (!icon) return;
|
|
15901
|
-
|
|
15902
|
-
icon.src = useDarkTheme ? '../assets/app-icon-dark-64.png' : '../assets/app-icon-light-64.png';
|
|
16207
|
+
icon.src = '../assets/app-icon-dark.svg';
|
|
15903
16208
|
};
|
|
15904
16209
|
window.refreshTitlebarSystemIcon = window.refreshTitlebarThemeIcon;
|
|
15905
16210
|
if (systemColorScheme.addEventListener) systemColorScheme.addEventListener('change', function() {
|
|
@@ -15920,6 +16225,15 @@ window.setAgentBackendMode = async function(mode) {
|
|
|
15920
16225
|
return true;
|
|
15921
16226
|
};
|
|
15922
16227
|
|
|
16228
|
+
window.setRemoteTouchEnabled = async function(value) {
|
|
16229
|
+
var next = !!value;
|
|
16230
|
+
state.remoteTouchEnabled = next;
|
|
16231
|
+
if (api.saveSetting) {
|
|
16232
|
+
try { await api.saveSetting('remote', 'touch_enabled', next); } catch (e) {}
|
|
16233
|
+
}
|
|
16234
|
+
window.settingsTab('general');
|
|
16235
|
+
};
|
|
16236
|
+
|
|
15923
16237
|
window.setAgentWslDistro = async function(value) {
|
|
15924
16238
|
var distro = String(value || '').trim() || 'Ubuntu-24.04';
|
|
15925
16239
|
await api.saveSetting('agent', 'wsl_distro', distro);
|
|
@@ -18171,9 +18485,9 @@ window.renderSubagentList = function() {
|
|
|
18171
18485
|
var unread = Number(a.mailbox && a.mailbox.unread || 0);
|
|
18172
18486
|
var queue = a.status === 'queued' && a.queueSequence ? (' · #' + a.queueSequence) : '';
|
|
18173
18487
|
var meta = esc((a.agentMode || a.mode || 'build') + ' / ' + (a.model || t('common.default')) + ' / ' + ((a.messages || []).length || a.messageCount || 0) + ' ' + t('common.messageShort') + queue + (unread ? (' · ' + t('subagent.unread').replace('{count}', String(unread))) : ''));
|
|
18174
|
-
var display = a.
|
|
18175
|
-
var qualified = a.qualifiedName || a.
|
|
18176
|
-
html += '<button type="button"
|
|
18488
|
+
var display = a.name || a.displayName || a.id || 'Agent';
|
|
18489
|
+
var qualified = a.qualifiedName || a.id || display;
|
|
18490
|
+
html += '<button type="button" data-subagent-id="' + escAttr(a.id || '') + '" onclick="window.openSubagentHistory(this.getAttribute(\'data-subagent-id\'))" title="' + escAttr(t('subagent.openHistory')) + '" style="width:100%;display:flex;align-items:center;gap:6px;padding:7px 8px;font-size:12px;border:0;border-bottom:1px solid var(--glass-border-1);background:transparent;text-align:left;cursor:pointer;">' +
|
|
18177
18491
|
iconSvg('bot', 'Subagent', 'small') +
|
|
18178
18492
|
'<span style="flex:1;min-width:0;color:var(--text);" title="' + escAttr(qualified) + '"><span style="display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">' + esc(display) + '</span><span style="display:block;color:var(--text-dim);font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">' + meta + '</span></span>' +
|
|
18179
18493
|
'<span style="color:var(--accent2);font-size:10px;">' + esc(a.status || t('common.idle')) + '</span>' +
|
|
@@ -18185,10 +18499,10 @@ window.renderSubagentList = function() {
|
|
|
18185
18499
|
};
|
|
18186
18500
|
|
|
18187
18501
|
window.refreshSubagentBuildChips = function() {
|
|
18188
|
-
var chips = document.querySelectorAll('.conversation-work-subagent-chip[data-subagent-
|
|
18502
|
+
var chips = document.querySelectorAll('.conversation-work-subagent-chip[data-subagent-id]');
|
|
18189
18503
|
for (var i = 0; i < chips.length; i++) {
|
|
18190
18504
|
var chip = chips[i];
|
|
18191
|
-
var record = findSubagentUiRecord(chip.getAttribute('data-subagent-
|
|
18505
|
+
var record = findSubagentUiRecord(chip.getAttribute('data-subagent-id'));
|
|
18192
18506
|
var status = String(record && record.status || 'accepted');
|
|
18193
18507
|
chip.classList.toggle('completed', status === 'completed');
|
|
18194
18508
|
var statusEl = chip.querySelector('.conversation-work-subagent-status');
|
|
@@ -18214,15 +18528,15 @@ window.scheduleSubagentStateRefresh = function() {
|
|
|
18214
18528
|
}, 1200);
|
|
18215
18529
|
};
|
|
18216
18530
|
|
|
18217
|
-
window.openSubagentFromBuild = function(
|
|
18218
|
-
var requested = String(
|
|
18531
|
+
window.openSubagentFromBuild = function(id) {
|
|
18532
|
+
var requested = String(id || '').trim();
|
|
18219
18533
|
var openLatest = function() {
|
|
18220
18534
|
var agent = findSubagentUiRecord(requested);
|
|
18221
18535
|
if (!agent) {
|
|
18222
18536
|
showUiNotice((currentLang() === 'zh' ? '尚未找到 Subagent:' : 'Subagent is not available yet: ') + requested, 'error', 'subagent-build-' + requested);
|
|
18223
18537
|
return false;
|
|
18224
18538
|
}
|
|
18225
|
-
window.openSubagentHistory(agent.id
|
|
18539
|
+
window.openSubagentHistory(agent.id);
|
|
18226
18540
|
return true;
|
|
18227
18541
|
};
|
|
18228
18542
|
if (!api.getState) return Promise.resolve(openLatest());
|
|
@@ -18380,13 +18694,17 @@ window.closeSubagentHistory = function() {
|
|
|
18380
18694
|
|
|
18381
18695
|
window.openSubagentHistory = function(id) {
|
|
18382
18696
|
var agents = state.subagents || [];
|
|
18383
|
-
var agent = agents.find(function(a) { return a.id === id
|
|
18384
|
-
|
|
18697
|
+
var agent = agents.find(function(a) { return a.id === id; });
|
|
18698
|
+
if (!agent) {
|
|
18699
|
+
showUiNotice((currentLang() === 'zh' ? '尚未找到真实 Subagent:' : 'Real Subagent is not available: ') + String(id || ''), 'error', 'subagent-history-' + String(id || 'missing'));
|
|
18700
|
+
return false;
|
|
18701
|
+
}
|
|
18702
|
+
state.subagentHistoryActorId = agent.id;
|
|
18385
18703
|
var existing = document.getElementById('subagent-history-overlay');
|
|
18386
18704
|
if (existing) existing.remove();
|
|
18387
18705
|
var lines = [];
|
|
18388
|
-
lines.push('<div style="font-size:13px;color:var(--text);font-weight:600;margin-bottom:4px;">' + esc(agent.
|
|
18389
|
-
lines.push('<div style="font-size:10px;color:var(--text-dim);word-break:break-all;margin-bottom:8px;">' + esc(agent.qualifiedName || agent.
|
|
18706
|
+
lines.push('<div style="font-size:13px;color:var(--text);font-weight:600;margin-bottom:4px;">' + esc(agent.name || agent.displayName || t('subagent.historyTitle')) + '</div>');
|
|
18707
|
+
lines.push('<div style="font-size:10px;color:var(--text-dim);word-break:break-all;margin-bottom:8px;">' + esc(agent.qualifiedName || agent.id || '') + '</div>');
|
|
18390
18708
|
lines.push('<div id="subagent-history-meta" style="font-size:11px;color:var(--text-dim);margin-bottom:10px;">' + esc((agent.status || t('common.idle')) + ' / ' + (agent.agentMode || agent.mode || 'build') + ' / ' + (agent.model || t('common.default')) + (agent.mailbox && agent.mailbox.unread ? (' / ' + agent.mailbox.unread + ' unread') : '')) + '</div>');
|
|
18391
18709
|
var compression = agent.metadata && agent.metadata.contextCompression;
|
|
18392
18710
|
if (compression) {
|
|
@@ -18416,6 +18734,7 @@ window.openSubagentHistory = function(id) {
|
|
|
18416
18734
|
for (var i = 0; i < cached.length; i++) renderSubagentPeerEvent(cached[i]);
|
|
18417
18735
|
autoScrollSubagentHistory(body);
|
|
18418
18736
|
window.scheduleSubagentStateRefresh();
|
|
18737
|
+
return true;
|
|
18419
18738
|
};
|
|
18420
18739
|
|
|
18421
18740
|
// === Browser ===
|
|
@@ -19058,16 +19377,15 @@ function renderConversations() {
|
|
|
19058
19377
|
? '<span class="conv-runtime-badge ' + escAttr(String(runtimeState.status)) + '">' + esc(String(runtimeState.status)) + '</span>' : '';
|
|
19059
19378
|
var branchCommIcon = conv.branchCommunication
|
|
19060
19379
|
? '<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
19380
|
div.innerHTML = '<span class="conv-summary" title="' + escAttr(String(conv.id || '')) + '">' + esc(displaySummary) + (conv.messageCount ? ' (' + esc(String(conv.messageCount)) + ')' : '') + '</span>' + branchCommIcon + runtimeBadge +
|
|
19066
|
-
'<button class="conv-
|
|
19067
|
-
archiveBtn +
|
|
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>';
|
|
19381
|
+
'<button class="conv-more-btn" aria-haspopup="menu" aria-expanded="false" onclick="event.stopPropagation();window.openConversationActionMenu(this, this.closest(".conv-item").getAttribute("data-conversation-id"))" title="' + escAttr(t('conversation.more')) + '">' + iconOnly('ellipsis', t('conversation.more')) + '</button>';
|
|
19069
19382
|
div.onclick = function(idx) { return function() { window.switchConversation(idx); }; }(i);
|
|
19070
19383
|
div.addEventListener('keydown', window.handleConversationKey);
|
|
19384
|
+
div.addEventListener('contextmenu', function(event) {
|
|
19385
|
+
event.preventDefault();
|
|
19386
|
+
event.stopPropagation();
|
|
19387
|
+
window.openConversationActionMenu(event.currentTarget, this.getAttribute('data-conversation-id') || '', { x: event.clientX, y: event.clientY });
|
|
19388
|
+
});
|
|
19071
19389
|
div.addEventListener('dragstart', function(event) {
|
|
19072
19390
|
this.classList.add('dragging');
|
|
19073
19391
|
if (event.dataTransfer) { event.dataTransfer.effectAllowed = 'move'; event.dataTransfer.setData('text/plain', this.getAttribute('data-conversation-id') || ''); }
|
|
@@ -20481,6 +20799,59 @@ window.openDshOfficial = function(kind) {
|
|
|
20481
20799
|
});
|
|
20482
20800
|
};
|
|
20483
20801
|
|
|
20802
|
+
function renderDshBundlesMarkup(bundles) {
|
|
20803
|
+
var values = dshCollection(bundles);
|
|
20804
|
+
if (!values.length) return '<div class="plugin-empty">' + esc(t('plugins.dshNone')) + '</div>';
|
|
20805
|
+
return '<div class="dsh-list">' + values.map(function(item, index) {
|
|
20806
|
+
var name = String(item.name || item.id || 'dsh-plugin');
|
|
20807
|
+
var manifestPath = String(item.manifestPath || '');
|
|
20808
|
+
var installed = !!item.installed;
|
|
20809
|
+
var enabled = item.enabled !== false;
|
|
20810
|
+
var actionHtml = installed
|
|
20811
|
+
? '<div class="dsh-candidate-actions">' +
|
|
20812
|
+
'<label class="toggle"><input type="checkbox" id="dsh-bundle-enabled-' + index + '"' + (enabled ? ' checked' : '') + ' onchange="window.setDshBundleEnabled(' + index + ', this.checked)"><span class="toggle-track"></span></label>' +
|
|
20813
|
+
'<span style="font-size:11px;color:var(--text-dim);">' + esc(t(enabled ? 'plugins.dshEnable' : 'plugins.dshDisable')) + '</span>' +
|
|
20814
|
+
'<button type="button" class="sec-btn" onclick="window.uninstallDshBundle(' + index + ')">' + esc(t('plugins.dshUninstall')) + '</button>' +
|
|
20815
|
+
'<span class="plugin-status-badge">' + esc(t('plugins.dshInstalled')) + '</span></div>'
|
|
20816
|
+
: '<div class="dsh-candidate-actions"><button type="button" class="sec-btn primary" onclick="window.installDshBundle(' + index + ')"' + (manifestPath ? '' : ' disabled') + '>' + esc(t('plugins.dshInstall')) + '</button></div>';
|
|
20817
|
+
return '<div class="dsh-list-item"><strong>' + esc(name) + '</strong>' +
|
|
20818
|
+
'<div class="provider-meta">' + esc(String(item.source || '')) + '</div>' + actionHtml + '</div>';
|
|
20819
|
+
}).join('') + '</div>';
|
|
20820
|
+
}
|
|
20821
|
+
|
|
20822
|
+
window.installDshBundle = function(index) {
|
|
20823
|
+
var bundle = dshCollection(state.dshCompatibility && state.dshCompatibility.bundles)[index];
|
|
20824
|
+
if (!bundle || !bundle.manifestPath) return;
|
|
20825
|
+
if (!api.installDshBundle) { showUiNotice(t('plugins.dshUnavailable'), 'error', 'dsh-install'); return; }
|
|
20826
|
+
api.installDshBundle(bundle.manifestPath).then(function(result) {
|
|
20827
|
+
if (!result || !result.ok) throw new Error((result && result.error) || t('plugins.dshLoadError'));
|
|
20828
|
+
showUiNotice(t('plugins.dshInstallOk'), 'success', 'dsh-install-' + bundle.name);
|
|
20829
|
+
window.renderDshPlugin();
|
|
20830
|
+
}).catch(function(error) { showUiNotice(error.message || String(error), 'error', 'dsh-install-' + bundle.name); });
|
|
20831
|
+
};
|
|
20832
|
+
|
|
20833
|
+
window.uninstallDshBundle = function(index) {
|
|
20834
|
+
var bundle = dshCollection(state.dshCompatibility && state.dshCompatibility.bundles)[index];
|
|
20835
|
+
if (!bundle || !bundle.name) return;
|
|
20836
|
+
if (!api.uninstallDshBundle) { showUiNotice(t('plugins.dshUnavailable'), 'error', 'dsh-uninstall'); return; }
|
|
20837
|
+
api.uninstallDshBundle(bundle.name).then(function(result) {
|
|
20838
|
+
if (!result || !result.ok) throw new Error((result && result.error) || t('plugins.dshLoadError'));
|
|
20839
|
+
showUiNotice(t('plugins.dshUninstallOk'), 'success', 'dsh-uninstall-' + bundle.name);
|
|
20840
|
+
window.renderDshPlugin();
|
|
20841
|
+
}).catch(function(error) { showUiNotice(error.message || String(error), 'error', 'dsh-uninstall-' + bundle.name); });
|
|
20842
|
+
};
|
|
20843
|
+
|
|
20844
|
+
window.setDshBundleEnabled = function(index, enabled) {
|
|
20845
|
+
var bundle = dshCollection(state.dshCompatibility && state.dshCompatibility.bundles)[index];
|
|
20846
|
+
if (!bundle || !bundle.name) return;
|
|
20847
|
+
if (!api.setDshBundleEnabled) { showUiNotice(t('plugins.dshUnavailable'), 'error', 'dsh-toggle'); return; }
|
|
20848
|
+
api.setDshBundleEnabled(bundle.name, !!enabled).then(function(result) {
|
|
20849
|
+
if (!result || !result.ok) throw new Error((result && result.error) || t('plugins.dshLoadError'));
|
|
20850
|
+
showUiNotice(t('plugins.dshSetOk'), 'success', 'dsh-toggle-' + bundle.name);
|
|
20851
|
+
window.renderDshPlugin();
|
|
20852
|
+
}).catch(function(error) { showUiNotice(error.message || String(error), 'error', 'dsh-toggle-' + bundle.name); });
|
|
20853
|
+
};
|
|
20854
|
+
|
|
20484
20855
|
window.renderDshPlugin = function() {
|
|
20485
20856
|
var panel = document.getElementById('plugin-panel');
|
|
20486
20857
|
if (!panel || state.pluginActiveTab !== 'dsh') return;
|
|
@@ -20538,7 +20909,7 @@ window.renderDshPluginContent = function() {
|
|
|
20538
20909
|
'<dt>' + esc(t('plugins.dshUpdateChannel')) + '</dt><dd id="dsh-update-channel">' + esc(dshDisplayValue(updateChannel)) + '</dd></dl>' +
|
|
20539
20910
|
'<div class="dsh-description">' + esc(t('plugins.dshReadonlyDetail')) + '</div></section>' +
|
|
20540
20911
|
'<section class="dsh-card" id="dsh-profiles-card"><div class="dsh-card-title">' + esc(t('plugins.dshProfiles')) + '</div>' + dshListMarkup(dsh.profiles) + '</section>' +
|
|
20541
|
-
'<section class="dsh-card" id="dsh-bundles-card"><div class="dsh-card-title">' + esc(t('plugins.dshBundles')) + '</div>' +
|
|
20912
|
+
'<section class="dsh-card" id="dsh-bundles-card"><div class="dsh-card-title">' + esc(t('plugins.dshBundles')) + '</div>' + renderDshBundlesMarkup(dsh.bundles) + '</section>' +
|
|
20542
20913
|
'<section class="dsh-card" id="dsh-warnings-card"><div class="dsh-card-title">' + esc(t('plugins.dshWarnings')) + '</div>' + dshListMarkup(dsh.warnings, t('plugins.dshNone'), true) + '</section>' +
|
|
20543
20914
|
'<section class="dsh-card" id="dsh-unknown-keys-card"><div class="dsh-card-title">' + esc(t('plugins.dshUnknownKeys')) + '</div>' + dshListMarkup(dsh.unknownKeys) + '</section></div>';
|
|
20544
20915
|
html += '<section class="plugin-section" id="dsh-config-files"><div class="plugin-section-head"><div class="plugin-section-title">' + esc(t('plugins.dshConfigFiles')) + '</div><span class="plugin-count-badge">' + configFiles.length + '</span></div>' + dshListMarkup(configFiles) + '</section>';
|
|
@@ -21030,10 +21401,18 @@ window.removeSkillFromUi = function(name) {
|
|
|
21030
21401
|
});
|
|
21031
21402
|
};
|
|
21032
21403
|
|
|
21404
|
+
window.refreshGithubOverview = function() {
|
|
21405
|
+
state.githubOverviewHash = '';
|
|
21406
|
+
window.loadGithubOverview('', { force: true });
|
|
21407
|
+
};
|
|
21408
|
+
|
|
21033
21409
|
window.renderGithubCliPanel = function() {
|
|
21034
21410
|
var panel = document.getElementById('plugin-panel');
|
|
21035
21411
|
if (!panel) return;
|
|
21036
|
-
panel.innerHTML = '<div
|
|
21412
|
+
panel.innerHTML = '<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;">' +
|
|
21413
|
+
'<div style="flex:1;font-size:13px;font-weight:700;color:var(--text);">' + esc(t('plugins.github')) + '</div>' +
|
|
21414
|
+
'<button type="button" class="sec-btn" onclick="window.refreshGithubOverview()">' + iconSvg('refresh-cw', t('plugins.refreshGh'), 'tiny') + ' ' + esc(t('plugins.refreshGh')) + '</button></div>' +
|
|
21415
|
+
'<div id="gh-overview" class="settings-card" style="min-height:220px;padding:14px;"></div>';
|
|
21037
21416
|
if (state.githubOverviewData) window.renderGithubOverview(state.githubOverviewData);
|
|
21038
21417
|
else document.getElementById('gh-overview').innerHTML = '<div class="settings-empty">' + esc(t('plugins.runningGh')) + '...</div>';
|
|
21039
21418
|
window.loadGithubOverview('', { initial: !state.githubOverviewLoaded });
|
|
@@ -21043,7 +21422,10 @@ window.renderGithubOverview = function(data) {
|
|
|
21043
21422
|
var out = document.getElementById('gh-overview');
|
|
21044
21423
|
if (!out) return;
|
|
21045
21424
|
if (!data || !data.ok) {
|
|
21046
|
-
out.innerHTML = '<div class="settings-empty">' + esc(data && data.error ? data.error : t('plugins.ghUnavailable')) + '</div>'
|
|
21425
|
+
out.innerHTML = '<div class="settings-empty">' + esc(data && data.error ? data.error : t('plugins.ghUnavailable')) + '</div>' +
|
|
21426
|
+
'<div style="display:flex;gap:8px;justify-content:center;margin-top:12px;">' +
|
|
21427
|
+
'<button type="button" class="sec-btn primary" onclick="window.githubCopilotLogin()">' + esc(t('plugins.connectGh')) + '</button>' +
|
|
21428
|
+
'<button type="button" class="sec-btn" onclick="window.refreshGithubOverview()">' + esc(t('plugins.refreshGh')) + '</button></div>';
|
|
21047
21429
|
return;
|
|
21048
21430
|
}
|
|
21049
21431
|
var account = data.account || {};
|
|
@@ -21089,6 +21471,10 @@ window.githubOverviewSignature = function(data) {
|
|
|
21089
21471
|
|
|
21090
21472
|
window.loadGithubOverview = function(repo, options) {
|
|
21091
21473
|
options = options || {};
|
|
21474
|
+
if (options.force) {
|
|
21475
|
+
state.githubOverviewHash = '';
|
|
21476
|
+
state.githubOverviewLoaded = false;
|
|
21477
|
+
}
|
|
21092
21478
|
var out = document.getElementById('gh-overview');
|
|
21093
21479
|
repo = String(repo || '').trim();
|
|
21094
21480
|
if (state.githubOverviewLoading) {
|
|
@@ -21871,6 +22257,47 @@ function guiHasSwitchableBranch() {
|
|
|
21871
22257
|
return branches.length > 1;
|
|
21872
22258
|
}
|
|
21873
22259
|
|
|
22260
|
+
window.showMobilePairing = function() {
|
|
22261
|
+
if (!api.mobilePairingQr) {
|
|
22262
|
+
showUiNotice('Mobile pairing API unavailable', 'error', 'mobile-pairing');
|
|
22263
|
+
return;
|
|
22264
|
+
}
|
|
22265
|
+
window.openSubWin(t('mobile.pair'), '<div style="text-align:center;color:var(--text-dim);">' + esc(t('common.loading')) + '</div>');
|
|
22266
|
+
api.mobilePairingQr().then(function(p) {
|
|
22267
|
+
if (!p || !p.ok) throw new Error((p && p.error) || 'Pairing failed');
|
|
22268
|
+
var expiresLabel = p.expiresAt ? Math.max(0, Math.round((p.expiresAt - Date.now()) / 1000)) + 's' : '';
|
|
22269
|
+
var html = '<div style="display:flex;flex-direction:column;align-items:center;gap:12px;padding:4px 2px;">' +
|
|
22270
|
+
'<img src="' + escAttr(p.dataUrl) + '" alt="Pairing QR" style="width:min(420px,100%);max-width:100%;border-radius:12px;background:#fff;padding:10px;">' +
|
|
22271
|
+
'<div style="font-size:12px;color:var(--text);word-break:break-all;text-align:center;">' + esc(p.url) + '</div>' +
|
|
22272
|
+
'<div style="font-size:11px;color:var(--text-dim);">' + esc(t('mobile.pairTokenFile')) + ': ' + esc(p.tokenFile) + '</div>' +
|
|
22273
|
+
'<div style="font-size:11px;color:var(--text-dim);">Tailscale: ' + esc(p.tailscaleIpv4 || '-') + '</div>' +
|
|
22274
|
+
(expiresLabel ? '<div style="font-size:11px;color:var(--text-dim);">' + esc('窗口期: ' + expiresLabel) + '</div>' : '') +
|
|
22275
|
+
'<div style="font-size:11px;color:var(--text-dim);text-align:center;max-width:420px;">' + esc(t('mobile.pairDesc')) + '</div>' +
|
|
22276
|
+
'</div>';
|
|
22277
|
+
window.openSubWin(t('mobile.pair'), html);
|
|
22278
|
+
// 连接成功后自动关闭二维码窗口
|
|
22279
|
+
if (api.mobilePairingStatus) {
|
|
22280
|
+
var poll = setInterval(function() {
|
|
22281
|
+
api.mobilePairingStatus().then(function(s) {
|
|
22282
|
+
var st = s && s.status;
|
|
22283
|
+
if (!st) return;
|
|
22284
|
+
if (st.confirmed) {
|
|
22285
|
+
clearInterval(poll);
|
|
22286
|
+
window.closeSubWin();
|
|
22287
|
+
showUiNotice('Mobile device connected', 'success', 'mobile-pairing-done');
|
|
22288
|
+
} else if (st.expired || !st.active) {
|
|
22289
|
+
clearInterval(poll);
|
|
22290
|
+
window.closeSubWin();
|
|
22291
|
+
showUiNotice('Pairing window expired', 'error', 'mobile-pairing-expired');
|
|
22292
|
+
}
|
|
22293
|
+
}).catch(function() {});
|
|
22294
|
+
}, 1000);
|
|
22295
|
+
}
|
|
22296
|
+
}).catch(function(err) {
|
|
22297
|
+
showUiNotice(err.message || String(err), 'error', 'mobile-pairing');
|
|
22298
|
+
});
|
|
22299
|
+
};
|
|
22300
|
+
|
|
21874
22301
|
function guiToggleTheme() {
|
|
21875
22302
|
var current = state.theme === 'light' ? 'light' : 'dark';
|
|
21876
22303
|
window.setTheme(current === 'light' ? 'dark' : 'light');
|
|
@@ -21893,6 +22320,7 @@ var NEWMARK_GUI_COMMANDS = [
|
|
|
21893
22320
|
guiCommand('workspace.manager', 'workspace.manager', 'workspace', { bindings:[{ keys:'Mod+K W', scope:'whenNotEditing' }], run:function(){ window.openWorkspaceManager(); } }),
|
|
21894
22321
|
guiCommand('workspace.new', 'workspace.new', 'workspace', { run:function(){ window.showNewWorkspaceDialog(); } }),
|
|
21895
22322
|
guiCommand('workspace.settings', 'workspace.settingsTitle', 'workspace', { run:function(){ window.openWsSettings(); }, available:function(){ return !!state.currentWorkspaceId; } }),
|
|
22323
|
+
guiCommand('mobile.pair', 'mobile.pair', 'general', { run:function(){ window.showMobilePairing(); } }),
|
|
21896
22324
|
|
|
21897
22325
|
guiCommand('view.plugins', 'plugins.title', 'navigation', { bindings:[{ keys:'Mod+K P', scope:'whenNotEditing' }], run:function(){ window.showPluginList(); } }),
|
|
21898
22326
|
guiCommand('view.plugins.mcp', 'plugins.mcp', 'navigation', { run:function(){ window.showPluginList('mcp'); } }),
|
|
@@ -22601,6 +23029,7 @@ function schedulePostStartupUiRendering() {
|
|
|
22601
23029
|
if (s.agentBackend) state.agentBackend = s.agentBackend;
|
|
22602
23030
|
if (s.configuredAgentBackend) state.configuredAgentBackend = s.configuredAgentBackend;
|
|
22603
23031
|
if (s.agentBackendRestartRequired !== undefined) state.agentBackendRestartRequired = !!s.agentBackendRestartRequired;
|
|
23032
|
+
if (s.remoteTouchEnabled !== undefined) state.remoteTouchEnabled = !!s.remoteTouchEnabled;
|
|
22604
23033
|
if (s.wslAvailable !== undefined) state.wslAvailable = !!s.wslAvailable;
|
|
22605
23034
|
if (Array.isArray(s.wslDistros)) state.wslDistros = s.wslDistros;
|
|
22606
23035
|
if (s.conversationId) state.activeBackendConversationId = s.conversationId;
|