clay-server 5.5.0-beta.1 → 5.5.0-beta.3
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/lib/clay-product-control-input.js +2 -2
- package/lib/clay-product-control-tools.js +1 -1
- package/lib/clay-product-control.js +4 -3
- package/lib/daemon-project-access.js +10 -2
- package/lib/daemon-projects.js +16 -4
- package/lib/daemon-worktree-controls.js +171 -0
- package/lib/daemon.js +14 -63
- package/lib/personal-provider-install.js +85 -0
- package/lib/personal-provider-settings.js +94 -0
- package/lib/project-logs-service.js +2 -2
- package/lib/project-pair-task-control.js +1 -1
- package/lib/project-pending-message-queue.js +6 -2
- package/lib/project-product-control.js +1 -0
- package/lib/project-session-actions.js +46 -3
- package/lib/project-session-pair.js +2 -0
- package/lib/project-sessions.js +11 -3
- package/lib/project-user-message.js +5 -1
- package/lib/project-vendor-login.js +95 -32
- package/lib/project-worker-auth.js +71 -0
- package/lib/project-worker-conversation.js +11 -2
- package/lib/project.js +9 -0
- package/lib/public/app.js +22 -0
- package/lib/public/css/icon-strip.css +5 -0
- package/lib/public/css/overlays.css +18 -0
- package/lib/public/css/settings-shell.css +14 -0
- package/lib/public/css/settings-ui.css +6 -0
- package/lib/public/css/split-view-layout.css +16 -11
- package/lib/public/modules/agent-message-bubbles.js +33 -4
- package/lib/public/modules/app-messages.js +7 -1
- package/lib/public/modules/app-projects.js +3 -4
- package/lib/public/modules/clay-control-copy.js +1 -0
- package/lib/public/modules/clay-tool-presentation.js +1 -1
- package/lib/public/modules/generation-stop.js +4 -4
- package/lib/public/modules/pane-activation.js +2 -2
- package/lib/public/modules/pane-bridge.js +4 -2
- package/lib/public/modules/personal-provider-context.js +11 -0
- package/lib/public/modules/project-settings.js +1 -1
- package/lib/public/modules/settings-section-nav.js +58 -0
- package/lib/public/modules/settings-shell-registry.js +4 -2
- package/lib/public/modules/settings-shell.js +17 -6
- package/lib/public/modules/sidebar-projects.js +23 -9
- package/lib/public/modules/sidebar-sessions.js +3 -0
- package/lib/public/modules/split-pane-force-stop.js +47 -0
- package/lib/public/modules/split-pane-header-state.js +11 -1
- package/lib/public/modules/split-pane-renderer.js +2 -2
- package/lib/public/modules/split-view-arrange-menu.js +38 -0
- package/lib/public/modules/split-view-create-menu.js +9 -5
- package/lib/public/modules/split-view-member-actions.js +42 -0
- package/lib/public/modules/split-view-picker-actions.js +2 -2
- package/lib/public/modules/split-view-presentation-renderer.js +10 -35
- package/lib/public/modules/split-view-presentations.js +9 -8
- package/lib/public/modules/split-view-sidebar-menu.js +2 -1
- package/lib/public/modules/split-view-workers.js +32 -17
- package/lib/public/modules/stt-settings.js +21 -4
- package/lib/public/modules/user-settings-layout.js +11 -8
- package/lib/public/modules/user-settings-provider-install.js +42 -0
- package/lib/public/modules/user-settings-providers.js +102 -0
- package/lib/public/modules/user-settings-voice.js +50 -41
- package/lib/public/modules/vendor-login-browser.js +1 -1
- package/lib/public/modules/vendor-login.js +72 -12
- package/lib/public/modules/view-workspace-state.js +1 -1
- package/lib/public/modules/worker-activity-indicator.js +49 -0
- package/lib/public/modules/worker-message-previews.js +47 -11
- package/lib/public/modules/worker-stop-controls.js +36 -0
- package/lib/public/modules/worktree-controls.js +86 -0
- package/lib/public/pane-assets/{app-4IZ6F6ND.js → app-ANJS2LSK.js} +1 -1
- package/lib/public/pane-assets/{chunk-L3FCTD7U.js → chunk-32YIYF7R.js} +1 -1
- package/lib/public/pane-assets/{chunk-RRYWV5JT.js → chunk-3EJ5IAHZ.js} +1 -1
- package/lib/public/pane-assets/{chunk-3E6LDNXF.js → chunk-3TIVBAKM.js} +1 -1
- package/lib/public/pane-assets/{chunk-I6X5J2V5.js → chunk-4QFNLHW5.js} +1 -1
- package/lib/public/pane-assets/{chunk-OB3KKICE.js → chunk-5XMZMIFG.js} +1 -1
- package/lib/public/pane-assets/chunk-6S2C7Q2N.js +1 -0
- package/lib/public/pane-assets/chunk-7B2GJI57.js +1 -0
- package/lib/public/pane-assets/{chunk-A7OB7HQS.js → chunk-BOFNCPTN.js} +1 -1
- package/lib/public/pane-assets/{chunk-ELL4UBGY.js → chunk-CXWAJEN5.js} +1 -1
- package/lib/public/pane-assets/{chunk-SEELA2D2.js → chunk-EWTXBZJO.js} +1 -1
- package/lib/public/pane-assets/{chunk-ADGKPVFD.js → chunk-G35ZOJGP.js} +1 -1
- package/lib/public/pane-assets/chunk-HYT24UBT.js +1 -0
- package/lib/public/pane-assets/chunk-ISQEPZMY.js +1 -0
- package/lib/public/pane-assets/{chunk-6ZF2FJT3.js → chunk-JM46WGDH.js} +1 -1
- package/lib/public/pane-assets/chunk-LBJG4MK2.js +174 -0
- package/lib/public/pane-assets/{chunk-YXJ7ISEK.js → chunk-P3AK4ORJ.js} +1 -1
- package/lib/public/pane-assets/chunk-QKPGE7DN.js +1 -0
- package/lib/public/pane-assets/chunk-TS5JUEVH.js +1 -0
- package/lib/public/pane-assets/{chunk-YWHBNEB2.js → chunk-UGH5MCNK.js} +1 -1
- package/lib/public/pane-assets/{chunk-YFUORWA6.js → chunk-V5DLPSLT.js} +1 -1
- package/lib/public/pane-assets/chunk-VFKDU64W.js +1 -0
- package/lib/public/pane-assets/{chunk-A4MLSYBJ.js → chunk-XSSTR6GC.js} +1 -1
- package/lib/public/pane-assets/{chunk-DJ5WXQKT.js → chunk-XVESKMU3.js} +1 -1
- package/lib/public/pane-assets/manifest.json +443 -433
- package/lib/public/pane-assets/style-VBVCWV44.css +1 -0
- package/lib/sdk-bridge.js +40 -6
- package/lib/sdk-force-stop.js +62 -0
- package/lib/sdk-message-processor.js +2 -1
- package/lib/server-worktree-controls.js +34 -0
- package/lib/server.js +11 -1
- package/lib/session-force-stop-support.js +15 -0
- package/lib/sessions.js +6 -1
- package/lib/terminal-manager.js +1 -1
- package/lib/terminal.js +13 -1
- package/lib/vendor-login-browser-flow.js +1 -1
- package/lib/worker-activity.js +26 -0
- package/lib/worker-message-previews.js +12 -7
- package/lib/worktree-branch.js +57 -0
- package/lib/worktree-identity.js +39 -0
- package/lib/worktree-preferences.js +25 -0
- package/lib/worktree-ref-transaction.js +36 -0
- package/lib/yoke/adapters/antigravity.js +3 -0
- package/lib/yoke/force-termination.js +26 -0
- package/lib/yoke/interface.js +14 -0
- package/lib/yoke/process-force-termination.js +24 -0
- package/lib/yoke/provider-install-recipes.js +20 -0
- package/lib/yoke/vendor-registry.js +20 -1
- package/package.json +1 -1
- package/lib/public/pane-assets/chunk-6KO36HMU.js +0 -1
- package/lib/public/pane-assets/chunk-FILRACQB.js +0 -168
- package/lib/public/pane-assets/chunk-H6MU72QE.js +0 -1
- package/lib/public/pane-assets/chunk-PJURCIJQ.js +0 -1
- package/lib/public/pane-assets/chunk-Q7RFSS5Q.js +0 -1
- package/lib/public/pane-assets/chunk-UTLQWAKG.js +0 -1
- package/lib/public/pane-assets/chunk-WE4NWXNK.js +0 -1
- package/lib/public/pane-assets/chunk-Z2MHS43B.js +0 -1
- package/lib/public/pane-assets/style-DZX6JAMF.css +0 -1
|
@@ -83,7 +83,7 @@ function attachProjectWorkerConversation(ctx) {
|
|
|
83
83
|
var activity = require('./project-pair-lifecycle-status').activityStatus(worker);
|
|
84
84
|
return { id: worker.localId, sessionOriginId: worker.sessionOriginId, parentSessionOriginId: driverOrigin, generation: binding.input.generation,
|
|
85
85
|
association: configured.indexOf(worker.localId) >= 0 ? 'current' : 'archived',
|
|
86
|
-
runtime: require('./session-activity-state').currentState(worker), delegated: activity.delegated,
|
|
86
|
+
recentActivity: require('./worker-activity').project(worker), runtime: require('./session-activity-state').currentState(worker), delegated: activity.delegated,
|
|
87
87
|
currentTaskId: activity.currentTaskId, interrupted: !!activity.interruption, lastTurnInterrupted: activity.lastTurnInterrupted };
|
|
88
88
|
}) };
|
|
89
89
|
} };
|
|
@@ -221,7 +221,16 @@ function attachProjectWorkerConversation(ctx) {
|
|
|
221
221
|
send(ws, response);
|
|
222
222
|
return true;
|
|
223
223
|
}
|
|
224
|
-
|
|
224
|
+
function currentPair(ws, target) {
|
|
225
|
+
var user = actor(ws), pair = user && exactPair(ws, target, user);
|
|
226
|
+
if (!pair || pair.driver.destroying || pair.worker.destroying) return null;
|
|
227
|
+
var group = ctx.getWorkerGroup && ctx.getWorkerGroup(pair.driver.localId);
|
|
228
|
+
var roles = require('./session-split-group-roles').resolveLiveRoles(sm, group);
|
|
229
|
+
if (!roles || roles.driver !== pair.driver || roles.workers.indexOf(pair.worker) < 0 ||
|
|
230
|
+
pair.worker._pairGeneration != null && pair.worker._pairGeneration !== target.generation) return null;
|
|
231
|
+
return { driver: pair.driver, worker: pair.worker, group: group, linuxUser: user.linuxUser };
|
|
232
|
+
}
|
|
233
|
+
return { handleMessage: handleMessage, supervision: supervision, currentPair: currentPair };
|
|
225
234
|
}
|
|
226
235
|
|
|
227
236
|
module.exports = { attachProjectWorkerConversation: attachProjectWorkerConversation };
|
package/lib/project.js
CHANGED
|
@@ -614,6 +614,7 @@ function createProjectContext(opts) {
|
|
|
614
614
|
// --- Session manager ---
|
|
615
615
|
var _gitAttribution = null;
|
|
616
616
|
var sm = createSessionManager({
|
|
617
|
+
onAuthRequired: function (session, msg) { return _workerAuth && _workerAuth.emit(session, msg); },
|
|
617
618
|
isMate: isMate,
|
|
618
619
|
cwd: cwd,
|
|
619
620
|
send: send,
|
|
@@ -718,6 +719,11 @@ function createProjectContext(opts) {
|
|
|
718
719
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
719
720
|
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
720
721
|
});
|
|
722
|
+
var _workerAuth = require('./project-worker-auth').attach({
|
|
723
|
+
sm: sm, clients: clients, slug: slug, osUsers: osUsers, sendTo: sendTo,
|
|
724
|
+
currentPair: _workerConversation.currentPair, requestAccess: _requestAccess,
|
|
725
|
+
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
726
|
+
});
|
|
721
727
|
|
|
722
728
|
var _projMode = typeof opts.onGetProjectDefaultMode === "function" ? opts.onGetProjectDefaultMode(slug) : null;
|
|
723
729
|
var _srvMode = typeof opts.onGetServerDefaultMode === "function" ? opts.onGetServerDefaultMode() : null;
|
|
@@ -2248,6 +2254,7 @@ function createProjectContext(opts) {
|
|
|
2248
2254
|
if (_scheduledTaskExecution) _scheduledTaskExecution.stopForSession(session, "The human stopped this scheduled run.");
|
|
2249
2255
|
return stopped;
|
|
2250
2256
|
},
|
|
2257
|
+
onPendingQueueRetire: function (session) { return _pendingMessageQueue.retireClaim(session); },
|
|
2251
2258
|
onPendingQueuePause: function (session, actor) { return _pendingMessageQueue.pause(session, actor); },
|
|
2252
2259
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
2253
2260
|
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
@@ -2453,6 +2460,7 @@ function createProjectContext(opts) {
|
|
|
2453
2460
|
|
|
2454
2461
|
// --- Vendor login flow (delegated to project-vendor-login.js) ---
|
|
2455
2462
|
var _vendorLogin = attachVendorLogin({
|
|
2463
|
+
workerAuth: _workerAuth,
|
|
2456
2464
|
onVendorAuthChanged: function () { _sessions.invalidateVendorUsage(); },
|
|
2457
2465
|
requestAccess: _requestAccess,
|
|
2458
2466
|
clients: clients,
|
|
@@ -2464,6 +2472,7 @@ function createProjectContext(opts) {
|
|
|
2464
2472
|
send: send,
|
|
2465
2473
|
sendTo: sendTo,
|
|
2466
2474
|
usersModule: usersModule,
|
|
2475
|
+
resolveOsUserInfo: resolveOsUserInfo,
|
|
2467
2476
|
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
2468
2477
|
getOsUserInfoForLinuxUser: getOsUserInfoForLinuxUser,
|
|
2469
2478
|
getLinuxUserForSession: getLinuxUserForSession,
|
package/lib/public/app.js
CHANGED
|
@@ -489,6 +489,27 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
489
489
|
scheduledMessageCorrelation: null,
|
|
490
490
|
activeSessionId: null,
|
|
491
491
|
speechActive: null,
|
|
492
|
+
settingsSectionPage: null,
|
|
493
|
+
settingsSectionScope: null,
|
|
494
|
+
settingsSectionActive: null,
|
|
495
|
+
settingsPageScroll: {},
|
|
496
|
+
personalProvidersOpen: false,
|
|
497
|
+
personalProvidersLoading: false,
|
|
498
|
+
personalProvidersError: '',
|
|
499
|
+
personalProvidersNotice: '',
|
|
500
|
+
personalProviderSignInResults: {},
|
|
501
|
+
personalProviderCatalog: null,
|
|
502
|
+
personalProviderContext: null,
|
|
503
|
+
personalProviderRequest: null,
|
|
504
|
+
personalProviderRevision: null,
|
|
505
|
+
personalProviderEditing: null,
|
|
506
|
+
personalProviderRuntimeDetailsOpen: false,
|
|
507
|
+
personalProviderSigningIn: null,
|
|
508
|
+
personalProviderInstall: null,
|
|
509
|
+
personalProviderInstallBusy: false,
|
|
510
|
+
personalProviderInstallRequest: null,
|
|
511
|
+
personalProviderInstallAwaiting: null,
|
|
512
|
+
speechSettingsContextGeneration: 0,
|
|
492
513
|
speechSettings: null,
|
|
493
514
|
speechSettingsRequest: 0,
|
|
494
515
|
speechSettingsSaving: false,
|
|
@@ -509,6 +530,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
509
530
|
agentMessagePreviews: {},
|
|
510
531
|
agentMessageBubble: null,
|
|
511
532
|
workerMessagePreviewSubscription: null,
|
|
533
|
+
workerActivityIndicators: {},
|
|
512
534
|
sessionVendorBound: false,
|
|
513
535
|
cliSessionId: null,
|
|
514
536
|
isHeadlessMode: false,
|
|
@@ -1764,3 +1764,8 @@ body.mate-workspace-active #composer-handoff-btn {
|
|
|
1764
1764
|
body.mate-workspace-active #knowledge-workbench-btn { display: flex !important; }
|
|
1765
1765
|
#mate-project-debates-btn { display: none !important; }
|
|
1766
1766
|
body.mate-workspace-active #mate-project-debates-btn { display: flex !important; }
|
|
1767
|
+
|
|
1768
|
+
.icon-strip-wt-item .wt-branch-abbrev svg {
|
|
1769
|
+
width: 14px;
|
|
1770
|
+
height: 14px;
|
|
1771
|
+
}
|
|
@@ -1207,3 +1207,21 @@ button.top-bar-pill.pill-accent:hover { background: color-mix(in srgb, var(--acc
|
|
|
1207
1207
|
.mate-delete-challenge input { height: 36px; box-sizing: border-box; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--text); font: inherit; }
|
|
1208
1208
|
.mate-delete-challenge input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
1209
1209
|
.mate-delete-confirm .confirm-btn:disabled { opacity: .4; cursor: not-allowed; }
|
|
1210
|
+
|
|
1211
|
+
.confirm-text.worktree-removal-review {
|
|
1212
|
+
white-space: pre-line;
|
|
1213
|
+
overflow-wrap: anywhere;
|
|
1214
|
+
max-height: 65vh;
|
|
1215
|
+
overflow-y: auto;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
.worktree-branch-option {
|
|
1219
|
+
display: flex;
|
|
1220
|
+
align-items: center;
|
|
1221
|
+
gap: 7px;
|
|
1222
|
+
margin-top: 12px;
|
|
1223
|
+
white-space: normal;
|
|
1224
|
+
cursor: pointer;
|
|
1225
|
+
}
|
|
1226
|
+
.worktree-branch-option input { margin: 0; accent-color: var(--accent); flex-shrink: 0; }
|
|
1227
|
+
.worktree-branch-option input:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
.settings-shell-nav .settings-nav-item.active { background: rgba(var(--overlay-rgb), .08); color: var(--text); }
|
|
47
47
|
.settings-shell-nav .settings-nav-item:focus-visible { outline-offset: -2px; }
|
|
48
48
|
.settings-shell-nav .settings-nav-dropdown { display: none; }
|
|
49
|
+
.settings-shell-content :is(.settings-hint, .settings-status) { overflow-wrap:anywhere; }
|
|
49
50
|
.settings-shell-content { flex: 1 1 auto; min-width: 0; overflow-y: auto; padding: 28px 40px calc(var(--safe-bottom) + 56px); }
|
|
50
51
|
.settings-shell-status { max-width: 760px; margin: 0 0 16px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-alt); color: var(--text-secondary); font-size: 13px; }
|
|
51
52
|
.settings-shell-status[data-state="error"] { border-color: color-mix(in srgb, var(--error) 40%, var(--border)); color: var(--error); }
|
|
@@ -101,3 +102,16 @@
|
|
|
101
102
|
@media (prefers-reduced-motion: reduce) {
|
|
102
103
|
#settings-shell * { transition: none !important; animation: none !important; }
|
|
103
104
|
}
|
|
105
|
+
|
|
106
|
+
/* Section links share the settings navigation recipe across covering scopes. */
|
|
107
|
+
.settings-shell-content [data-settings-section] { scroll-margin-top:16px; }
|
|
108
|
+
.settings-shell-content .ab-narrow [data-settings-section] { scroll-margin-top:60px; }
|
|
109
|
+
#user-settings #api-connections { margin-top:32px; }
|
|
110
|
+
#user-settings #us-voice-settings h4 { font-size:13px; font-weight:600; margin:20px 0 8px; }
|
|
111
|
+
#user-settings [data-section="us-providers"] .us-voice-row-controls > .settings-btn-sm { min-width:76px; font-size:13px; }
|
|
112
|
+
#user-settings [data-coding-provider] > .settings-card { padding:0 0 12px 34px; }
|
|
113
|
+
@media(max-width:600px) {
|
|
114
|
+
#user-settings [data-section="us-providers"] .us-voice-row-controls { display:grid; grid-template-columns:24px minmax(0,1fr) auto; gap:8px; }
|
|
115
|
+
#user-settings [data-section="us-providers"] .us-integration-state { grid-column:2; grid-row:2; }
|
|
116
|
+
#user-settings [data-section="us-providers"] .us-voice-row-controls > button { grid-column:3; grid-row:1 / span 2; }
|
|
117
|
+
}
|
|
@@ -518,3 +518,9 @@
|
|
|
518
518
|
#user-settings .email-setup-inline .email-setup-input { height:36px; font-size:13px; }
|
|
519
519
|
#user-settings .email-setup-inline .email-setup-actions { flex-wrap:wrap; }
|
|
520
520
|
#user-settings .email-setup-inline .email-setup-btn { min-height:32px; font-size:13px; }
|
|
521
|
+
|
|
522
|
+
:is(#user-settings, #project-settings, #server-settings) .settings-link { font-size:13px; color:var(--link); overflow-wrap:anywhere; }
|
|
523
|
+
|
|
524
|
+
:is(.us-section, .ps-section, .server-settings-section) .settings-section-heading { display:flex; align-items:center; justify-content:space-between; gap:12px; margin:26px 0 8px; min-height:32px; }
|
|
525
|
+
:is(#user-settings, #project-settings, #server-settings) .settings-section-heading h3 { margin:0; }
|
|
526
|
+
:is(#user-settings, #project-settings, #server-settings) .settings-runtime-details summary { cursor:pointer; width:fit-content; }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
.split-view-group-open, .split-view-group-more, .split-view-create-trigger,
|
|
3
3
|
.split-view-arrange button,
|
|
4
4
|
.split-view-worker-popover button, .split-pane-search,
|
|
5
|
-
.split-pane-info, .split-pane-sidebar,
|
|
5
|
+
.split-pane-force-stop, .split-pane-info, .split-pane-sidebar,
|
|
6
6
|
.split-view-canvas .split-view-arrange-trigger {
|
|
7
7
|
appearance: none;
|
|
8
8
|
border: 0;
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
background: var(--sidebar-hover);
|
|
20
20
|
color: var(--text);
|
|
21
21
|
}
|
|
22
|
-
.split-pane-info:hover, .split-pane-sidebar:hover {
|
|
22
|
+
.split-pane-force-stop:hover, .split-pane-info:hover, .split-pane-sidebar:hover {
|
|
23
23
|
background: var(--sidebar-hover);
|
|
24
24
|
color: var(--text);
|
|
25
25
|
}
|
|
@@ -30,10 +30,11 @@
|
|
|
30
30
|
outline: 2px solid var(--accent);
|
|
31
31
|
outline-offset: -2px;
|
|
32
32
|
}
|
|
33
|
-
.split-pane-info:focus-visible, .split-pane-sidebar:focus-visible {
|
|
33
|
+
.split-pane-force-stop:focus-visible, .split-pane-info:focus-visible, .split-pane-sidebar:focus-visible {
|
|
34
34
|
outline: 2px solid var(--accent);
|
|
35
35
|
outline-offset: -2px;
|
|
36
36
|
}
|
|
37
|
+
.split-pane-force-stop:disabled, .worker-conversation-stop:disabled { opacity: .45; cursor: default; }
|
|
37
38
|
.split-view-arrange button:disabled { opacity: .45; cursor: default; }
|
|
38
39
|
.split-view-create-trigger {
|
|
39
40
|
display: flex;
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
text-align: left;
|
|
47
48
|
}
|
|
48
49
|
.split-pane-search, .split-view-canvas .split-view-arrange-trigger,
|
|
49
|
-
.split-pane-info, .split-pane-sidebar,
|
|
50
|
+
.split-pane-force-stop, .split-pane-info, .split-pane-sidebar,
|
|
50
51
|
.split-view-worker-popover-header button {
|
|
51
52
|
display: inline-flex;
|
|
52
53
|
align-items: center;
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
padding: 5px;
|
|
57
58
|
flex: 0 0 24px;
|
|
58
59
|
}
|
|
59
|
-
.split-pane-search svg, .split-pane-info svg, .split-pane-sidebar svg,
|
|
60
|
+
.split-pane-force-stop svg, .split-pane-search svg, .split-pane-info svg, .split-pane-sidebar svg,
|
|
60
61
|
.split-view-worker-popover-header button svg { width: 14px; height: 14px; }
|
|
61
62
|
.split-pane-info { width: 20px; flex-basis: 20px; padding: 3px; }
|
|
62
63
|
.split-view-canvas .split-pane-header button[hidden] { display: none; }
|
|
@@ -258,9 +259,12 @@ body.split-view-resizing .split-pane-frame { pointer-events: none; }
|
|
|
258
259
|
.split-view-worker-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
259
260
|
.split-view-worker-identity { flex-shrink: 0; white-space: nowrap; }
|
|
260
261
|
.split-view-worker-generation { flex-shrink: 0; color: var(--text-dimmer); white-space: nowrap; }
|
|
261
|
-
.split-view-worker-
|
|
262
|
-
.split-view-worker-
|
|
263
|
-
.split-view-worker-
|
|
262
|
+
.split-view-worker-loop { display: inline-flex; align-items: center; justify-content: center; width: 5px; height: 5px; flex: 0 0 5px; color: var(--text-dimmer); transition: transform 350ms ease-in-out; }
|
|
263
|
+
.split-view-worker-loop svg { width: 9px; height: 9px; flex-shrink: 0; }
|
|
264
|
+
.split-view-worker-loop[data-state="working"] { color: var(--brand-green); }
|
|
265
|
+
@media (prefers-reduced-motion: reduce) { .split-view-worker-loop { transition: none; } }
|
|
266
|
+
.agent-message-bubble-activity { color: var(--text-muted); font-size: 10px; margin-bottom: 5px; line-height: 1.4; white-space: normal; }
|
|
267
|
+
.agent-message-bubble-text[hidden] { display: none; }
|
|
264
268
|
@keyframes split-view-working { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
|
|
265
269
|
.split-view-group { margin: 2px 0 8px; }
|
|
266
270
|
.split-view-group-heading { display: flex; align-items: center; gap: 2px; min-height: 34px; border-radius: 6px; }
|
|
@@ -410,7 +414,7 @@ body.wide-view .readonly-session-transcript .msg-user .bubble,
|
|
|
410
414
|
.split-view-worker-page-status { display: block; margin-top: 3px; line-height: 1.4; }
|
|
411
415
|
.split-view-worker-popover-footer button { margin-left: 8px; padding: 4px 6px; font-size: 10px; }
|
|
412
416
|
.split-view-worker-popover[hidden], .split-view-menu[hidden], .split-view-arrange[hidden], .split-view-workers[hidden], .split-view-drop-preview[hidden], .split-view-drag-ghost[hidden] { display: none; }
|
|
413
|
-
|
|
417
|
+
|
|
414
418
|
@media (pointer: coarse) { .split-view-worker-chip { min-height: 30px; } .split-view-divider { flex-basis: 10px; } }
|
|
415
419
|
|
|
416
420
|
/* Keep iframe nodes mounted while tree geometry changes around them. */
|
|
@@ -455,8 +459,6 @@ body.wide-view .readonly-session-transcript .msg-user .bubble,
|
|
|
455
459
|
#split-view-arrange-context-list [aria-selected="true"] { background: var(--accent-bg); color: var(--accent); }
|
|
456
460
|
.split-view-arrange [data-focus-layout] { width: 100%; min-height: 29px; margin-top: 5px; border-top: 1px solid var(--border-subtle); font-size: 11px; }
|
|
457
461
|
|
|
458
|
-
/* Light reflects received WebSocket output, independent of processing state. */
|
|
459
|
-
.split-view-worker-dot.io { background: var(--brand-green); box-shadow: 0 0 5px var(--brand-green); }
|
|
460
462
|
|
|
461
463
|
/* Header whitespace is a handle; text and controls retain their own actions. */
|
|
462
464
|
.split-pane-drag-space { flex: 1 1 12px; min-width: 12px; align-self: stretch; cursor: grab; touch-action: none; }
|
|
@@ -565,3 +567,6 @@ body.is-dragging .split-pane-header, body.is-dragging .split-pane-drag-space { c
|
|
|
565
567
|
.agent-message-bubble-avatar { width: 16px; height: 16px; border-radius: 4px; object-fit: contain; flex: none; }
|
|
566
568
|
.agent-message-bubble-vendor { overflow: hidden; text-overflow: ellipsis; }
|
|
567
569
|
.agent-message-bubble-time { margin-left: auto; flex: none; font-variant-numeric: tabular-nums; }
|
|
570
|
+
|
|
571
|
+
.split-view-canvas .split-pane-header .split-pane-force-stop { order: 11; }
|
|
572
|
+
.split-pane-force-stop:hover { color: var(--error); }
|
|
@@ -2,13 +2,14 @@ import { dismissTooltip } from './tooltip.js';
|
|
|
2
2
|
import { renderMarkdown } from './markdown.js';
|
|
3
3
|
import { store } from './store.js';
|
|
4
4
|
|
|
5
|
-
var timer = null;
|
|
5
|
+
var timer = null, recencyTimer = null;
|
|
6
6
|
function context() { return JSON.stringify([store.get('myUserId') || null, store.get('currentSlug'), store.get('projectSplitViewSocketGeneration') || 0]); }
|
|
7
7
|
export function messagePreviewKey(kind, identities) { return JSON.stringify([context(), kind].concat(identities)); }
|
|
8
8
|
function element() { return document.getElementById('agent-message-bubble'); }
|
|
9
9
|
function anchor(key) { return Array.from(document.querySelectorAll('[data-message-preview]')).find(function (node) { return node.dataset.messagePreview === key && node.isConnected && node.getClientRects().length && !node.closest('[hidden], .split-pane-cached'); }); }
|
|
10
10
|
function remove() {
|
|
11
11
|
if (timer) clearTimeout(timer); timer = null;
|
|
12
|
+
if (recencyTimer) clearTimeout(recencyTimer); recencyTimer = null;
|
|
12
13
|
var node = element(); if (node) node.remove();
|
|
13
14
|
document.querySelectorAll('[aria-describedby="agent-message-bubble"]').forEach(function (chip) { chip.removeAttribute('aria-describedby'); });
|
|
14
15
|
if (store.get('agentMessageBubble')) store.set({ agentMessageBubble: null });
|
|
@@ -37,9 +38,18 @@ function renderMetadata(node, latest) {
|
|
|
37
38
|
var date = new Date(latest.timestamp); time.dateTime = date.toISOString();
|
|
38
39
|
time.textContent = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
39
40
|
time.setAttribute('aria-label', 'Message time: ' + date.toLocaleString());
|
|
40
|
-
} else time.textContent = 'Time unavailable';
|
|
41
|
+
} else time.textContent = !latest.text && latest.activity ? 'No recent message' : 'Time unavailable';
|
|
41
42
|
meta.appendChild(time);
|
|
42
43
|
}
|
|
44
|
+
function renderActivity(node, activity, workerActivity, clock) {
|
|
45
|
+
var line = node.querySelector('.agent-message-bubble-activity');
|
|
46
|
+
if (!activity && !workerActivity) { if (line) line.remove(); return; }
|
|
47
|
+
if (!line) { line = document.createElement('div'); line.className = 'agent-message-bubble-activity'; node.insertBefore(line, node.querySelector('.agent-message-bubble-text')); }
|
|
48
|
+
if (!activity) { line.textContent = 'Activity time unavailable'; return; }
|
|
49
|
+
var elapsed = clock ? Math.floor((clock.age + performance.now() - clock.received) / 1000) : -1;
|
|
50
|
+
var age = elapsed < 0 ? 'Activity time unavailable' : 'last activity ' + (elapsed < 60 ? elapsed + 's' : elapsed < 3600 ? Math.floor(elapsed / 60) + 'm' : Math.floor(elapsed / 3600) + 'h') + ' ago';
|
|
51
|
+
line.textContent = activity.summary + ' · ' + age;
|
|
52
|
+
}
|
|
43
53
|
function show(key, held, fresh) {
|
|
44
54
|
var latest = (store.get('agentMessagePreviews') || {})[key], chip = anchor(key);
|
|
45
55
|
if (!latest || !chip || store.get('splitViewWorkerConversation') || store.get('backgroundTaskViewer') || store.get('paneSuspended') || document.hidden || !store.get('connected')) return;
|
|
@@ -52,7 +62,13 @@ function show(key, held, fresh) {
|
|
|
52
62
|
node.setAttribute('role', 'tooltip'); var text = document.createElement('div'); text.className = 'agent-message-bubble-text'; node.appendChild(text); document.body.appendChild(node);
|
|
53
63
|
}
|
|
54
64
|
renderMetadata(node, latest);
|
|
55
|
-
node
|
|
65
|
+
renderActivity(node, latest.activity, latest.workerActivity, latest.activityClock);
|
|
66
|
+
if (recencyTimer) clearTimeout(recencyTimer); recencyTimer = null;
|
|
67
|
+
if (latest.activity) recencyTimer = setTimeout(function () {
|
|
68
|
+
recencyTimer = null; var current = element(), state = store.get('agentMessageBubble');
|
|
69
|
+
if (current && state && state.key === key) show(key, state.held, false);
|
|
70
|
+
}, 1000);
|
|
71
|
+
node.querySelector('.agent-message-bubble-text').innerHTML = DOMPurify.sanitize(renderMarkdown(latest.text || ''), { ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'code', 'pre', 'ul', 'ol', 'li', 'blockquote', 'del', 's'], ALLOWED_ATTR: [], ALLOW_DATA_ATTR: false }); node.querySelector('.agent-message-bubble-text').hidden = !latest.text; node.dataset.held = String(!!held); node.dataset.live = String(expires > Date.now());
|
|
56
72
|
dismissTooltip();
|
|
57
73
|
chip.setAttribute('aria-describedby', node.id);
|
|
58
74
|
store.set({ agentMessageBubble: { key: key, expiresAt: expires, held: !!held } }); position();
|
|
@@ -65,13 +81,26 @@ export function rememberAgentMessage(key, preview, live) {
|
|
|
65
81
|
if (!preview || typeof preview.id !== 'string' || typeof preview.text !== 'string' || !preview.text.trim()) return;
|
|
66
82
|
var all = Object.assign({}, store.get('agentMessagePreviews') || {}), previous = all[key];
|
|
67
83
|
var fresh = !previous || previous.id !== preview.id;
|
|
68
|
-
all[key] = { id: preview.id, text: preview.text.slice(0, 1200), vendor: preview.vendor || previous && previous.vendor || null, timestamp: typeof preview.timestamp === 'number' && Number.isFinite(preview.timestamp) && preview.timestamp > 0 ? preview.timestamp : previous && previous.id === preview.id ? previous.timestamp : null };
|
|
84
|
+
all[key] = { activityClock: previous && previous.activityClock || null, workerActivity: previous && previous.workerActivity, activity: previous && previous.activity || null, id: preview.id, text: preview.text.slice(0, 1200), vendor: preview.vendor || previous && previous.vendor || null, timestamp: typeof preview.timestamp === 'number' && Number.isFinite(preview.timestamp) && preview.timestamp > 0 ? preview.timestamp : previous && previous.id === preview.id ? previous.timestamp : null };
|
|
69
85
|
var keys = Object.keys(all); while (keys.length > 128) delete all[keys.shift()];
|
|
70
86
|
store.set({ agentMessagePreviews: all });
|
|
71
87
|
var state = store.get('agentMessageBubble'), chip = anchor(key);
|
|
72
88
|
var held = !!(chip && (chip.matches(':hover') || chip.contains(document.activeElement)));
|
|
73
89
|
if (live && fresh || held || state && state.key === key) show(key, held || !!(state && state.key === key && state.held), !!live && fresh);
|
|
74
90
|
}
|
|
91
|
+
export function forgetAgentMessage(key) {
|
|
92
|
+
var all = Object.assign({}, store.get('agentMessagePreviews') || {}); delete all[key];
|
|
93
|
+
store.set({ agentMessagePreviews: all });
|
|
94
|
+
var state = store.get('agentMessageBubble'); if (state && state.key === key) remove();
|
|
95
|
+
}
|
|
96
|
+
export function rememberAgentActivity(key, activity, vendor, observedAt) {
|
|
97
|
+
var all = Object.assign({}, store.get('agentMessagePreviews') || {}), previous = all[key];
|
|
98
|
+
if (!activity && !previous) return;
|
|
99
|
+
all[key] = Object.assign({ text: '', timestamp: null, vendor: vendor || null }, previous || {}, { activity: activity, workerActivity: true, activityClock: activity && Number.isFinite(observedAt) && observedAt >= activity.timestamp ? { age: observedAt - activity.timestamp, received: performance.now() } : null });
|
|
100
|
+
store.set({ agentMessagePreviews: all });
|
|
101
|
+
var state = store.get('agentMessageBubble'), chip = anchor(key), held = !!(chip && (chip.matches(':hover') || chip.contains(document.activeElement)));
|
|
102
|
+
if (held || state && state.key === key) show(key, held || !!(state && state.held), false);
|
|
103
|
+
}
|
|
75
104
|
export function bindAgentMessageBubble(chip, key) {
|
|
76
105
|
chip.dataset.messagePreview = key;
|
|
77
106
|
if (chip.dataset.previewBound) return;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { handlePersonalProviderMessage } from './user-settings-providers.js';
|
|
1
2
|
import { handleSplitSessionCreated, finishPickerCreation } from './split-view-picker-actions.js';
|
|
2
3
|
import { handleWorkerMessagePreview } from './worker-message-previews.js';
|
|
3
4
|
import { handleBackgroundTaskPreview } from './background-task-previews.js';
|
|
@@ -125,7 +126,7 @@ import { showDebateSticky, showDebateConcludeConfirm, showDebateUserFloor, exitD
|
|
|
125
126
|
import { handleSkillInstallWs } from './app-skills-install.js';
|
|
126
127
|
import { handleNotificationsState, handleNotificationCreated, handleNotificationDismissed, handleNotificationDismissedAll, showUpdateBanner } from './app-notifications.js';
|
|
127
128
|
import { handleUpdateSnoozed } from './update-snooze.js';
|
|
128
|
-
import { autoStartLoginIfNeeded, handleVendorLoginReady, handleVendorLoginState, handleVendorLoginError, handleAuthRefreshed } from './vendor-login.js';
|
|
129
|
+
import { autoStartLoginIfNeeded, handleWorkerAuthRequired, handleVendorLoginReady, handleVendorLoginState, handleVendorLoginError, handleAuthRefreshed } from './vendor-login.js';
|
|
129
130
|
import { handleLoginBrowserMessage } from './vendor-login-browser.js';
|
|
130
131
|
import { handleDebatePreparing, handleDebateBriefReady, renderDebateBriefReady, handleDebateStarted, renderDebateStarted, handleDebateTurn, handleDebateActivity, handleDebateStream, handleDebateTurnDone, handleDebateCommentQueued, handleDebateCommentInjected, renderDebateCommentInjected, handleDebateResumed, handleDebateEnded, renderDebateEnded, handleDebateError, isDebateActive, renderMcpDebateProposal, renderDebateUserResume } from './debate.js';
|
|
131
132
|
import { handleMentionStart, handleMentionActivity, handleMentionStream, handleMentionDone, handleMentionError, renderMentionUser, renderMentionResponse, renderUserMention } from './mention.js';
|
|
@@ -143,6 +144,7 @@ export function processMessage(msg) {
|
|
|
143
144
|
if (handleOwnerNavigation(msg)) return;
|
|
144
145
|
if (["update_available", "up_to_date", "update_started", "update_check_failed"].indexOf(msg.type) !== -1) handleServerUpdate(msg);
|
|
145
146
|
if (/^(set_pin|set_keep_awake|set_inherit_groups|set_image_retention|set_update_channel|restart_server|shutdown_server)_result$/.test(msg.type)) handleServerSettingResult(msg);
|
|
147
|
+
if (handlePersonalProviderMessage(msg)) return;
|
|
146
148
|
if (handleProjectDebateMessage(msg)) return;
|
|
147
149
|
if (handleMcpConnectionMessage(msg)) return;
|
|
148
150
|
if (handleSharedBrowserMessage(msg)) return;
|
|
@@ -1618,6 +1620,10 @@ export function processMessage(msg) {
|
|
|
1618
1620
|
window.location.reload();
|
|
1619
1621
|
break;
|
|
1620
1622
|
|
|
1623
|
+
case "worker_auth_required":
|
|
1624
|
+
handleWorkerAuthRequired(msg);
|
|
1625
|
+
break;
|
|
1626
|
+
|
|
1621
1627
|
case "auth_required":
|
|
1622
1628
|
removeMatePreThinking();
|
|
1623
1629
|
setActivity(null);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { reviewWorktreeRemoval } from './worktree-controls.js';
|
|
1
2
|
import { prepareContextualWorkspaceDeparture } from './contextual-clay-workspace.js';
|
|
2
3
|
import { checkComposerDeparture, saveSessionRichDraft } from './session-rich-drafts.js';
|
|
3
4
|
// app-projects.js - Project list, switching, add/remove project modals
|
|
@@ -359,14 +360,12 @@ export function handleRemoveProjectCheckResult(msg) {
|
|
|
359
360
|
var slug = msg.slug || pendingRemoveSlug;
|
|
360
361
|
var name = msg.name || pendingRemoveName || slug;
|
|
361
362
|
if (!slug) return;
|
|
363
|
+
if (slug.indexOf("--") !== -1) { pendingRemoveSlug = null; pendingRemoveName = null; reviewWorktreeRemoval(slug, "exclude"); return; }
|
|
362
364
|
|
|
363
365
|
if (msg.count > 0) {
|
|
364
366
|
showRemoveProjectTaskDialog(slug, name, msg.count);
|
|
365
367
|
} else {
|
|
366
|
-
var
|
|
367
|
-
var confirmMsg = isWt
|
|
368
|
-
? 'Delete worktree "' + name + '"? The branch and working directory will be removed from disk.'
|
|
369
|
-
: 'Remove "' + name + '"? You can re-add it later.';
|
|
368
|
+
var confirmMsg = 'Remove "' + name + '"? You can re-add it later.';
|
|
370
369
|
showConfirm(confirmMsg, function () {
|
|
371
370
|
var iconEl = document.querySelector('.icon-strip-item[data-slug="' + slug + '"]');
|
|
372
371
|
if (iconEl) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
var domains = { session: 'conversation', project: 'project', mate: 'Mate profile', knowledge: 'Mate Knowledge', records: 'project record', schedule: 'schedule', conversation: 'Mate conversation', workspace: 'workspace', screen: 'screen', assignment: 'Driver work', studio: 'Studio workbench' };
|
|
2
2
|
var actions = {
|
|
3
|
+
force_stop: 'force terminate supported session and Worker runtimes and pause queued messages',
|
|
3
4
|
rename: 'rename this conversation so it is easier to find', stop: 'request Stop so this work can settle',
|
|
4
5
|
model: 'change the model for this conversation', effort: 'adjust reasoning effort for this conversation',
|
|
5
6
|
permission: 'change the reviewed permission mode', delete: 'remove the reviewed item',
|
|
@@ -294,7 +294,7 @@ export function clayToolPresentation(name, input, outcome) {
|
|
|
294
294
|
else { phase = 'returned'; label = 'Project change request returned'; }
|
|
295
295
|
} else if (def.rule === 'product-control') {
|
|
296
296
|
if (status === 'queued') { phase = 'pending'; label = input.action === 'stop' ? 'Stop requested · runtime pending' : input.action === 'queue_add' ? 'Message queued for project Driver' : 'Conversation change queued'; }
|
|
297
|
-
else if (status === 'completed') label = input.action === 'queue_add' ? 'Message delivered to project Driver' : input.action === 'queue_edit' ? 'Queued message updated' : input.action === 'queue_cancel' ? 'Queued message cancelled' : input.action === 'queue_reorder' ? 'Message queue reordered' : input.action === 'vendor' ? 'Driver provider selected' : 'Conversation change completed';
|
|
297
|
+
else if (status === 'completed') label = input.action === 'force_stop' ? 'Session and Worker runtimes exited · external effects unconfirmed' : input.action === 'queue_add' ? 'Message delivered to project Driver' : input.action === 'queue_edit' ? 'Queued message updated' : input.action === 'queue_cancel' ? 'Queued message cancelled' : input.action === 'queue_reorder' ? 'Message queue reordered' : input.action === 'vendor' ? 'Driver provider selected' : 'Conversation change completed';
|
|
298
298
|
else { phase = 'returned'; label = 'Conversation change request returned'; }
|
|
299
299
|
} else if (def.rule === 'observation') {
|
|
300
300
|
if (status !== 'pending') { label = 'Preference submission returned'; phase = 'returned'; }
|
|
@@ -2,10 +2,10 @@ import { store } from './store.js';
|
|
|
2
2
|
import { getWs } from './ws-ref.js';
|
|
3
3
|
import { isDriverOperatedView } from './worker-pane-lock.js';
|
|
4
4
|
|
|
5
|
-
export function stopGeneration() {
|
|
5
|
+
export function stopGeneration(force) {
|
|
6
6
|
var ws = getWs();
|
|
7
|
-
if (!store.get('processing') || !store.get('connected') || !ws || ws.readyState !== 1) return false;
|
|
8
|
-
var message = { type: 'stop' };
|
|
7
|
+
if ((!store.get('processing') && !isDriverOperatedView() && force !== true) || !store.get('connected') || !ws || ws.readyState !== 1) return false;
|
|
8
|
+
var message = { type: force === true ? 'force_stop' : 'stop' };
|
|
9
9
|
if (store.get('paneMode')) {
|
|
10
10
|
var binding = store.get('paneCommittedBinding');
|
|
11
11
|
if (!store.get('paneReady') || !binding || binding.sessionId !== store.get('activeSessionId') || binding.sessionOriginId !== store.get('sessionOriginId')) return false;
|
|
@@ -39,7 +39,7 @@ export function initGenerationStop() {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
function sync() {
|
|
42
|
-
button.classList.toggle('hidden', !store.get('processing'));
|
|
42
|
+
button.classList.toggle('hidden', !store.get('processing') && !isDriverOperatedView());
|
|
43
43
|
button.disabled = !store.get('connected');
|
|
44
44
|
button.title = store.get('connected') ? 'Stop generating' : 'Reconnect to stop generating';
|
|
45
45
|
place();
|
|
@@ -168,13 +168,13 @@ export function paneOutgoing(data) {
|
|
|
168
168
|
if (store.get('deferredSessionSwitch')) {
|
|
169
169
|
var source = store.get('deferredSessionSwitch');
|
|
170
170
|
if (source.draining) return null;
|
|
171
|
-
if (message.type === 'stop') return JSON.stringify(Object.assign({}, message, { sessionId: source.sessionId, sessionOriginId: source.origin }));
|
|
171
|
+
if (message.type === 'stop' || message.type === 'force_stop') return JSON.stringify(Object.assign({}, message, { sessionId: source.sessionId, sessionOriginId: source.origin }));
|
|
172
172
|
return null;
|
|
173
173
|
}
|
|
174
174
|
if (!enabled()) return data;
|
|
175
175
|
var binding = store.get('paneCommittedBinding');
|
|
176
176
|
if (store.get('panePendingBinding') || store.get('paneSuspended') || binding && !store.get('paneReady')) return null;
|
|
177
|
-
if (!binding) return ['stop', 'user_message', 'permission_response', 'ask_user_response', 'elicitation_response', 'user_dialog_response', 'input_sync'].indexOf(message.type) >= 0 ? null : data;
|
|
177
|
+
if (!binding) return ['stop', 'force_stop', 'user_message', 'permission_response', 'ask_user_response', 'elicitation_response', 'user_dialog_response', 'input_sync'].indexOf(message.type) >= 0 ? null : data;
|
|
178
178
|
if (message.paneBinding && !samePaneBinding(binding, message.paneBinding)) return null;
|
|
179
179
|
var gesture = (store.get('paneActionEvents') || []).find(function (entry) { return entry.event.isTrusted && entry.event.eventPhase && samePaneBinding(entry.binding, binding); });
|
|
180
180
|
var action = store.get('paneCallbackBinding') || gesture && gesture.binding;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { stopGeneration } from './generation-stop.js';
|
|
1
2
|
import { forwardStudioPresentation } from './clay-studio-render.js';
|
|
2
3
|
// Pane-side postMessage bridge for the split-view shell. A chrome-less pane
|
|
3
4
|
// iframe reports its context usage up to the parent (which renders a chip in
|
|
@@ -73,11 +74,12 @@ export function initPaneBridge() {
|
|
|
73
74
|
window.addEventListener("message", function (event) {
|
|
74
75
|
if (event.origin !== window.location.origin) return;
|
|
75
76
|
var msg = event.data;
|
|
76
|
-
if (!msg || (msg.type !== "clay-pane-toggle-context" && msg.type !== "clay-pane-toggle-search" && msg.type !== "clay-pane-search-command" && msg.type !== "clay-pane-layout-resize")) return;
|
|
77
|
+
if (!msg || (msg.type !== "clay-pane-force-stop" && msg.type !== "clay-pane-toggle-context" && msg.type !== "clay-pane-toggle-search" && msg.type !== "clay-pane-search-command" && msg.type !== "clay-pane-layout-resize")) return;
|
|
77
78
|
var committed = store.get('paneCommittedBinding');
|
|
78
79
|
if (event.source !== window.parent || !committed || !paneMessageBinding() ||
|
|
79
80
|
!samePaneBinding(committed, msg.paneBinding) || !samePaneBinding(paneMessageBinding(), msg.paneBinding)) return;
|
|
80
|
-
if (msg.type === "clay-pane-
|
|
81
|
+
if (msg.type === "clay-pane-force-stop") stopGeneration(true);
|
|
82
|
+
else if (msg.type === "clay-pane-layout-resize") {
|
|
81
83
|
if (msg.phase === 'begin') beginPaneLayoutScrollLock(msg.token, msg.scrollTop);
|
|
82
84
|
else if (msg.phase === 'end') endPaneLayoutScrollLock(msg.token);
|
|
83
85
|
} else if (msg.type === "clay-pane-toggle-context") togglePaneContextPanel();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { getWs } from './ws-ref.js';
|
|
3
|
+
export function personalProviderContext() {
|
|
4
|
+
return JSON.stringify([store.get('myUserId'), store.get('currentSlug'), store.get('projectSplitViewSocketGeneration')]);
|
|
5
|
+
}
|
|
6
|
+
export function personalLoginCurrent(message) {
|
|
7
|
+
if (!message.personalRequestId) return true;
|
|
8
|
+
return store.get('settingsOpen') && store.get('personalProvidersOpen') && store.get('connected') !== false &&
|
|
9
|
+
message.personalRequestId === store.get('personalProviderRevision') && store.get('personalProviderContext') === personalProviderContext() &&
|
|
10
|
+
getWs() && getWs().readyState === 1;
|
|
11
|
+
}
|
|
@@ -246,7 +246,7 @@ function updateIconPreview(icon) {
|
|
|
246
246
|
if (preview) {
|
|
247
247
|
preview.textContent = icon || "";
|
|
248
248
|
if (icon) parseEmojis(preview);
|
|
249
|
-
else { preview.innerHTML = '<i data-lucide="folder"></i>'; refreshIcons(); }
|
|
249
|
+
else { preview.innerHTML = '<i data-lucide="' + (settingsProject() && settingsProject().isWorktree ? 'git-branch' : 'folder') + '"></i>'; refreshIcons(); }
|
|
250
250
|
}
|
|
251
251
|
if (removeBtn) {
|
|
252
252
|
removeBtn.classList.toggle("hidden", !icon);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Personal provider anchors reuse the Agent behavior page's continuous-page
|
|
2
|
+
// navigation and shell placement. Other pages retain their own lifecycle.
|
|
3
|
+
import { store } from './store.js';
|
|
4
|
+
import { attachSectionNav } from './agent-behavior-nav.js';
|
|
5
|
+
import { setPageSubnav } from './settings-shell-view.js';
|
|
6
|
+
|
|
7
|
+
var mounted = null;
|
|
8
|
+
|
|
9
|
+
export function deactivateSettingsSections() {
|
|
10
|
+
if (!mounted) return;
|
|
11
|
+
var positions = Object.assign({}, store.get('settingsPageScroll') || {});
|
|
12
|
+
positions['user-settings:us-providers'] = mounted.scroller.scrollTop;
|
|
13
|
+
store.set({ settingsPageScroll: positions });
|
|
14
|
+
mounted.controller.destroy();
|
|
15
|
+
setPageSubnav(null, null);
|
|
16
|
+
mounted.nav.remove();
|
|
17
|
+
mounted.layout.classList.remove('ab-layout', 'ab-narrow');
|
|
18
|
+
mounted = null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function activateSettingsSections(page, anchor) {
|
|
22
|
+
var area = document.getElementById('settings-shell-content');
|
|
23
|
+
var pane = document.querySelector('.settings-pane:not(.hidden)');
|
|
24
|
+
if (!area || !pane) return;
|
|
25
|
+
if (page !== 'us-providers' || pane.id !== 'user-settings') {
|
|
26
|
+
// Agent behavior owns its catalog-derived anchors. Legacy shortcuts on
|
|
27
|
+
// other pages only reveal and focus their destination.
|
|
28
|
+
var heading = anchor && document.getElementById(anchor);
|
|
29
|
+
if (heading && pane.contains(heading)) {
|
|
30
|
+
if (heading.tagName === 'DETAILS') heading.open = true;
|
|
31
|
+
heading.tabIndex = -1; heading.scrollIntoView({ block: 'start' }); heading.focus({ preventScroll: true });
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!mounted) {
|
|
36
|
+
var layout = pane.querySelector('.us-section[data-section="us-providers"]');
|
|
37
|
+
var nav = document.createElement('nav'); nav.className = 'ab-nav'; nav.setAttribute('aria-label', 'AI providers sections');
|
|
38
|
+
var list = document.createElement('ul'); list.className = 'ab-nav-list'; nav.appendChild(list);
|
|
39
|
+
var sections = Array.from(layout.querySelectorAll('[data-settings-section]')).map(function (heading) {
|
|
40
|
+
var item = document.createElement('li'); var link = document.createElement('a');
|
|
41
|
+
link.className = 'ab-nav-link'; link.href = '#' + heading.id; link.dataset.section = heading.id;
|
|
42
|
+
link.dataset.settingsAnchor = heading.id; link.textContent = heading.textContent; item.appendChild(link); list.appendChild(item);
|
|
43
|
+
heading.tabIndex = -1;
|
|
44
|
+
return { id: heading.id, el: heading, heading: heading };
|
|
45
|
+
});
|
|
46
|
+
layout.classList.add('ab-layout');
|
|
47
|
+
var last = sections[sections.length - 1];
|
|
48
|
+
if (last && last.el.nextElementSibling) last.el.nextElementSibling.style.minHeight = area.clientHeight + 'px';
|
|
49
|
+
var controller = attachSectionNav({ layout: layout, nav: nav, scroller: area, sections: sections, onPlace: function (narrow) {
|
|
50
|
+
if (narrow) { setPageSubnav(null, null); layout.insertBefore(nav, layout.firstChild); }
|
|
51
|
+
else setPageSubnav('us-providers', nav);
|
|
52
|
+
} });
|
|
53
|
+
mounted = { layout: layout, nav: nav, scroller: area, controller: controller };
|
|
54
|
+
area.scrollTop = (store.get('settingsPageScroll') || {})['user-settings:us-providers'] || 0;
|
|
55
|
+
controller.refresh();
|
|
56
|
+
}
|
|
57
|
+
if (anchor) mounted.controller.go(anchor);
|
|
58
|
+
}
|
|
@@ -10,7 +10,7 @@ export var SETTINGS_SCOPES = [
|
|
|
10
10
|
|
|
11
11
|
export var PERSONAL_PAGES = [
|
|
12
12
|
{ id: 'us-account', label: 'Account' }, { id: 'us-appearance', label: 'Appearance' },
|
|
13
|
-
{ id: 'us-
|
|
13
|
+
{ id: 'us-providers', label: 'AI providers' }, { id: 'us-notifications', label: 'Notifications' },
|
|
14
14
|
{ id: 'us-ai', label: 'AI preferences' }, { id: 'us-agent', label: 'Agent behavior' }, { id: 'us-integrations', label: 'Integrations' }
|
|
15
15
|
];
|
|
16
16
|
|
|
@@ -31,7 +31,7 @@ export var SERVER_PAGES = [
|
|
|
31
31
|
];
|
|
32
32
|
|
|
33
33
|
var PERSONAL_ALIASES = {
|
|
34
|
-
'us-mates': 'us-
|
|
34
|
+
'us-chat': 'us-providers', 'us-mates': 'us-ai', 'us-experimental': 'us-ai', 'us-voice': 'us-providers', 'us-connections': 'us-integrations',
|
|
35
35
|
'us-email': 'us-integrations', 'us-logout': 'us-account'
|
|
36
36
|
};
|
|
37
37
|
var SERVER_ALIASES = { 'admin-invites': 'admin-users' };
|
|
@@ -66,6 +66,7 @@ export function scopeAvailable(scope, access) {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
export function resolvePage(scope, page, access) {
|
|
69
|
+
page = (page || '').split('#')[0];
|
|
69
70
|
var alias = scope === 'personal' ? PERSONAL_ALIASES[page] : scope === 'server' ? SERVER_ALIASES[page] : null;
|
|
70
71
|
var id = alias || page;
|
|
71
72
|
var pages = pagesForScope(scope, access);
|
|
@@ -82,6 +83,7 @@ export function resolveRoute(route, access) {
|
|
|
82
83
|
scope: scope,
|
|
83
84
|
page: resolvePage(scope, requested, access),
|
|
84
85
|
slug: scope === 'project' ? (route.slug || null) : null,
|
|
86
|
+
anchor: route.anchor || (route.page || '').split('#')[1] || (scope === 'personal' ? ({'us-chat':'api-connections','us-voice':'api-connections','us-experimental':'experimental-features','us-mates':'execution-behavior'})[route.page] : null) || null,
|
|
85
87
|
requestedScope: route.scope || 'personal',
|
|
86
88
|
redirected: scope !== (route.scope || 'personal')
|
|
87
89
|
};
|