newmark-agent 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-commands.d.ts +1 -1
- package/dist/cli-commands.js +89 -7
- package/dist/cli-discovery.js +8 -0
- package/dist/conversation-utility-host.bundle.cjs +860 -688
- package/dist/core/agent.d.ts +19 -0
- package/dist/core/agent.js +72 -8
- 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 +265 -0
- package/dist/core/mobilePairing.d.ts +46 -0
- package/dist/core/mobilePairing.js +207 -0
- package/dist/core/toolPolicy.js +28 -13
- package/dist/core/workspace.d.ts +6 -0
- package/dist/core/workspace.js +14 -0
- package/dist/main.js +49 -0
- package/dist/preload.js +5 -0
- package/dist/server.js +195 -3
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.js +143 -17
- 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 +455 -13
- package/dist/ui/lucide-sprite.svg +10 -0
- package/dist/wsl-agent-host.bundle.cjs +860 -688
- package/package.json +15 -8
package/dist/ui/index.html
CHANGED
|
@@ -1115,6 +1115,74 @@ button.left-ws-item {
|
|
|
1115
1115
|
border-color: var(--accent);
|
|
1116
1116
|
}
|
|
1117
1117
|
|
|
1118
|
+
.conv-more-btn {
|
|
1119
|
+
width: 20px;
|
|
1120
|
+
height: 20px;
|
|
1121
|
+
margin-left: auto;
|
|
1122
|
+
border: 0;
|
|
1123
|
+
border-radius: var(--radius-sm);
|
|
1124
|
+
background: transparent;
|
|
1125
|
+
color: var(--text-dim);
|
|
1126
|
+
cursor: pointer;
|
|
1127
|
+
display: flex;
|
|
1128
|
+
align-items: center;
|
|
1129
|
+
justify-content: center;
|
|
1130
|
+
transition: background var(--duration-fast) var(--ease-out-expo), color var(--duration-fast) var(--ease-out-expo);
|
|
1131
|
+
flex-shrink: 0;
|
|
1132
|
+
}
|
|
1133
|
+
.conv-more-btn:hover,
|
|
1134
|
+
.conv-more-btn[aria-expanded="true"] {
|
|
1135
|
+
background: var(--control-hover-bg);
|
|
1136
|
+
color: var(--text-bright);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
.conv-action-menu {
|
|
1140
|
+
position: fixed;
|
|
1141
|
+
inset: auto;
|
|
1142
|
+
margin: 0;
|
|
1143
|
+
z-index: 560;
|
|
1144
|
+
display: none;
|
|
1145
|
+
min-width: 168px;
|
|
1146
|
+
max-height: min(56vh, 320px);
|
|
1147
|
+
overflow: auto;
|
|
1148
|
+
padding: 6px;
|
|
1149
|
+
border: 1px solid var(--glass-border-2);
|
|
1150
|
+
border-radius: var(--radius-lg);
|
|
1151
|
+
background: var(--modal-surface);
|
|
1152
|
+
box-shadow: var(--shadow-lg);
|
|
1153
|
+
backdrop-filter: blur(var(--glass-blur-3)) saturate(1.08);
|
|
1154
|
+
}
|
|
1155
|
+
.conv-action-menu:popover-open { display: block; animation: model-menu-in 150ms var(--ease-out-expo); }
|
|
1156
|
+
|
|
1157
|
+
.conv-action-menu-item {
|
|
1158
|
+
width: 100%;
|
|
1159
|
+
min-height: 32px;
|
|
1160
|
+
display: flex;
|
|
1161
|
+
align-items: center;
|
|
1162
|
+
gap: 8px;
|
|
1163
|
+
padding: 6px 10px;
|
|
1164
|
+
border: 0;
|
|
1165
|
+
border-radius: var(--radius-md);
|
|
1166
|
+
background: transparent;
|
|
1167
|
+
color: var(--text);
|
|
1168
|
+
text-align: left;
|
|
1169
|
+
white-space: nowrap;
|
|
1170
|
+
font: 12px var(--font-ui);
|
|
1171
|
+
cursor: pointer;
|
|
1172
|
+
}
|
|
1173
|
+
.conv-action-menu-item:hover,
|
|
1174
|
+
.conv-action-menu-item:focus-visible {
|
|
1175
|
+
background: var(--control-hover-bg);
|
|
1176
|
+
color: var(--text-bright);
|
|
1177
|
+
outline: none;
|
|
1178
|
+
}
|
|
1179
|
+
.conv-action-menu-item:disabled { opacity: 0.55; cursor: default; }
|
|
1180
|
+
.conv-action-menu-item .nm-icon { color: var(--text-dim); flex-shrink: 0; }
|
|
1181
|
+
.conv-action-menu-item:hover .nm-icon,
|
|
1182
|
+
.conv-action-menu-item:focus-visible .nm-icon { color: var(--text-bright); }
|
|
1183
|
+
.conv-action-menu-item.active { color: var(--text-accent); }
|
|
1184
|
+
.conv-action-menu-item.active .nm-icon { color: var(--text-accent); }
|
|
1185
|
+
|
|
1118
1186
|
/* ============================================================
|
|
1119
1187
|
RESIZE HANDLES
|
|
1120
1188
|
============================================================ */
|
|
@@ -2715,15 +2783,18 @@ button.todo-item { background: transparent; }
|
|
|
2715
2783
|
}
|
|
2716
2784
|
|
|
2717
2785
|
.option-btn {
|
|
2718
|
-
|
|
2786
|
+
display: block;
|
|
2787
|
+
width: 100%;
|
|
2788
|
+
padding: 6px 14px;
|
|
2719
2789
|
border: 1px solid var(--border);
|
|
2720
2790
|
border-radius: var(--radius-md);
|
|
2721
2791
|
background: var(--glass-bg-1);
|
|
2722
2792
|
color: var(--text);
|
|
2723
2793
|
font-size: 12px;
|
|
2724
2794
|
font-family: var(--font-ui);
|
|
2795
|
+
text-align: left;
|
|
2725
2796
|
cursor: pointer;
|
|
2726
|
-
margin:
|
|
2797
|
+
margin: 3px 0;
|
|
2727
2798
|
transition: background var(--duration-fast) var(--ease-out-expo), border-color var(--duration-fast) var(--ease-out-expo);
|
|
2728
2799
|
}
|
|
2729
2800
|
|
|
@@ -2739,6 +2810,45 @@ button.todo-item { background: transparent; }
|
|
|
2739
2810
|
font-size: 11px;
|
|
2740
2811
|
}
|
|
2741
2812
|
|
|
2813
|
+
.option-manual {
|
|
2814
|
+
display: flex;
|
|
2815
|
+
align-items: center;
|
|
2816
|
+
gap: 6px;
|
|
2817
|
+
margin-top: 8px;
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
.option-manual-input {
|
|
2821
|
+
flex: 1;
|
|
2822
|
+
min-width: 0;
|
|
2823
|
+
height: 30px;
|
|
2824
|
+
padding: 3px 9px;
|
|
2825
|
+
border: 1px solid var(--border);
|
|
2826
|
+
border-radius: var(--radius-md);
|
|
2827
|
+
background: var(--glass-bg-1);
|
|
2828
|
+
color: var(--text);
|
|
2829
|
+
font: 12px var(--font-ui);
|
|
2830
|
+
outline: none;
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2833
|
+
.option-manual-input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-glow); }
|
|
2834
|
+
.option-manual-input:disabled { opacity: .55; cursor: default; }
|
|
2835
|
+
|
|
2836
|
+
.option-manual-submit {
|
|
2837
|
+
flex-shrink: 0;
|
|
2838
|
+
height: 30px;
|
|
2839
|
+
padding: 0 12px;
|
|
2840
|
+
border: 1px solid var(--accent);
|
|
2841
|
+
border-radius: var(--radius-md);
|
|
2842
|
+
background: rgba(91,120,255,0.14);
|
|
2843
|
+
color: var(--text-bright);
|
|
2844
|
+
font: 12px var(--font-ui);
|
|
2845
|
+
cursor: pointer;
|
|
2846
|
+
transition: background var(--duration-fast) var(--ease-out-expo);
|
|
2847
|
+
}
|
|
2848
|
+
|
|
2849
|
+
.option-manual-submit:hover { background: rgba(91,120,255,0.24); }
|
|
2850
|
+
.option-manual-submit:disabled { opacity: .55; cursor: default; }
|
|
2851
|
+
|
|
2742
2852
|
/* ============================================================
|
|
2743
2853
|
INPUT STACK
|
|
2744
2854
|
============================================================ */
|
|
@@ -4098,6 +4208,21 @@ textarea.mcp-input { min-height:76px; resize:vertical; font-family:var(--font-mo
|
|
|
4098
4208
|
transition: none !important;
|
|
4099
4209
|
}
|
|
4100
4210
|
|
|
4211
|
+
.setting-subsection {
|
|
4212
|
+
margin-top: 14px;
|
|
4213
|
+
padding: 12px 14px;
|
|
4214
|
+
border: 1px solid var(--glass-border-1);
|
|
4215
|
+
border-radius: var(--radius-md);
|
|
4216
|
+
background: var(--glass-bg-1);
|
|
4217
|
+
}
|
|
4218
|
+
|
|
4219
|
+
.setting-subsection-title {
|
|
4220
|
+
margin-bottom: 6px;
|
|
4221
|
+
color: var(--text-bright);
|
|
4222
|
+
font-size: 12px;
|
|
4223
|
+
font-weight: 650;
|
|
4224
|
+
}
|
|
4225
|
+
|
|
4101
4226
|
.setting-row {
|
|
4102
4227
|
display: flex;
|
|
4103
4228
|
align-items: center;
|
|
@@ -5340,6 +5465,11 @@ html.newmark-memory-overview-viewer body {
|
|
|
5340
5465
|
<path d="m15 10 5 5-5 5" />
|
|
5341
5466
|
<path d="M4 4v7a4 4 0 0 0 4 4h12" />
|
|
5342
5467
|
</symbol>
|
|
5468
|
+
<symbol id="ellipsis" viewBox="0 0 24 24">
|
|
5469
|
+
<circle cx="12" cy="12" r="1" />
|
|
5470
|
+
<circle cx="19" cy="12" r="1" />
|
|
5471
|
+
<circle cx="5" cy="12" r="1" />
|
|
5472
|
+
</symbol>
|
|
5343
5473
|
<symbol id="file-diff" viewBox="0 0 24 24">
|
|
5344
5474
|
<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
5475
|
<path d="M9 10h6" />
|
|
@@ -5448,6 +5578,11 @@ html.newmark-memory-overview-viewer body {
|
|
|
5448
5578
|
<path d="M3 16v3a2 2 0 0 0 2 2h3" />
|
|
5449
5579
|
<path d="M16 21h3a2 2 0 0 0 2-2v-3" />
|
|
5450
5580
|
</symbol>
|
|
5581
|
+
<symbol id="menu" viewBox="0 0 24 24">
|
|
5582
|
+
<path d="M4 5h16" />
|
|
5583
|
+
<path d="M4 12h16" />
|
|
5584
|
+
<path d="M4 19h16" />
|
|
5585
|
+
</symbol>
|
|
5451
5586
|
<symbol id="merge" viewBox="0 0 24 24">
|
|
5452
5587
|
<path d="m8 6 4-4 4 4" />
|
|
5453
5588
|
<path d="M12 2v10.3a4 4 0 0 1-1.172 2.872L4 22" />
|
|
@@ -5841,6 +5976,7 @@ html.newmark-memory-overview-viewer body {
|
|
|
5841
5976
|
<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
5977
|
<div class="model-select-menu" id="model-select-menu" role="listbox" aria-label="Model" popover="manual"></div>
|
|
5843
5978
|
</div>
|
|
5979
|
+
<div class="conv-action-menu" id="conversation-action-menu" role="menu" aria-label="Conversation actions" popover="manual"></div>
|
|
5844
5980
|
<div class="context-token-wrap">
|
|
5845
5981
|
<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
5982
|
<div id="context-token-tooltip"></div>
|
|
@@ -6184,6 +6320,7 @@ var state = {
|
|
|
6184
6320
|
agentBackend: { enabled: false, connected: true, distro: '', pid: 0, error: '' },
|
|
6185
6321
|
configuredAgentBackend: 'windows',
|
|
6186
6322
|
agentBackendRestartRequired: false,
|
|
6323
|
+
remoteTouchEnabled: true,
|
|
6187
6324
|
wslAvailable: false,
|
|
6188
6325
|
wslDistros: [],
|
|
6189
6326
|
defaultTerminalShell: 'powershell',
|
|
@@ -6364,6 +6501,11 @@ var NEWMARK_I18N = {
|
|
|
6364
6501
|
'settings.configReloaded': 'config.json refreshed',
|
|
6365
6502
|
'settings.runInWsl': 'Agent runtime environment',
|
|
6366
6503
|
'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.',
|
|
6504
|
+
'settings.remoteTouch': 'Mobile remote-touch',
|
|
6505
|
+
'settings.remoteTouchDesc': 'Allow the mobile app to reach this Newmark instance over Tailscale. Turn off to disable remote pairing and sync APIs immediately.',
|
|
6506
|
+
'settings.remoteBehavior': 'Remote behavior',
|
|
6507
|
+
'settings.remoteConnect': 'Start connection',
|
|
6508
|
+
'settings.remoteConnectDesc': 'Show the pairing QR code for the Newmark mobile app.',
|
|
6367
6509
|
'settings.wslDistro': 'WSL distribution',
|
|
6368
6510
|
'settings.wslConnected': 'WSL backend connected',
|
|
6369
6511
|
'settings.wslDisconnected': 'WSL backend unavailable',
|
|
@@ -6632,6 +6774,8 @@ var NEWMARK_I18N = {
|
|
|
6632
6774
|
'plugins.management': 'Skills Management',
|
|
6633
6775
|
'plugins.market': 'Skills Market',
|
|
6634
6776
|
'plugins.github': 'GitHub CLI',
|
|
6777
|
+
'plugins.refreshGh': 'Refresh',
|
|
6778
|
+
'plugins.connectGh': 'Connect GitHub',
|
|
6635
6779
|
'plugins.noInstalled': 'No installed skills.',
|
|
6636
6780
|
'plugins.projectSkill': 'project skill',
|
|
6637
6781
|
'plugins.discovering': 'Discovering local and portable skills...',
|
|
@@ -6724,6 +6868,14 @@ var NEWMARK_I18N = {
|
|
|
6724
6868
|
'plugins.retry': 'Retry',
|
|
6725
6869
|
'plugins.dshTitle': 'DSH Plugin compatibility',
|
|
6726
6870
|
'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.',
|
|
6871
|
+
'plugins.dshInstall': 'Install into Newmark',
|
|
6872
|
+
'plugins.dshInstalled': 'Installed',
|
|
6873
|
+
'plugins.dshUninstall': 'Uninstall',
|
|
6874
|
+
'plugins.dshEnable': 'Enable',
|
|
6875
|
+
'plugins.dshDisable': 'Disable',
|
|
6876
|
+
'plugins.dshInstallOk': 'DSH plugin installed into local .Newmark.',
|
|
6877
|
+
'plugins.dshUninstallOk': 'DSH plugin removed.',
|
|
6878
|
+
'plugins.dshSetOk': 'DSH plugin setting saved.',
|
|
6727
6879
|
'plugins.dshPreview': 'Developer preview',
|
|
6728
6880
|
'plugins.dshRescan': 'Rescan',
|
|
6729
6881
|
'plugins.dshScanning': 'Scanning DSH compatibility...',
|
|
@@ -6875,6 +7027,11 @@ var NEWMARK_I18N = {
|
|
|
6875
7027
|
'status.pendingOptions': 'Pending options',
|
|
6876
7028
|
'status.noPendingOptions': 'No option question is waiting for user input.',
|
|
6877
7029
|
'status.question': 'Question',
|
|
7030
|
+
'option.manualPlaceholder': 'Or type your own answer...',
|
|
7031
|
+
'option.manualSubmit': 'Submit',
|
|
7032
|
+
'mobile.pair': 'Pair mobile device',
|
|
7033
|
+
'mobile.pairDesc': 'Scan this QR code with the Newmark mobile app over Tailscale. The pairing token is saved after the first bind.',
|
|
7034
|
+
'mobile.pairTokenFile': 'Token file',
|
|
6878
7035
|
'subagent.empty': 'No retained subagent records',
|
|
6879
7036
|
'subagent.openHistory': 'Open subagent history',
|
|
6880
7037
|
'subagent.historyTitle': 'Subagent history',
|
|
@@ -6885,6 +7042,7 @@ var NEWMARK_I18N = {
|
|
|
6885
7042
|
'subagent.noMessages': 'No messages recorded.',
|
|
6886
7043
|
'subagent.unread': '{count} unread',
|
|
6887
7044
|
'conversation.archive': 'Archive',
|
|
7045
|
+
'conversation.more': 'More conversation actions',
|
|
6888
7046
|
'conversation.rename': 'Rename conversation',
|
|
6889
7047
|
'conversation.renameFailed': 'Could not rename the conversation.',
|
|
6890
7048
|
'conversation.reorderFailed': 'Could not save the conversation order.',
|
|
@@ -7070,6 +7228,11 @@ var NEWMARK_I18N = {
|
|
|
7070
7228
|
'settings.configReloaded': '已刷新 config.json',
|
|
7071
7229
|
'settings.runInWsl': 'Agent 运行环境',
|
|
7072
7230
|
'settings.runInWslDesc': 'Windows UI 与桌面原生工具保留在本机,持续 Agent 内核、模型请求、Shell 和文件工具运行在 WSL。',
|
|
7231
|
+
'settings.remoteTouch': '移动端远程触及',
|
|
7232
|
+
'settings.remoteTouchDesc': '允许移动端通过 Tailscale 连接本机 Newmark。关闭后立即禁用远程配对与同步 API。',
|
|
7233
|
+
'settings.remoteBehavior': '远程行为',
|
|
7234
|
+
'settings.remoteConnect': '发起连接',
|
|
7235
|
+
'settings.remoteConnectDesc': '显示 Newmark 移动端配对二维码。',
|
|
7073
7236
|
'settings.wslDistro': 'WSL 发行版',
|
|
7074
7237
|
'settings.wslConnected': 'WSL 后端已连接',
|
|
7075
7238
|
'settings.wslDisconnected': 'WSL 后端不可用',
|
|
@@ -7338,6 +7501,8 @@ var NEWMARK_I18N = {
|
|
|
7338
7501
|
'plugins.management': 'Skills 管理',
|
|
7339
7502
|
'plugins.market': 'Skills Market',
|
|
7340
7503
|
'plugins.github': 'GitHub CLI',
|
|
7504
|
+
'plugins.refreshGh': '刷新',
|
|
7505
|
+
'plugins.connectGh': '连接 GitHub',
|
|
7341
7506
|
'plugins.noInstalled': '暂无已安装 skill。',
|
|
7342
7507
|
'plugins.projectSkill': '项目 skill',
|
|
7343
7508
|
'plugins.discovering': '正在发现本地和便携 skill...',
|
|
@@ -7430,6 +7595,14 @@ var NEWMARK_I18N = {
|
|
|
7430
7595
|
'plugins.retry': '重试',
|
|
7431
7596
|
'plugins.dshTitle': 'DSH Plugin 兼容',
|
|
7432
7597
|
'plugins.dshHelp': '开发者预览:检查本地官方 DSH CLI 与包配置。发现过程严格只读,绝不会安装、执行、更新或改写 DSH。',
|
|
7598
|
+
'plugins.dshInstall': '安装到 Newmark',
|
|
7599
|
+
'plugins.dshInstalled': '已安装',
|
|
7600
|
+
'plugins.dshUninstall': '卸载',
|
|
7601
|
+
'plugins.dshEnable': '启用',
|
|
7602
|
+
'plugins.dshDisable': '禁用',
|
|
7603
|
+
'plugins.dshInstallOk': 'DSH 插件已安装到本地 .Newmark。',
|
|
7604
|
+
'plugins.dshUninstallOk': 'DSH 插件已移除。',
|
|
7605
|
+
'plugins.dshSetOk': 'DSH 插件设置已保存。',
|
|
7433
7606
|
'plugins.dshPreview': '开发者预览',
|
|
7434
7607
|
'plugins.dshRescan': '重新扫描',
|
|
7435
7608
|
'plugins.dshScanning': '正在扫描 DSH 兼容信息...',
|
|
@@ -7581,6 +7754,11 @@ var NEWMARK_I18N = {
|
|
|
7581
7754
|
'status.pendingOptions': '待处理选项',
|
|
7582
7755
|
'status.noPendingOptions': '暂无等待用户输入的选项问题。',
|
|
7583
7756
|
'status.question': '问题',
|
|
7757
|
+
'option.manualPlaceholder': '或输入自己的答案...',
|
|
7758
|
+
'option.manualSubmit': '提交',
|
|
7759
|
+
'mobile.pair': '配对移动设备',
|
|
7760
|
+
'mobile.pairDesc': '使用 Newmark 移动端通过 Tailscale 扫描二维码。首次绑定后保存配对令牌。',
|
|
7761
|
+
'mobile.pairTokenFile': '令牌文件',
|
|
7584
7762
|
'subagent.empty': '暂无保留的 subagent 记录',
|
|
7585
7763
|
'subagent.openHistory': '打开 subagent 历史',
|
|
7586
7764
|
'subagent.historyTitle': 'Subagent 历史',
|
|
@@ -7591,6 +7769,7 @@ var NEWMARK_I18N = {
|
|
|
7591
7769
|
'subagent.noMessages': '没有记录消息。',
|
|
7592
7770
|
'subagent.unread': '{count} 条未读',
|
|
7593
7771
|
'conversation.archive': '归档',
|
|
7772
|
+
'conversation.more': '更多对话操作',
|
|
7594
7773
|
'conversation.rename': '编辑对话名称',
|
|
7595
7774
|
'conversation.renameFailed': '无法保存对话名称。',
|
|
7596
7775
|
'conversation.reorderFailed': '无法保存对话顺序。',
|
|
@@ -11521,6 +11700,10 @@ function addOptionBlock(question, options, questionKey) {
|
|
|
11521
11700
|
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
11701
|
esc(label) + (desc ? '<span class="option-desc">' + esc(desc) + '</span>' : '') + '</button>';
|
|
11523
11702
|
}
|
|
11703
|
+
html += '<div class="option-manual">' +
|
|
11704
|
+
'<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);}" />' +
|
|
11705
|
+
'<button class="option-manual-submit" onclick="window.optionManualSubmitted(this)">' + esc(t('option.manualSubmit')) + '</button>' +
|
|
11706
|
+
'</div>';
|
|
11524
11707
|
html += '</div>';
|
|
11525
11708
|
div.innerHTML = html;
|
|
11526
11709
|
els['chat-area'].appendChild(div);
|
|
@@ -11637,6 +11820,20 @@ window.optionSelected = function(questionKey, opt, button) {
|
|
|
11637
11820
|
window.sendMessage();
|
|
11638
11821
|
};
|
|
11639
11822
|
|
|
11823
|
+
window.optionManualSubmitted = function(element) {
|
|
11824
|
+
var manual = element && element.closest ? element.closest('.option-manual') : null;
|
|
11825
|
+
if (!manual) return;
|
|
11826
|
+
var input = manual.querySelector('.option-manual-input');
|
|
11827
|
+
if (!input) return;
|
|
11828
|
+
var value = String(input.value || '').trim();
|
|
11829
|
+
if (!value) { input.focus(); return; }
|
|
11830
|
+
var key = input.getAttribute('data-option-question-key') || '';
|
|
11831
|
+
var decoded;
|
|
11832
|
+
try { decoded = decodeURIComponent(key); } catch (e) { decoded = key; }
|
|
11833
|
+
window.optionSelected(decoded, value, input);
|
|
11834
|
+
Array.from(manual.querySelectorAll('input, button')).forEach(function(control) { control.disabled = true; });
|
|
11835
|
+
};
|
|
11836
|
+
|
|
11640
11837
|
// === Working State ===
|
|
11641
11838
|
function setWorking(working) {
|
|
11642
11839
|
state.isWorking = working;
|
|
@@ -12230,6 +12427,119 @@ window.selectModelFromMenu = function(value) {
|
|
|
12230
12427
|
window.closeModelSelectMenu({ focus: true });
|
|
12231
12428
|
};
|
|
12232
12429
|
|
|
12430
|
+
window.closeConversationActionMenu = function(options) {
|
|
12431
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12432
|
+
var anchor = state.conversationActionAnchor;
|
|
12433
|
+
if (menu && typeof menu.hidePopover === 'function' && menu.matches(':popover-open')) menu.hidePopover();
|
|
12434
|
+
document.querySelectorAll('.conv-more-btn[aria-expanded="true"]').forEach(function(item) { item.setAttribute('aria-expanded', 'false'); });
|
|
12435
|
+
state.conversationActionAnchor = null;
|
|
12436
|
+
if (options && options.focus && anchor && anchor.focus) anchor.focus();
|
|
12437
|
+
};
|
|
12438
|
+
|
|
12439
|
+
window.positionConversationActionMenu = function(anchor, menu, pos) {
|
|
12440
|
+
if (!menu) return;
|
|
12441
|
+
var width = 168;
|
|
12442
|
+
var margin = 8;
|
|
12443
|
+
menu.style.width = width + 'px';
|
|
12444
|
+
var rect = anchor && anchor.getBoundingClientRect ? anchor.getBoundingClientRect() : null;
|
|
12445
|
+
var desiredHeight = Math.min(320, menu.scrollHeight || menu.offsetHeight || 0);
|
|
12446
|
+
var left, top, below, above, openAbove;
|
|
12447
|
+
if (pos && typeof pos.x === 'number' && typeof pos.y === 'number') {
|
|
12448
|
+
left = Math.max(margin, Math.min(window.innerWidth - width - margin, pos.x));
|
|
12449
|
+
below = Math.max(0, window.innerHeight - pos.y - margin);
|
|
12450
|
+
above = Math.max(0, pos.y - margin);
|
|
12451
|
+
openAbove = below < desiredHeight && above > below;
|
|
12452
|
+
top = openAbove ? Math.max(margin, pos.y - Math.min(desiredHeight, above) - margin) : pos.y + margin;
|
|
12453
|
+
} else if (rect) {
|
|
12454
|
+
left = Math.max(margin, Math.min(window.innerWidth - width - margin, rect.right - width));
|
|
12455
|
+
below = Math.max(0, window.innerHeight - rect.bottom - margin);
|
|
12456
|
+
above = Math.max(0, rect.top - margin);
|
|
12457
|
+
openAbove = below < desiredHeight && above > below;
|
|
12458
|
+
top = openAbove ? Math.max(margin, rect.top - Math.min(desiredHeight, above) - margin) : rect.bottom + margin;
|
|
12459
|
+
} else {
|
|
12460
|
+
left = Math.max(margin, Math.round((window.innerWidth - width) / 2));
|
|
12461
|
+
top = Math.round(window.innerHeight / 3);
|
|
12462
|
+
}
|
|
12463
|
+
menu.style.left = left + 'px';
|
|
12464
|
+
menu.style.top = top + 'px';
|
|
12465
|
+
};
|
|
12466
|
+
|
|
12467
|
+
window.openConversationActionMenu = function(anchor, conversationId, pos) {
|
|
12468
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12469
|
+
if (!menu) return;
|
|
12470
|
+
var convs = currentWorkspaceConversations();
|
|
12471
|
+
var idx = convs.findIndex(function(item) { return String(item && item.id || 'default') === String(conversationId || ''); });
|
|
12472
|
+
var conv = convs[idx];
|
|
12473
|
+
if (!conv) return;
|
|
12474
|
+
window.closeModelSelectMenu();
|
|
12475
|
+
document.querySelectorAll('.newmark-select-shell.open').forEach(function(item) { window.closeNewmarkSelect(item); });
|
|
12476
|
+
var pendingKey = currentWorkspaceKey() + '::' + String(conv.id);
|
|
12477
|
+
var pending = !!state.conversationArchivePending[pendingKey];
|
|
12478
|
+
var pinLabel = conv.pinned ? t('conversation.unpin') : t('conversation.pin');
|
|
12479
|
+
var archiveHtml = pending
|
|
12480
|
+
? '<button type="button" class="conv-action-menu-item" disabled><span class="conv-archive-spinner"></span><span>' + esc(t('archive.archiving')) + '</span></button>'
|
|
12481
|
+
: '<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>';
|
|
12482
|
+
menu.innerHTML =
|
|
12483
|
+
'<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>' +
|
|
12484
|
+
archiveHtml +
|
|
12485
|
+
'<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>';
|
|
12486
|
+
menu.setAttribute('data-index', String(idx));
|
|
12487
|
+
var moreBtn = anchor && anchor.classList && anchor.classList.contains('conv-more-btn') ? anchor : (anchor && anchor.querySelector ? anchor.querySelector('.conv-more-btn') : null);
|
|
12488
|
+
document.querySelectorAll('.conv-more-btn[aria-expanded="true"]').forEach(function(item) { item.setAttribute('aria-expanded', 'false'); });
|
|
12489
|
+
if (moreBtn) moreBtn.setAttribute('aria-expanded', 'true');
|
|
12490
|
+
state.conversationActionAnchor = anchor || moreBtn || null;
|
|
12491
|
+
if (typeof menu.showPopover === 'function' && !menu.matches(':popover-open')) menu.showPopover();
|
|
12492
|
+
requestAnimationFrame(function() {
|
|
12493
|
+
window.positionConversationActionMenu(state.conversationActionAnchor || moreBtn, menu, pos);
|
|
12494
|
+
var item = menu.querySelector('.conv-action-menu-item:not(:disabled)');
|
|
12495
|
+
if (item) item.focus({ preventScroll: true });
|
|
12496
|
+
});
|
|
12497
|
+
};
|
|
12498
|
+
|
|
12499
|
+
window.runConversationAction = function(button, action) {
|
|
12500
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12501
|
+
var idx = Number(menu && menu.getAttribute('data-index') || '-1');
|
|
12502
|
+
window.closeConversationActionMenu();
|
|
12503
|
+
var convs = currentWorkspaceConversations();
|
|
12504
|
+
var conv = convs[idx];
|
|
12505
|
+
if (!conv) return;
|
|
12506
|
+
if (action === 'edit') window.editConversationName(idx);
|
|
12507
|
+
else if (action === 'archive') window.archiveConv(String(conv.id || 'default'));
|
|
12508
|
+
else if (action === 'pin') window.toggleConversationPinned(idx);
|
|
12509
|
+
};
|
|
12510
|
+
|
|
12511
|
+
document.addEventListener('pointerdown', function(event) {
|
|
12512
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12513
|
+
if (!menu || !menu.matches || !menu.matches(':popover-open')) return;
|
|
12514
|
+
var anchor = state.conversationActionAnchor;
|
|
12515
|
+
if (anchor && anchor.contains && anchor.contains(event.target)) return;
|
|
12516
|
+
if (menu.contains(event.target)) return;
|
|
12517
|
+
window.closeConversationActionMenu();
|
|
12518
|
+
});
|
|
12519
|
+
|
|
12520
|
+
document.addEventListener('keydown', function(event) {
|
|
12521
|
+
if (event.key === 'Escape') window.closeConversationActionMenu();
|
|
12522
|
+
});
|
|
12523
|
+
|
|
12524
|
+
(function() {
|
|
12525
|
+
var menu = document.getElementById('conversation-action-menu');
|
|
12526
|
+
if (!menu) return;
|
|
12527
|
+
menu.addEventListener('keydown', function(event) {
|
|
12528
|
+
if (event.key === 'Escape') {
|
|
12529
|
+
event.preventDefault();
|
|
12530
|
+
window.closeConversationActionMenu({ focus: true });
|
|
12531
|
+
return;
|
|
12532
|
+
}
|
|
12533
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;
|
|
12534
|
+
event.preventDefault();
|
|
12535
|
+
var items = Array.prototype.slice.call(menu.querySelectorAll('.conv-action-menu-item:not(:disabled)'));
|
|
12536
|
+
if (!items.length) return;
|
|
12537
|
+
var current = items.indexOf(document.activeElement);
|
|
12538
|
+
var next = event.key === 'ArrowDown' ? items[(current + 1) % items.length] : items[(current - 1 + items.length) % items.length];
|
|
12539
|
+
if (next) next.focus();
|
|
12540
|
+
});
|
|
12541
|
+
})();
|
|
12542
|
+
|
|
12233
12543
|
window.handleModelSelectButtonKey = function(event) {
|
|
12234
12544
|
if (!event) return;
|
|
12235
12545
|
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
@@ -15244,7 +15554,20 @@ function renderGeneralSettings() {
|
|
|
15244
15554
|
'<div class="setting-row"><span class="setting-label">' + esc(t('settings.wslDistro')) + '</span>' +
|
|
15245
15555
|
'<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
15556
|
'<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-
|
|
15557
|
+
return wslHtml + '<div class="setting-subsection">' +
|
|
15558
|
+
'<div class="setting-subsection-title">' + esc(t('settings.remoteBehavior')) + '</div>' +
|
|
15559
|
+
'<div class="setting-row">' +
|
|
15560
|
+
'<label class="setting-label" for="remote-touch-enabled">' + esc(t('settings.remoteTouch')) + '</label>' +
|
|
15561
|
+
'<div class="setting-control"><label class="toggle"><input type="checkbox" id="remote-touch-enabled"' + (state.remoteTouchEnabled ? ' checked' : '') + ' onchange="window.setRemoteTouchEnabled(this.checked)"><span class="toggle-track"></span></label>' +
|
|
15562
|
+
'<div class="setting-desc">' + esc(t('settings.remoteTouchDesc')) + '</div></div>' +
|
|
15563
|
+
'</div>' +
|
|
15564
|
+
'<div class="setting-row">' +
|
|
15565
|
+
'<span class="setting-label">' + esc(t('settings.remoteConnect')) + '</span>' +
|
|
15566
|
+
'<div class="setting-control"><button type="button" class="sec-btn primary" onclick="window.showMobilePairing()">' + esc(t('settings.remoteConnect')) + '</button>' +
|
|
15567
|
+
'<div class="setting-desc">' + esc(t('settings.remoteConnectDesc')) + '</div></div>' +
|
|
15568
|
+
'</div>' +
|
|
15569
|
+
'</div>' +
|
|
15570
|
+
'<div class="setting-row">' +
|
|
15248
15571
|
'<span class="setting-label">' + esc(t('settings.configFile')) + '</span>' +
|
|
15249
15572
|
'<div class="setting-control"><div style="display:flex;align-items:center;gap:7px;flex-wrap:wrap;">' +
|
|
15250
15573
|
'<button type="button" class="sec-btn" onclick="window.openGlobalConfigFile()">' + esc(t('settings.openConfig')) + '</button>' +
|
|
@@ -15920,6 +16243,15 @@ window.setAgentBackendMode = async function(mode) {
|
|
|
15920
16243
|
return true;
|
|
15921
16244
|
};
|
|
15922
16245
|
|
|
16246
|
+
window.setRemoteTouchEnabled = async function(value) {
|
|
16247
|
+
var next = !!value;
|
|
16248
|
+
state.remoteTouchEnabled = next;
|
|
16249
|
+
if (api.saveSetting) {
|
|
16250
|
+
try { await api.saveSetting('remote', 'touch_enabled', next); } catch (e) {}
|
|
16251
|
+
}
|
|
16252
|
+
window.settingsTab('general');
|
|
16253
|
+
};
|
|
16254
|
+
|
|
15923
16255
|
window.setAgentWslDistro = async function(value) {
|
|
15924
16256
|
var distro = String(value || '').trim() || 'Ubuntu-24.04';
|
|
15925
16257
|
await api.saveSetting('agent', 'wsl_distro', distro);
|
|
@@ -19058,16 +19390,15 @@ function renderConversations() {
|
|
|
19058
19390
|
? '<span class="conv-runtime-badge ' + escAttr(String(runtimeState.status)) + '">' + esc(String(runtimeState.status)) + '</span>' : '';
|
|
19059
19391
|
var branchCommIcon = conv.branchCommunication
|
|
19060
19392
|
? '<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
19393
|
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>';
|
|
19394
|
+
'<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
19395
|
div.onclick = function(idx) { return function() { window.switchConversation(idx); }; }(i);
|
|
19070
19396
|
div.addEventListener('keydown', window.handleConversationKey);
|
|
19397
|
+
div.addEventListener('contextmenu', function(event) {
|
|
19398
|
+
event.preventDefault();
|
|
19399
|
+
event.stopPropagation();
|
|
19400
|
+
window.openConversationActionMenu(event.currentTarget, this.getAttribute('data-conversation-id') || '', { x: event.clientX, y: event.clientY });
|
|
19401
|
+
});
|
|
19071
19402
|
div.addEventListener('dragstart', function(event) {
|
|
19072
19403
|
this.classList.add('dragging');
|
|
19073
19404
|
if (event.dataTransfer) { event.dataTransfer.effectAllowed = 'move'; event.dataTransfer.setData('text/plain', this.getAttribute('data-conversation-id') || ''); }
|
|
@@ -20481,6 +20812,59 @@ window.openDshOfficial = function(kind) {
|
|
|
20481
20812
|
});
|
|
20482
20813
|
};
|
|
20483
20814
|
|
|
20815
|
+
function renderDshBundlesMarkup(bundles) {
|
|
20816
|
+
var values = dshCollection(bundles);
|
|
20817
|
+
if (!values.length) return '<div class="plugin-empty">' + esc(t('plugins.dshNone')) + '</div>';
|
|
20818
|
+
return '<div class="dsh-list">' + values.map(function(item, index) {
|
|
20819
|
+
var name = String(item.name || item.id || 'dsh-plugin');
|
|
20820
|
+
var manifestPath = String(item.manifestPath || '');
|
|
20821
|
+
var installed = !!item.installed;
|
|
20822
|
+
var enabled = item.enabled !== false;
|
|
20823
|
+
var actionHtml = installed
|
|
20824
|
+
? '<div class="dsh-candidate-actions">' +
|
|
20825
|
+
'<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>' +
|
|
20826
|
+
'<span style="font-size:11px;color:var(--text-dim);">' + esc(t(enabled ? 'plugins.dshEnable' : 'plugins.dshDisable')) + '</span>' +
|
|
20827
|
+
'<button type="button" class="sec-btn" onclick="window.uninstallDshBundle(' + index + ')">' + esc(t('plugins.dshUninstall')) + '</button>' +
|
|
20828
|
+
'<span class="plugin-status-badge">' + esc(t('plugins.dshInstalled')) + '</span></div>'
|
|
20829
|
+
: '<div class="dsh-candidate-actions"><button type="button" class="sec-btn primary" onclick="window.installDshBundle(' + index + ')"' + (manifestPath ? '' : ' disabled') + '>' + esc(t('plugins.dshInstall')) + '</button></div>';
|
|
20830
|
+
return '<div class="dsh-list-item"><strong>' + esc(name) + '</strong>' +
|
|
20831
|
+
'<div class="provider-meta">' + esc(String(item.source || '')) + '</div>' + actionHtml + '</div>';
|
|
20832
|
+
}).join('') + '</div>';
|
|
20833
|
+
}
|
|
20834
|
+
|
|
20835
|
+
window.installDshBundle = function(index) {
|
|
20836
|
+
var bundle = dshCollection(state.dshCompatibility && state.dshCompatibility.bundles)[index];
|
|
20837
|
+
if (!bundle || !bundle.manifestPath) return;
|
|
20838
|
+
if (!api.installDshBundle) { showUiNotice(t('plugins.dshUnavailable'), 'error', 'dsh-install'); return; }
|
|
20839
|
+
api.installDshBundle(bundle.manifestPath).then(function(result) {
|
|
20840
|
+
if (!result || !result.ok) throw new Error((result && result.error) || t('plugins.dshLoadError'));
|
|
20841
|
+
showUiNotice(t('plugins.dshInstallOk'), 'success', 'dsh-install-' + bundle.name);
|
|
20842
|
+
window.renderDshPlugin();
|
|
20843
|
+
}).catch(function(error) { showUiNotice(error.message || String(error), 'error', 'dsh-install-' + bundle.name); });
|
|
20844
|
+
};
|
|
20845
|
+
|
|
20846
|
+
window.uninstallDshBundle = function(index) {
|
|
20847
|
+
var bundle = dshCollection(state.dshCompatibility && state.dshCompatibility.bundles)[index];
|
|
20848
|
+
if (!bundle || !bundle.name) return;
|
|
20849
|
+
if (!api.uninstallDshBundle) { showUiNotice(t('plugins.dshUnavailable'), 'error', 'dsh-uninstall'); return; }
|
|
20850
|
+
api.uninstallDshBundle(bundle.name).then(function(result) {
|
|
20851
|
+
if (!result || !result.ok) throw new Error((result && result.error) || t('plugins.dshLoadError'));
|
|
20852
|
+
showUiNotice(t('plugins.dshUninstallOk'), 'success', 'dsh-uninstall-' + bundle.name);
|
|
20853
|
+
window.renderDshPlugin();
|
|
20854
|
+
}).catch(function(error) { showUiNotice(error.message || String(error), 'error', 'dsh-uninstall-' + bundle.name); });
|
|
20855
|
+
};
|
|
20856
|
+
|
|
20857
|
+
window.setDshBundleEnabled = function(index, enabled) {
|
|
20858
|
+
var bundle = dshCollection(state.dshCompatibility && state.dshCompatibility.bundles)[index];
|
|
20859
|
+
if (!bundle || !bundle.name) return;
|
|
20860
|
+
if (!api.setDshBundleEnabled) { showUiNotice(t('plugins.dshUnavailable'), 'error', 'dsh-toggle'); return; }
|
|
20861
|
+
api.setDshBundleEnabled(bundle.name, !!enabled).then(function(result) {
|
|
20862
|
+
if (!result || !result.ok) throw new Error((result && result.error) || t('plugins.dshLoadError'));
|
|
20863
|
+
showUiNotice(t('plugins.dshSetOk'), 'success', 'dsh-toggle-' + bundle.name);
|
|
20864
|
+
window.renderDshPlugin();
|
|
20865
|
+
}).catch(function(error) { showUiNotice(error.message || String(error), 'error', 'dsh-toggle-' + bundle.name); });
|
|
20866
|
+
};
|
|
20867
|
+
|
|
20484
20868
|
window.renderDshPlugin = function() {
|
|
20485
20869
|
var panel = document.getElementById('plugin-panel');
|
|
20486
20870
|
if (!panel || state.pluginActiveTab !== 'dsh') return;
|
|
@@ -20538,7 +20922,7 @@ window.renderDshPluginContent = function() {
|
|
|
20538
20922
|
'<dt>' + esc(t('plugins.dshUpdateChannel')) + '</dt><dd id="dsh-update-channel">' + esc(dshDisplayValue(updateChannel)) + '</dd></dl>' +
|
|
20539
20923
|
'<div class="dsh-description">' + esc(t('plugins.dshReadonlyDetail')) + '</div></section>' +
|
|
20540
20924
|
'<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>' +
|
|
20925
|
+
'<section class="dsh-card" id="dsh-bundles-card"><div class="dsh-card-title">' + esc(t('plugins.dshBundles')) + '</div>' + renderDshBundlesMarkup(dsh.bundles) + '</section>' +
|
|
20542
20926
|
'<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
20927
|
'<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
20928
|
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 +21414,18 @@ window.removeSkillFromUi = function(name) {
|
|
|
21030
21414
|
});
|
|
21031
21415
|
};
|
|
21032
21416
|
|
|
21417
|
+
window.refreshGithubOverview = function() {
|
|
21418
|
+
state.githubOverviewHash = '';
|
|
21419
|
+
window.loadGithubOverview('', { force: true });
|
|
21420
|
+
};
|
|
21421
|
+
|
|
21033
21422
|
window.renderGithubCliPanel = function() {
|
|
21034
21423
|
var panel = document.getElementById('plugin-panel');
|
|
21035
21424
|
if (!panel) return;
|
|
21036
|
-
panel.innerHTML = '<div
|
|
21425
|
+
panel.innerHTML = '<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;">' +
|
|
21426
|
+
'<div style="flex:1;font-size:13px;font-weight:700;color:var(--text);">' + esc(t('plugins.github')) + '</div>' +
|
|
21427
|
+
'<button type="button" class="sec-btn" onclick="window.refreshGithubOverview()">' + iconSvg('refresh-cw', t('plugins.refreshGh'), 'tiny') + ' ' + esc(t('plugins.refreshGh')) + '</button></div>' +
|
|
21428
|
+
'<div id="gh-overview" class="settings-card" style="min-height:220px;padding:14px;"></div>';
|
|
21037
21429
|
if (state.githubOverviewData) window.renderGithubOverview(state.githubOverviewData);
|
|
21038
21430
|
else document.getElementById('gh-overview').innerHTML = '<div class="settings-empty">' + esc(t('plugins.runningGh')) + '...</div>';
|
|
21039
21431
|
window.loadGithubOverview('', { initial: !state.githubOverviewLoaded });
|
|
@@ -21043,7 +21435,10 @@ window.renderGithubOverview = function(data) {
|
|
|
21043
21435
|
var out = document.getElementById('gh-overview');
|
|
21044
21436
|
if (!out) return;
|
|
21045
21437
|
if (!data || !data.ok) {
|
|
21046
|
-
out.innerHTML = '<div class="settings-empty">' + esc(data && data.error ? data.error : t('plugins.ghUnavailable')) + '</div>'
|
|
21438
|
+
out.innerHTML = '<div class="settings-empty">' + esc(data && data.error ? data.error : t('plugins.ghUnavailable')) + '</div>' +
|
|
21439
|
+
'<div style="display:flex;gap:8px;justify-content:center;margin-top:12px;">' +
|
|
21440
|
+
'<button type="button" class="sec-btn primary" onclick="window.githubCopilotLogin()">' + esc(t('plugins.connectGh')) + '</button>' +
|
|
21441
|
+
'<button type="button" class="sec-btn" onclick="window.refreshGithubOverview()">' + esc(t('plugins.refreshGh')) + '</button></div>';
|
|
21047
21442
|
return;
|
|
21048
21443
|
}
|
|
21049
21444
|
var account = data.account || {};
|
|
@@ -21089,6 +21484,10 @@ window.githubOverviewSignature = function(data) {
|
|
|
21089
21484
|
|
|
21090
21485
|
window.loadGithubOverview = function(repo, options) {
|
|
21091
21486
|
options = options || {};
|
|
21487
|
+
if (options.force) {
|
|
21488
|
+
state.githubOverviewHash = '';
|
|
21489
|
+
state.githubOverviewLoaded = false;
|
|
21490
|
+
}
|
|
21092
21491
|
var out = document.getElementById('gh-overview');
|
|
21093
21492
|
repo = String(repo || '').trim();
|
|
21094
21493
|
if (state.githubOverviewLoading) {
|
|
@@ -21871,6 +22270,47 @@ function guiHasSwitchableBranch() {
|
|
|
21871
22270
|
return branches.length > 1;
|
|
21872
22271
|
}
|
|
21873
22272
|
|
|
22273
|
+
window.showMobilePairing = function() {
|
|
22274
|
+
if (!api.mobilePairingQr) {
|
|
22275
|
+
showUiNotice('Mobile pairing API unavailable', 'error', 'mobile-pairing');
|
|
22276
|
+
return;
|
|
22277
|
+
}
|
|
22278
|
+
window.openSubWin(t('mobile.pair'), '<div style="text-align:center;color:var(--text-dim);">' + esc(t('common.loading')) + '</div>');
|
|
22279
|
+
api.mobilePairingQr().then(function(p) {
|
|
22280
|
+
if (!p || !p.ok) throw new Error((p && p.error) || 'Pairing failed');
|
|
22281
|
+
var expiresLabel = p.expiresAt ? Math.max(0, Math.round((p.expiresAt - Date.now()) / 1000)) + 's' : '';
|
|
22282
|
+
var html = '<div style="display:flex;flex-direction:column;align-items:center;gap:12px;padding:4px 2px;">' +
|
|
22283
|
+
'<img src="' + escAttr(p.dataUrl) + '" alt="Pairing QR" style="width:min(420px,100%);max-width:100%;border-radius:12px;background:#fff;padding:10px;">' +
|
|
22284
|
+
'<div style="font-size:12px;color:var(--text);word-break:break-all;text-align:center;">' + esc(p.url) + '</div>' +
|
|
22285
|
+
'<div style="font-size:11px;color:var(--text-dim);">' + esc(t('mobile.pairTokenFile')) + ': ' + esc(p.tokenFile) + '</div>' +
|
|
22286
|
+
'<div style="font-size:11px;color:var(--text-dim);">Tailscale: ' + esc(p.tailscaleIpv4 || '-') + '</div>' +
|
|
22287
|
+
(expiresLabel ? '<div style="font-size:11px;color:var(--text-dim);">' + esc('窗口期: ' + expiresLabel) + '</div>' : '') +
|
|
22288
|
+
'<div style="font-size:11px;color:var(--text-dim);text-align:center;max-width:420px;">' + esc(t('mobile.pairDesc')) + '</div>' +
|
|
22289
|
+
'</div>';
|
|
22290
|
+
window.openSubWin(t('mobile.pair'), html);
|
|
22291
|
+
// 连接成功后自动关闭二维码窗口
|
|
22292
|
+
if (api.mobilePairingStatus) {
|
|
22293
|
+
var poll = setInterval(function() {
|
|
22294
|
+
api.mobilePairingStatus().then(function(s) {
|
|
22295
|
+
var st = s && s.status;
|
|
22296
|
+
if (!st) return;
|
|
22297
|
+
if (st.confirmed) {
|
|
22298
|
+
clearInterval(poll);
|
|
22299
|
+
window.closeSubWin();
|
|
22300
|
+
showUiNotice('Mobile device connected', 'success', 'mobile-pairing-done');
|
|
22301
|
+
} else if (st.expired || !st.active) {
|
|
22302
|
+
clearInterval(poll);
|
|
22303
|
+
window.closeSubWin();
|
|
22304
|
+
showUiNotice('Pairing window expired', 'error', 'mobile-pairing-expired');
|
|
22305
|
+
}
|
|
22306
|
+
}).catch(function() {});
|
|
22307
|
+
}, 1000);
|
|
22308
|
+
}
|
|
22309
|
+
}).catch(function(err) {
|
|
22310
|
+
showUiNotice(err.message || String(err), 'error', 'mobile-pairing');
|
|
22311
|
+
});
|
|
22312
|
+
};
|
|
22313
|
+
|
|
21874
22314
|
function guiToggleTheme() {
|
|
21875
22315
|
var current = state.theme === 'light' ? 'light' : 'dark';
|
|
21876
22316
|
window.setTheme(current === 'light' ? 'dark' : 'light');
|
|
@@ -21893,6 +22333,7 @@ var NEWMARK_GUI_COMMANDS = [
|
|
|
21893
22333
|
guiCommand('workspace.manager', 'workspace.manager', 'workspace', { bindings:[{ keys:'Mod+K W', scope:'whenNotEditing' }], run:function(){ window.openWorkspaceManager(); } }),
|
|
21894
22334
|
guiCommand('workspace.new', 'workspace.new', 'workspace', { run:function(){ window.showNewWorkspaceDialog(); } }),
|
|
21895
22335
|
guiCommand('workspace.settings', 'workspace.settingsTitle', 'workspace', { run:function(){ window.openWsSettings(); }, available:function(){ return !!state.currentWorkspaceId; } }),
|
|
22336
|
+
guiCommand('mobile.pair', 'mobile.pair', 'general', { run:function(){ window.showMobilePairing(); } }),
|
|
21896
22337
|
|
|
21897
22338
|
guiCommand('view.plugins', 'plugins.title', 'navigation', { bindings:[{ keys:'Mod+K P', scope:'whenNotEditing' }], run:function(){ window.showPluginList(); } }),
|
|
21898
22339
|
guiCommand('view.plugins.mcp', 'plugins.mcp', 'navigation', { run:function(){ window.showPluginList('mcp'); } }),
|
|
@@ -22601,6 +23042,7 @@ function schedulePostStartupUiRendering() {
|
|
|
22601
23042
|
if (s.agentBackend) state.agentBackend = s.agentBackend;
|
|
22602
23043
|
if (s.configuredAgentBackend) state.configuredAgentBackend = s.configuredAgentBackend;
|
|
22603
23044
|
if (s.agentBackendRestartRequired !== undefined) state.agentBackendRestartRequired = !!s.agentBackendRestartRequired;
|
|
23045
|
+
if (s.remoteTouchEnabled !== undefined) state.remoteTouchEnabled = !!s.remoteTouchEnabled;
|
|
22604
23046
|
if (s.wslAvailable !== undefined) state.wslAvailable = !!s.wslAvailable;
|
|
22605
23047
|
if (Array.isArray(s.wslDistros)) state.wslDistros = s.wslDistros;
|
|
22606
23048
|
if (s.conversationId) state.activeBackendConversationId = s.conversationId;
|