clay-server 4.2.0 → 4.3.0-beta.10
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/driver-continuation-access.js +54 -0
- package/lib/driver-continuation-lease.js +52 -0
- package/lib/driver-continuation-pair-transfer.js +86 -0
- package/lib/driver-continuation-pair.js +86 -0
- package/lib/driver-continuation-record.js +40 -0
- package/lib/driver-continuation-startup.js +68 -0
- package/lib/driver-continuation-transaction.js +61 -0
- package/lib/driver-continuation-trigger.js +110 -0
- package/lib/multi-worker-feature.js +11 -0
- package/lib/project-connection.js +3 -1
- package/lib/project-driver-continuation.js +499 -0
- package/lib/project-message-delivery.js +20 -0
- package/lib/project-pair-autonomous-stop.js +14 -8
- package/lib/project-pair-close-transaction.js +59 -0
- package/lib/project-pair-global-stop.js +18 -0
- package/lib/project-pair-lifecycle-status.js +34 -0
- package/lib/project-pair-lifecycle.js +117 -135
- package/lib/project-pair-message.js +1 -1
- package/lib/project-pair-owned-stop.js +7 -4
- package/lib/project-pair-replacement-state.js +5 -1
- package/lib/project-pair-result-capture.js +116 -0
- package/lib/project-pair-result-delivery.js +140 -0
- package/lib/project-pair-result-outbox.js +400 -0
- package/lib/project-pair-result-pipeline.js +16 -0
- package/lib/project-pair-result-recovery.js +229 -0
- package/lib/project-pair-structural-close.js +20 -0
- package/lib/project-pair-task-control.js +45 -18
- package/lib/project-pair-worker-close.js +68 -0
- package/lib/project-session-handoff.js +48 -55
- package/lib/project-session-pair-prompt.js +26 -0
- package/lib/project-session-pair.js +87 -106
- package/lib/project-sessions.js +4 -0
- package/lib/project-user-message.js +21 -0
- package/lib/project-worker-creation-proposal.js +176 -0
- package/lib/project-worker-permission.js +7 -8
- package/lib/project-worker-proposal-runner.js +45 -0
- package/lib/project-worker-proposal.js +79 -115
- package/lib/project.js +87 -3
- package/lib/public/app.js +1 -0
- package/lib/public/css/driver-continuation.css +56 -0
- package/lib/public/css/messages.css +12 -0
- package/lib/public/css/mobile-nav.css +29 -14
- package/lib/public/css/overlays.css +54 -25
- package/lib/public/css/pane.css +66 -12
- package/lib/public/css/sidebar.css +62 -7
- package/lib/public/index.html +3 -3
- package/lib/public/modules/app-connection.js +165 -74
- package/lib/public/modules/app-messages.js +31 -3
- package/lib/public/modules/driver-continuation-state.js +76 -0
- package/lib/public/modules/driver-continuation.js +260 -0
- package/lib/public/modules/message-delivery-ui.js +63 -0
- package/lib/public/modules/message-delivery.js +163 -6
- package/lib/public/modules/pair-result-status.js +87 -0
- package/lib/public/modules/permission-control.js +10 -5
- package/lib/public/modules/project-activation.js +10 -7
- package/lib/public/modules/session-creation-cta.js +46 -0
- package/lib/public/modules/sidebar-mobile.js +42 -30
- package/lib/public/modules/sidebar-sessions.js +77 -52
- package/lib/public/modules/split-group-helpers.js +74 -2
- package/lib/public/modules/split-pair-ui.js +28 -6
- package/lib/public/modules/split-pane-reconciler.js +28 -0
- package/lib/public/modules/split-pane-renderer.js +107 -0
- package/lib/public/modules/split-view.js +58 -188
- package/lib/public/modules/websocket-lifecycle.js +178 -0
- package/lib/public/modules/websocket-watchdog.js +126 -0
- package/lib/public/modules/worker-pane-lock.js +13 -3
- package/lib/public/style.css +1 -0
- package/lib/sdk-bridge.js +77 -0
- package/lib/server.js +1 -0
- package/lib/session-handoff-discovery.js +443 -0
- package/lib/session-handoff-mcp-server.js +32 -4
- package/lib/session-pair-factory.js +66 -0
- package/lib/session-pair-mcp-server.js +10 -5
- package/lib/session-pair-prompts.js +46 -25
- package/lib/session-pair-target.js +42 -0
- package/lib/session-pair-turn-control.js +30 -9
- package/lib/session-split-group-anchors.js +126 -0
- package/lib/session-split-group-persistence.js +136 -0
- package/lib/session-split-group-roles.js +164 -0
- package/lib/session-split-group-v2-store.js +146 -0
- package/lib/session-split-groups.js +293 -133
- package/lib/sessions.js +89 -22
- package/lib/ws-schema.js +8 -0
- package/package.json +1 -1
package/lib/project.js
CHANGED
|
@@ -55,7 +55,11 @@ var { attachDelegatedFollowUp } = require("./project-delegated-follow-up");
|
|
|
55
55
|
var { attachCapsuleTurn } = require("./project-capsule-turn");
|
|
56
56
|
var workspaceSessionRef = require("./workspace-query-service").sessionRef;
|
|
57
57
|
var { attachSessionPair } = require("./project-session-pair");
|
|
58
|
+
var { attachPairResultOutbox } = require("./project-pair-result-outbox");
|
|
59
|
+
var { attachPairResultRecovery } = require("./project-pair-result-recovery");
|
|
58
60
|
var { attachSessionHandoff } = require("./project-session-handoff");
|
|
61
|
+
var { attachDriverContinuation } = require("./project-driver-continuation");
|
|
62
|
+
var driverContinuationAccess = require("./driver-continuation-access");
|
|
59
63
|
var { attachSessionNotes, composeSystemPrompts } = require("./project-session-notes");
|
|
60
64
|
var { attachSessionDocument } = require("./project-session-document");
|
|
61
65
|
var { attachCapsuleCatalog } = require("./project-capsule-catalog");
|
|
@@ -64,6 +68,7 @@ var { attachProjectLogs } = require("./project-logs");
|
|
|
64
68
|
var { attachProjectLogFeedbackDelivery } = require("./project-log-feedback-delivery");
|
|
65
69
|
var { attachProjectMateKnowledge } = require("./project-mate-knowledge");
|
|
66
70
|
var { attachSplitGroups } = require("./session-split-groups");
|
|
71
|
+
var multiWorkerFeature = require("./multi-worker-feature");
|
|
67
72
|
var toolControlMcp = require("./tool-control-mcp-server");
|
|
68
73
|
var capsuleFloor = require("./capsule-display-floor");
|
|
69
74
|
var toolLlm = require("./tool-llm");
|
|
@@ -203,6 +208,7 @@ function safeAbsPath(requested) {
|
|
|
203
208
|
* opts: { cwd, slug, title, pushModule, debug, dangerouslySkipPermissions, currentVersion }
|
|
204
209
|
*/
|
|
205
210
|
function createProjectContext(opts) {
|
|
211
|
+
var multiWorkerGate = multiWorkerFeature.fromServerConfig(opts);
|
|
206
212
|
var cwd = opts.cwd;
|
|
207
213
|
var slug = opts.slug;
|
|
208
214
|
var project = path.basename(cwd);
|
|
@@ -657,6 +663,7 @@ function createProjectContext(opts) {
|
|
|
657
663
|
clients: clients,
|
|
658
664
|
sendTo: sendTo,
|
|
659
665
|
usersModule: usersModule,
|
|
666
|
+
multiWorkerFeature: multiWorkerGate,
|
|
660
667
|
onPairChanged: function (group) {
|
|
661
668
|
if (!sdk || !group || !Array.isArray(group.members)) return;
|
|
662
669
|
for (var i = 0; i < group.members.length; i++) {
|
|
@@ -817,10 +824,14 @@ function createProjectContext(opts) {
|
|
|
817
824
|
|
|
818
825
|
// The SDK bridge is created after local MCP servers. Session spawning uses
|
|
819
826
|
// a getter so tool handlers see the initialized bridge when they run.
|
|
827
|
+
var _pairResultOutbox = attachPairResultOutbox({ storageDir: sm.sessionsDir, projectSlug: slug });
|
|
828
|
+
_pairResultOutbox.recoverPending(sm.sessions);
|
|
829
|
+
var _pairResultRecovery = null;
|
|
820
830
|
var _sessionPair = attachSessionPair({
|
|
821
831
|
sm: sm,
|
|
822
832
|
isMate: isMate,
|
|
823
833
|
splitStore: _splitGroups.store,
|
|
834
|
+
multiWorkerFeature: multiWorkerGate,
|
|
824
835
|
getSdk: function () { return sdk; },
|
|
825
836
|
send: send,
|
|
826
837
|
sendTo: sendTo,
|
|
@@ -835,12 +846,31 @@ function createProjectContext(opts) {
|
|
|
835
846
|
usersModule: usersModule,
|
|
836
847
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
837
848
|
onProcessingChanged: onProcessingChanged,
|
|
849
|
+
projectSlug: slug,
|
|
850
|
+
resultOutbox: _pairResultOutbox,
|
|
851
|
+
onResultStateChange: function (driver, record) { if (_pairResultRecovery) _pairResultRecovery.stateChanged(driver, record); },
|
|
838
852
|
adapters: adapters,
|
|
839
853
|
onPartnerResult: function (driver, worker, token) {
|
|
840
854
|
if (_scheduledTaskExecution) _scheduledTaskExecution.onPartnerResult(driver, worker, token);
|
|
841
855
|
if (_autonomousRun) _autonomousRun.onPartnerResult(driver, worker, token);
|
|
842
856
|
},
|
|
843
857
|
});
|
|
858
|
+
var _pairWorkerClose = require("./project-pair-worker-close").attachPairWorkerClose({
|
|
859
|
+
sm: sm,
|
|
860
|
+
splitStore: _splitGroups.store,
|
|
861
|
+
multiWorkerFeature: multiWorkerGate,
|
|
862
|
+
isMate: isMate,
|
|
863
|
+
projectSlug: slug,
|
|
864
|
+
hasSocket: function (ws) { return clients.has(ws); },
|
|
865
|
+
sendTo: sendTo,
|
|
866
|
+
closeWorker: _sessionPair.closeWorker,
|
|
867
|
+
});
|
|
868
|
+
_pairResultRecovery = attachPairResultRecovery({
|
|
869
|
+
sm: sm, store: _splitGroups.store, outbox: _pairResultOutbox, resultCapture: _sessionPair.resultCapture,
|
|
870
|
+
wake: _sessionPair.wakePartnerResult, projectSlug: slug, sendTo: sendTo,
|
|
871
|
+
blockedReason: _sessionPair.stopBarrier,
|
|
872
|
+
getClients: function () { return clients; }, isMultiUser: usersModule.isMultiUser,
|
|
873
|
+
});
|
|
844
874
|
var _sessionSpawn = attachSessionSpawn({
|
|
845
875
|
cwd: cwd,
|
|
846
876
|
sm: sm,
|
|
@@ -854,16 +884,41 @@ function createProjectContext(opts) {
|
|
|
854
884
|
});
|
|
855
885
|
var _sessionHandoff = attachSessionHandoff({
|
|
856
886
|
cwd: cwd,
|
|
887
|
+
projectSlug: slug,
|
|
857
888
|
sm: sm,
|
|
858
889
|
isMate: isMate,
|
|
859
890
|
splitStore: _splitGroups.store,
|
|
860
891
|
getSdk: function () { return sdk; },
|
|
861
892
|
sendTo: sendTo,
|
|
862
893
|
usersModule: usersModule,
|
|
894
|
+
isMultiUser: usersModule.isMultiUser,
|
|
895
|
+
getProjectAccess: opts.getProjectAccess || function () { return { visibility: "public", ownerId: projectOwnerId || null }; },
|
|
896
|
+
canAccessSession: usersModule.canAccessSession,
|
|
897
|
+
findUserById: usersModule.findUserById,
|
|
898
|
+
isDriverOperatedSession: function (session) { return !isMate && _sessionPair.workerPermission.isDriverOperated(session); },
|
|
863
899
|
adapters: adapters,
|
|
864
900
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
865
901
|
onProcessingChanged: onProcessingChanged,
|
|
866
902
|
});
|
|
903
|
+
var _driverContinuation = attachDriverContinuation({
|
|
904
|
+
sm: sm,
|
|
905
|
+
isMate: isMate,
|
|
906
|
+
projectSlug: slug,
|
|
907
|
+
splitStore: _splitGroups.store,
|
|
908
|
+
pendingMessageQueue: _pendingMessageQueue,
|
|
909
|
+
dangerouslySkipPermissions: dangerouslySkipPermissions,
|
|
910
|
+
isMultiUser: usersModule.isMultiUser,
|
|
911
|
+
isDriverOperatedSession: function (session) { return !isMate && _sessionPair.workerPermission.isDriverOperated(session); },
|
|
912
|
+
authorizeSession: function (session, ownerId) {
|
|
913
|
+
return driverContinuationAccess.authorize({ usersModule: usersModule, projectSlug: slug,
|
|
914
|
+
getProjectAccess: opts.getProjectAccess, canAccessProjectSlug: opts.canAccessProjectSlug }, session, ownerId);
|
|
915
|
+
},
|
|
916
|
+
getSdk: function () { return sdk; },
|
|
917
|
+
getLinuxUserForSession: getLinuxUserForSession,
|
|
918
|
+
onProcessingChanged: onProcessingChanged,
|
|
919
|
+
consumePendingMessage: function (session) { return _userMessage && _userMessage.consumePendingMessage(session); },
|
|
920
|
+
sendTo: sendTo,
|
|
921
|
+
});
|
|
867
922
|
var _debate = null;
|
|
868
923
|
var _debateProposal = attachDebateProposal({
|
|
869
924
|
cwd: cwd,
|
|
@@ -1250,6 +1305,7 @@ function createProjectContext(opts) {
|
|
|
1250
1305
|
},
|
|
1251
1306
|
onProcessingChanged: onProcessingChanged,
|
|
1252
1307
|
onSessionAvailable: function (session) {
|
|
1308
|
+
if (_pairResultRecovery) _pairResultRecovery.available(session);
|
|
1253
1309
|
if (_scheduledMessages) _scheduledMessages.notify();
|
|
1254
1310
|
if (_userMessage && session) setImmediate(function () { _userMessage.consumePendingMessage(session); });
|
|
1255
1311
|
},
|
|
@@ -1287,6 +1343,7 @@ function createProjectContext(opts) {
|
|
|
1287
1343
|
_sessionPair.getSystemPrompt(session),
|
|
1288
1344
|
_sessionNotes.getSystemPrompt(session),
|
|
1289
1345
|
_sessionHandoff.getSystemPrompt(session),
|
|
1346
|
+
_driverContinuation.getSystemPrompt(session),
|
|
1290
1347
|
_sessionDocument.getSystemPrompt(session),
|
|
1291
1348
|
_capsuleCatalog.getSystemPrompt(session),
|
|
1292
1349
|
_projectLogs.getSystemPrompt(session),
|
|
@@ -1304,6 +1361,7 @@ function createProjectContext(opts) {
|
|
|
1304
1361
|
return _sessionPair.getToolDefs(session)
|
|
1305
1362
|
.concat(_sessionNotes.getToolDefs(session))
|
|
1306
1363
|
.concat(_sessionHandoff.getToolDefs(session))
|
|
1364
|
+
.concat(_driverContinuation.getToolDefs(session, Number(session._sdkQueryGeneration || 0)))
|
|
1307
1365
|
.concat(_sessionDocument.getToolDefs(session))
|
|
1308
1366
|
.concat(_debateProposal.getToolDefs(session))
|
|
1309
1367
|
.concat(_mateCreationProposal.getToolDefs(session))
|
|
@@ -1712,8 +1770,11 @@ function createProjectContext(opts) {
|
|
|
1712
1770
|
if (msg.type === "memory_delete") { _memory.handleMemoryDelete(ws, msg); return; }
|
|
1713
1771
|
|
|
1714
1772
|
// --- Sessions, config, project mgmt (delegated to project-sessions.js) ---
|
|
1773
|
+
if (_pairResultRecovery.handleMessage(ws, msg)) return;
|
|
1774
|
+
if (_pairWorkerClose.handleMessage(ws, msg)) return;
|
|
1715
1775
|
if (_sessionPair.handleMessage(ws, msg)) return;
|
|
1716
1776
|
if (_sessionHandoff.handleMessage(ws, msg)) return;
|
|
1777
|
+
if (_driverContinuation.handleMessage(ws, msg)) return;
|
|
1717
1778
|
if (_splitGroups.handleMessage(ws, msg)) return;
|
|
1718
1779
|
if (_models.handleMessage(ws, msg)) return;
|
|
1719
1780
|
if (_scheduledTasks.handleMessage(ws, msg)) return;
|
|
@@ -1986,6 +2047,7 @@ function createProjectContext(opts) {
|
|
|
1986
2047
|
serverAuthToken: serverAuthToken,
|
|
1987
2048
|
resolveDefaultAi: opts.resolveDefaultAi,
|
|
1988
2049
|
});
|
|
2050
|
+
_pairResultRecovery.reconcile();
|
|
1989
2051
|
var _toolLlmRuntime = attachProjectToolLlmRuntime({
|
|
1990
2052
|
users: usersModule,
|
|
1991
2053
|
osUsers: osUsers,
|
|
@@ -2036,7 +2098,11 @@ function createProjectContext(opts) {
|
|
|
2036
2098
|
if (isMate || !_sessionPair.workerPermission) return false;
|
|
2037
2099
|
return _sessionPair.workerPermission.isDriverOperated(session);
|
|
2038
2100
|
},
|
|
2039
|
-
beginHumanPairTurn: function (session) {
|
|
2101
|
+
beginHumanPairTurn: function (session) {
|
|
2102
|
+
var resumed = _sessionPair.beginHumanTurn(session);
|
|
2103
|
+
if (resumed) _pairResultRecovery.beginHumanTurn(session);
|
|
2104
|
+
return resumed;
|
|
2105
|
+
},
|
|
2040
2106
|
authorizePendingDispatch: function (session, actor, item) {
|
|
2041
2107
|
if (!session || sm.sessions.get(session.localId) !== session || !item || item.projectSlug !== slug) return false;
|
|
2042
2108
|
if (_scheduledMessages && !_scheduledMessages.authorizePending(item, session)) return false;
|
|
@@ -2226,7 +2292,7 @@ function createProjectContext(opts) {
|
|
|
2226
2292
|
inputSchema: normalizeToolSchema(noteTools[nti].inputSchema),
|
|
2227
2293
|
});
|
|
2228
2294
|
}
|
|
2229
|
-
var handoffTools = _sessionHandoff.getToolDefs(boundSession);
|
|
2295
|
+
var handoffTools = _sessionHandoff.getToolDefs(boundSession, queryGeneration);
|
|
2230
2296
|
for (var hti = 0; hti < handoffTools.length; hti++) {
|
|
2231
2297
|
tools.push({
|
|
2232
2298
|
server: "clay-handoff",
|
|
@@ -2235,6 +2301,15 @@ function createProjectContext(opts) {
|
|
|
2235
2301
|
inputSchema: normalizeToolSchema(handoffTools[hti].inputSchema),
|
|
2236
2302
|
});
|
|
2237
2303
|
}
|
|
2304
|
+
var continuationTools = _driverContinuation.getToolDefs(boundSession, queryGeneration);
|
|
2305
|
+
for (var cti = 0; cti < continuationTools.length; cti++) {
|
|
2306
|
+
tools.push({
|
|
2307
|
+
server: "clay-continuation",
|
|
2308
|
+
name: continuationTools[cti].name,
|
|
2309
|
+
description: continuationTools[cti].description || continuationTools[cti].name,
|
|
2310
|
+
inputSchema: normalizeToolSchema(continuationTools[cti].inputSchema),
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2238
2313
|
var documentTools = _sessionDocument.getToolDefs(boundSession);
|
|
2239
2314
|
for (var dti = 0; dti < documentTools.length; dti++) {
|
|
2240
2315
|
tools.push({
|
|
@@ -2321,13 +2396,21 @@ function createProjectContext(opts) {
|
|
|
2321
2396
|
}
|
|
2322
2397
|
}
|
|
2323
2398
|
if (boundSession && serverName === "clay-handoff") {
|
|
2324
|
-
var handoffTools = _sessionHandoff.getToolDefs(boundSession);
|
|
2399
|
+
var handoffTools = _sessionHandoff.getToolDefs(boundSession, queryGeneration);
|
|
2325
2400
|
for (var hti = 0; hti < handoffTools.length; hti++) {
|
|
2326
2401
|
if (handoffTools[hti].name === toolName && typeof handoffTools[hti].handler === "function") {
|
|
2327
2402
|
return Promise.resolve(handoffTools[hti].handler(args || {}));
|
|
2328
2403
|
}
|
|
2329
2404
|
}
|
|
2330
2405
|
}
|
|
2406
|
+
if (boundSession && serverName === "clay-continuation") {
|
|
2407
|
+
var continuationTools = _driverContinuation.getToolDefs(boundSession, queryGeneration);
|
|
2408
|
+
for (var cti = 0; cti < continuationTools.length; cti++) {
|
|
2409
|
+
if (continuationTools[cti].name === toolName && typeof continuationTools[cti].handler === "function") {
|
|
2410
|
+
return Promise.resolve(continuationTools[cti].handler(args || {}));
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2331
2414
|
if (boundSession && serverName === "clay-documents") {
|
|
2332
2415
|
var documentTools = _sessionDocument.getToolDefs(boundSession);
|
|
2333
2416
|
for (var dti = 0; dti < documentTools.length; dti++) {
|
|
@@ -2452,6 +2535,7 @@ function createProjectContext(opts) {
|
|
|
2452
2535
|
_email: _email,
|
|
2453
2536
|
restoreDebateState: restoreDebateState,
|
|
2454
2537
|
scheduledMessages: _scheduledMessages,
|
|
2538
|
+
pairResultRecovery: _pairResultRecovery,
|
|
2455
2539
|
sendCursorSharingState: opts.sendCursorSharingState,
|
|
2456
2540
|
stopFileWatch: stopFileWatch,
|
|
2457
2541
|
stopAllDirWatches: stopAllDirWatches,
|
package/lib/public/app.js
CHANGED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
.driver-continuation-card,
|
|
2
|
+
.driver-continuation-context {
|
|
3
|
+
width: min(680px, calc(100% - 24px));
|
|
4
|
+
margin: 14px auto;
|
|
5
|
+
border: 1px solid var(--border);
|
|
6
|
+
border-radius: 14px;
|
|
7
|
+
background: var(--bg-alt);
|
|
8
|
+
color: var(--text);
|
|
9
|
+
box-shadow: 0 10px 28px rgba(0, 0, 0, .08);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.driver-continuation-card { padding: 18px; }
|
|
13
|
+
.driver-continuation-card header,
|
|
14
|
+
.driver-continuation-context { display: flex; align-items: flex-start; gap: 12px; }
|
|
15
|
+
.driver-continuation-context { padding: 15px 17px; }
|
|
16
|
+
.driver-continuation-card header > div,
|
|
17
|
+
.driver-continuation-context-copy { display: grid; gap: 3px; min-width: 0; flex: 1; }
|
|
18
|
+
.driver-continuation-mark { display: grid; place-items: center; width: 30px; height: 30px; flex: 0 0 auto; border-radius: 9px; color: var(--accent2); background: color-mix(in srgb, var(--accent2) 12%, transparent); }
|
|
19
|
+
.driver-continuation-kicker { font-size: 10px; line-height: 1.2; font-weight: 700; letter-spacing: .1em; color: var(--text-muted); }
|
|
20
|
+
.driver-continuation-status { margin-left: auto; white-space: nowrap; font-size: 12px; color: var(--text-muted); }
|
|
21
|
+
.driver-continuation-reason,
|
|
22
|
+
.driver-continuation-context p { margin: 12px 0; color: var(--text-secondary); line-height: 1.5; }
|
|
23
|
+
.driver-continuation-summary { display: grid; grid-template-columns: 80px 1fr; gap: 7px 12px; padding: 13px; border-radius: 10px; background: var(--bg); }
|
|
24
|
+
.driver-continuation-summary dt,
|
|
25
|
+
.driver-continuation-details dt { font-size: 11px; font-weight: 700; color: var(--text-muted); }
|
|
26
|
+
.driver-continuation-summary dd,
|
|
27
|
+
.driver-continuation-details dd { margin: 0; white-space: pre-wrap; line-height: 1.45; }
|
|
28
|
+
.driver-continuation-details { margin-top: 12px; color: var(--text-secondary); }
|
|
29
|
+
.driver-continuation-details summary { cursor: pointer; font-size: 12px; font-weight: 600; }
|
|
30
|
+
.driver-continuation-details dl { display: grid; grid-template-columns: 120px 1fr; gap: 8px 12px; margin: 12px 0 0; }
|
|
31
|
+
.driver-continuation-error { padding: 10px; border-radius: 8px; color: var(--error); background: var(--error-8); }
|
|
32
|
+
.driver-continuation-context .driver-continuation-error { color: var(--error); }
|
|
33
|
+
.driver-continuation-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
|
|
34
|
+
.driver-continuation-action,
|
|
35
|
+
.driver-continuation-source { min-height: 36px; border: 1px solid var(--border); border-radius: 9px; padding: 8px 13px; font: inherit; cursor: pointer; }
|
|
36
|
+
.driver-continuation-action.primary { display: inline-flex; align-items: center; gap: 7px; border-color: var(--accent2); background: color-mix(in srgb, var(--accent2) 16%, var(--bg)); color: var(--accent2); }
|
|
37
|
+
.driver-continuation-action.secondary,
|
|
38
|
+
.driver-continuation-source { background: transparent; color: var(--text); }
|
|
39
|
+
.driver-continuation-action:disabled,
|
|
40
|
+
.driver-continuation-source:disabled { cursor: not-allowed; opacity: .45; }
|
|
41
|
+
.driver-continuation-action:focus-visible,
|
|
42
|
+
.driver-continuation-source:focus-visible,
|
|
43
|
+
.driver-continuation-details summary:focus-visible { outline: 2px solid var(--accent2); outline-offset: 2px; }
|
|
44
|
+
.driver-continuation-source { justify-self: start; margin-top: 5px; padding: 5px 9px; min-height: 30px; font-size: 12px; }
|
|
45
|
+
|
|
46
|
+
@media (max-width: 600px) {
|
|
47
|
+
.driver-continuation-card,
|
|
48
|
+
.driver-continuation-context { width: calc(100% - 16px); }
|
|
49
|
+
.driver-continuation-card { padding: 14px; }
|
|
50
|
+
.driver-continuation-card header { flex-wrap: wrap; }
|
|
51
|
+
.driver-continuation-status { width: 100%; margin-left: 42px; }
|
|
52
|
+
.driver-continuation-summary,
|
|
53
|
+
.driver-continuation-details dl { grid-template-columns: 1fr; }
|
|
54
|
+
.driver-continuation-actions { flex-direction: column-reverse; }
|
|
55
|
+
.driver-continuation-action { width: 100%; justify-content: center; }
|
|
56
|
+
}
|
|
@@ -1387,6 +1387,18 @@ pre.mermaid-error {
|
|
|
1387
1387
|
.plan-banner.plan-exit { color: var(--success); }
|
|
1388
1388
|
.plan-banner.plan-exit .plan-banner-icon { color: var(--success); }
|
|
1389
1389
|
|
|
1390
|
+
.pair-result-status { display: grid; gap: 8px; padding: 10px 16px 0; }
|
|
1391
|
+
.pair-result-status-card { border: 1px solid var(--border); border-radius: 10px; background: var(--bg-alt); padding: 10px 12px; color: var(--text-secondary); font-size: 12px; }
|
|
1392
|
+
.pair-result-status-card > strong, .pair-result-status-card > span { display: block; }
|
|
1393
|
+
.pair-result-status-card > strong { color: var(--text); margin-bottom: 3px; }
|
|
1394
|
+
.pair-result-status-card details { margin-top: 7px; }
|
|
1395
|
+
.pair-result-status-card summary { cursor: pointer; color: var(--accent); }
|
|
1396
|
+
.pair-result-status-card pre { max-height: 180px; overflow: auto; white-space: pre-wrap; font: inherit; }
|
|
1397
|
+
.pair-result-status-card button { margin-top: 8px; }
|
|
1398
|
+
.pair-result-status-retry:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
1399
|
+
.pair-result-status-retry:disabled { cursor: not-allowed; opacity: 0.55; }
|
|
1400
|
+
.pair-result-status-uncertain, .pair-result-status-blocked { border-color: color-mix(in srgb, var(--warning) 45%, var(--border)); }
|
|
1401
|
+
|
|
1390
1402
|
/* --- Plan card --- */
|
|
1391
1403
|
.plan-card {
|
|
1392
1404
|
max-width: var(--content-width);
|
|
@@ -358,11 +358,15 @@
|
|
|
358
358
|
background: rgba(var(--overlay-rgb), 0.06);
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
|
|
362
|
-
|
|
361
|
+
.mobile-session-new:focus-visible {
|
|
362
|
+
outline: 2px solid var(--accent);
|
|
363
|
+
outline-offset: 2px;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Primary creation action with an adjacent icon-only provider selector. */
|
|
363
367
|
.mobile-session-new-row {
|
|
364
368
|
display: flex;
|
|
365
|
-
gap:
|
|
369
|
+
gap: 0;
|
|
366
370
|
padding: 6px 8px 8px;
|
|
367
371
|
}
|
|
368
372
|
|
|
@@ -370,33 +374,44 @@
|
|
|
370
374
|
flex: 1 1 auto;
|
|
371
375
|
width: auto;
|
|
372
376
|
margin-bottom: 0;
|
|
377
|
+
min-width: 0;
|
|
373
378
|
padding: 10px 12px;
|
|
374
379
|
border: 1px solid var(--border-subtle);
|
|
375
380
|
border-radius: 8px;
|
|
376
381
|
background: rgba(var(--overlay-rgb), 0.03);
|
|
377
382
|
color: var(--text);
|
|
378
383
|
gap: 8px;
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
384
|
+
border-radius: 8px 0 0 8px;
|
|
385
|
+
white-space: normal;
|
|
386
|
+
line-height: 1.2;
|
|
387
|
+
}
|
|
388
|
+
.mobile-session-new-row .mobile-session-new-provider {
|
|
389
|
+
flex: 0 0 34px;
|
|
390
|
+
width: 34px;
|
|
391
|
+
min-width: 34px;
|
|
383
392
|
margin-bottom: 0;
|
|
384
|
-
padding:
|
|
393
|
+
padding: 0;
|
|
385
394
|
border: 1px solid var(--border-subtle);
|
|
386
|
-
border-
|
|
395
|
+
border-left-color: var(--border);
|
|
396
|
+
border-radius: 0 8px 8px 0;
|
|
387
397
|
background: rgba(var(--overlay-rgb), 0.03);
|
|
388
398
|
color: var(--text-muted);
|
|
389
|
-
|
|
399
|
+
display: inline-flex;
|
|
400
|
+
align-items: center;
|
|
390
401
|
gap: 0;
|
|
391
|
-
|
|
392
|
-
.mobile-session-new-row .mobile-session-new-chevron.expanded svg {
|
|
393
|
-
transform: rotate(180deg);
|
|
402
|
+
justify-content: center;
|
|
394
403
|
}
|
|
395
404
|
.mobile-session-new-row .mobile-session-new-main:active,
|
|
396
|
-
.mobile-session-new-row .mobile-session-new-
|
|
405
|
+
.mobile-session-new-row .mobile-session-new-provider:active {
|
|
397
406
|
background: rgba(var(--overlay-rgb), 0.1);
|
|
398
407
|
}
|
|
399
408
|
|
|
409
|
+
.mobile-session-new-row .session-create-provider-chevron .lucide,
|
|
410
|
+
.mobile-session-new-row .session-create-provider-chevron svg {
|
|
411
|
+
width: 14px;
|
|
412
|
+
height: 14px;
|
|
413
|
+
}
|
|
414
|
+
|
|
400
415
|
.mobile-vendor-list {
|
|
401
416
|
display: flex;
|
|
402
417
|
flex-direction: column;
|
|
@@ -518,13 +518,13 @@ button.top-bar-pill.pill-accent:hover { background: color-mix(in srgb, var(--acc
|
|
|
518
518
|
.popover-copy:hover { color: var(--text); border-color: var(--text-dimmer); }
|
|
519
519
|
.popover-copy.copied { color: var(--success); border-color: var(--success); }
|
|
520
520
|
|
|
521
|
-
/*
|
|
521
|
+
/* Quiet native toolbar control for session permission mode. */
|
|
522
522
|
.session-permission-control {
|
|
523
523
|
display: inline-flex;
|
|
524
524
|
align-items: center;
|
|
525
525
|
flex: 0 1 auto;
|
|
526
|
-
flex-wrap:
|
|
527
|
-
gap:
|
|
526
|
+
flex-wrap: nowrap;
|
|
527
|
+
gap: 5px;
|
|
528
528
|
max-width: 100%;
|
|
529
529
|
min-width: 0;
|
|
530
530
|
}
|
|
@@ -533,52 +533,81 @@ button.top-bar-pill.pill-accent:hover { background: color-mix(in srgb, var(--acc
|
|
|
533
533
|
display: inline-flex;
|
|
534
534
|
align-items: center;
|
|
535
535
|
flex: 0 0 auto;
|
|
536
|
-
gap:
|
|
536
|
+
gap: 1px;
|
|
537
537
|
padding: 2px;
|
|
538
|
-
border: 1px solid var(--border
|
|
539
|
-
border-radius:
|
|
540
|
-
background: var(--
|
|
538
|
+
border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
|
|
539
|
+
border-radius: 8px;
|
|
540
|
+
background: color-mix(in srgb, var(--bg-alt) 72%, transparent);
|
|
541
541
|
}
|
|
542
542
|
.session-permission-segmented button {
|
|
543
|
-
|
|
543
|
+
position: relative;
|
|
544
|
+
flex: 0 0 48px;
|
|
545
|
+
width: 48px;
|
|
546
|
+
height: 22px;
|
|
544
547
|
border: 0;
|
|
545
|
-
border-radius:
|
|
546
|
-
padding: 3px
|
|
547
|
-
color: var(--text-
|
|
548
|
+
border-radius: 7px;
|
|
549
|
+
padding: 3px 4px;
|
|
550
|
+
color: var(--text-secondary);
|
|
548
551
|
background: transparent;
|
|
549
552
|
font: inherit;
|
|
553
|
+
font-weight: 500;
|
|
550
554
|
font-size: 11px;
|
|
555
|
+
line-height: 1;
|
|
551
556
|
white-space: nowrap;
|
|
552
557
|
cursor: pointer;
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
.session-permission-segmented button:disabled {
|
|
558
|
+
transition: color .15s ease, background .15s ease, box-shadow .15s ease, border-color .15s ease;
|
|
559
|
+
}
|
|
560
|
+
.session-permission-segmented button:hover:not(:disabled) { color: var(--text); background: color-mix(in srgb, var(--bg) 76%, transparent); }
|
|
561
|
+
.session-permission-segmented button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; z-index: 1; }
|
|
562
|
+
.session-permission-segmented button.active { border: 1px solid var(--border); background: var(--input-bg); color: var(--text); font-weight: var(--font-weight-heading, 600); box-shadow: 0 1px 2px rgba(var(--shadow-rgb), .12); }
|
|
563
|
+
:root.light-theme .session-permission-segmented button.active { background: var(--bg); }
|
|
564
|
+
.session-permission-segmented button:disabled { cursor: not-allowed; }
|
|
565
|
+
.session-permission-control:not(.permission-pending) .session-permission-segmented button:disabled { color: var(--text-muted); opacity: .65; }
|
|
556
566
|
.session-permission-control.permission-pending .session-permission-segmented button:disabled { cursor: wait; }
|
|
567
|
+
.session-permission-segmented button.pending { color: var(--text); background: color-mix(in srgb, var(--bg) 42%, transparent); }
|
|
568
|
+
.session-permission-segmented button.pending .permission-label { visibility: hidden; }
|
|
569
|
+
.permission-spinner { position: absolute; inset: 50% auto auto 50%; display: block; visibility: hidden; width: 10px; height: 10px; transform: translate(-50%, -50%); border: 1.5px solid currentColor; border-right-color: transparent; border-radius: 50%; }
|
|
570
|
+
.session-permission-segmented button.pending .permission-spinner { visibility: visible; animation: permission-spin .7s linear infinite; }
|
|
571
|
+
@keyframes permission-spin { to { transform: translate(-50%, -50%) rotate(360deg); } }
|
|
557
572
|
.session-permission-status {
|
|
558
|
-
flex:
|
|
573
|
+
flex: 0 1 auto;
|
|
559
574
|
min-width: 0;
|
|
560
|
-
max-width:
|
|
561
|
-
overflow
|
|
562
|
-
|
|
575
|
+
max-width: 180px;
|
|
576
|
+
overflow: hidden;
|
|
577
|
+
text-overflow: ellipsis;
|
|
578
|
+
white-space: nowrap;
|
|
579
|
+
padding: 3px 6px;
|
|
580
|
+
border: 1px solid transparent;
|
|
581
|
+
border-radius: 6px;
|
|
563
582
|
color: var(--text-dimmer, var(--text-muted));
|
|
564
583
|
font-size: 10px;
|
|
565
584
|
line-height: 1.2;
|
|
566
585
|
}
|
|
567
586
|
.session-permission-status.hidden { display: none; }
|
|
587
|
+
.session-permission-control.permission-pending .session-permission-status:not(.hidden) {
|
|
588
|
+
position: absolute;
|
|
589
|
+
width: 1px;
|
|
590
|
+
height: 1px;
|
|
591
|
+
padding: 0;
|
|
592
|
+
margin: -1px;
|
|
593
|
+
overflow: hidden;
|
|
594
|
+
clip: rect(0, 0, 0, 0);
|
|
595
|
+
white-space: nowrap;
|
|
596
|
+
border: 0;
|
|
597
|
+
}
|
|
568
598
|
.permission-runtime-fallback .session-permission-status { color: var(--warning, #d49a55); }
|
|
569
599
|
.permission-globally-forced .session-permission-status { color: var(--warning, #d49a55); }
|
|
570
|
-
.permission-label-short { display: none; }
|
|
571
600
|
@media (max-width: 760px) {
|
|
572
|
-
.permission-
|
|
573
|
-
.permission-label-short { display: inline; }
|
|
574
|
-
.session-permission-control { column-gap: 5px; row-gap: 2px; }
|
|
575
|
-
.session-permission-segmented button { padding-inline: 7px; }
|
|
601
|
+
.session-permission-control { column-gap: 4px; }
|
|
576
602
|
.session-permission-status {
|
|
577
|
-
|
|
578
|
-
max-width: 170px;
|
|
603
|
+
max-width: 132px;
|
|
579
604
|
font-size: 9px;
|
|
580
605
|
}
|
|
581
606
|
}
|
|
607
|
+
@media (prefers-reduced-motion: reduce) {
|
|
608
|
+
.session-permission-segmented button { transition: none; }
|
|
609
|
+
.session-permission-segmented button.pending .permission-spinner { animation: none; opacity: .7; }
|
|
610
|
+
}
|
|
582
611
|
#skip-perms-pill .lucide { width: 12px; height: 12px; flex-shrink: 0; }
|
|
583
612
|
|
|
584
613
|
/* --- Confirm modal --- */
|
package/lib/public/css/pane.css
CHANGED
|
@@ -73,6 +73,28 @@ body.pane-mode #input-area {
|
|
|
73
73
|
display: flex;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/* A configured two-Worker group is a deliberate workspace hierarchy: the
|
|
77
|
+
Driver gets the broad working canvas, while both Workers remain visible as
|
|
78
|
+
equal-height execution surfaces on the right. Legacy/ad-hoc two-pane
|
|
79
|
+
splits keep the ordinary equal columns below. */
|
|
80
|
+
#split-host:has(.split-pane-role-worker:nth-of-type(3)) {
|
|
81
|
+
display: grid;
|
|
82
|
+
grid-template-columns: minmax(0, 3fr) minmax(260px, 2fr);
|
|
83
|
+
grid-template-rows: repeat(2, minmax(0, 1fr));
|
|
84
|
+
gap: 1px;
|
|
85
|
+
background: var(--border-subtle);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#split-host:has(.split-pane-role-worker:nth-of-type(3)) .split-pane-role-driver {
|
|
89
|
+
grid-row: 1 / span 2;
|
|
90
|
+
grid-column: 1;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#split-host:has(.split-pane-role-worker:nth-of-type(3)) .split-pane-role-worker {
|
|
94
|
+
grid-column: 2;
|
|
95
|
+
grid-row: var(--split-worker-row, auto);
|
|
96
|
+
}
|
|
97
|
+
|
|
76
98
|
.split-pane {
|
|
77
99
|
flex: 1;
|
|
78
100
|
display: flex;
|
|
@@ -365,26 +387,34 @@ body.pane-mode #input-area {
|
|
|
365
387
|
line-height: 1;
|
|
366
388
|
}
|
|
367
389
|
|
|
368
|
-
/* Header-scoped
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
390
|
+
/* Header-scoped selectors keep the compact permission control clear of the
|
|
391
|
+
title and close affordance while preserving the shared header rhythm. */
|
|
392
|
+
.split-pane-header {
|
|
393
|
+
height: 28px;
|
|
394
|
+
min-height: 28px;
|
|
395
|
+
}
|
|
396
|
+
|
|
372
397
|
.split-pane-header .split-pane-full-access {
|
|
373
|
-
height:
|
|
398
|
+
height: 24px;
|
|
374
399
|
align-self: center;
|
|
375
400
|
margin-left: 0;
|
|
376
401
|
padding: 0;
|
|
377
402
|
gap: 4px;
|
|
378
|
-
font-size:
|
|
403
|
+
font-size: 11px;
|
|
379
404
|
letter-spacing: 0.02em;
|
|
380
405
|
flex-wrap: nowrap;
|
|
381
406
|
flex: 0 0 auto;
|
|
382
|
-
overflow: hidden;
|
|
383
407
|
}
|
|
384
408
|
|
|
385
409
|
.split-pane-header .session-permission-segmented button {
|
|
386
|
-
|
|
387
|
-
|
|
410
|
+
min-height: 20px;
|
|
411
|
+
height: 20px;
|
|
412
|
+
font-size: 11px;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.split-pane-header .session-permission-segmented {
|
|
416
|
+
height: 24px;
|
|
417
|
+
padding: 1px;
|
|
388
418
|
}
|
|
389
419
|
|
|
390
420
|
.split-pane-header .session-permission-status {
|
|
@@ -394,7 +424,7 @@ body.pane-mode #input-area {
|
|
|
394
424
|
overflow: hidden;
|
|
395
425
|
text-overflow: ellipsis;
|
|
396
426
|
white-space: nowrap;
|
|
397
|
-
font-size:
|
|
427
|
+
font-size: 10px;
|
|
398
428
|
}
|
|
399
429
|
|
|
400
430
|
.split-pane-header .session-full-access-track {
|
|
@@ -433,6 +463,11 @@ body.pane-mode #input-area {
|
|
|
433
463
|
color: var(--text);
|
|
434
464
|
}
|
|
435
465
|
|
|
466
|
+
.split-pane-close:disabled {
|
|
467
|
+
opacity: 0.42;
|
|
468
|
+
cursor: not-allowed;
|
|
469
|
+
}
|
|
470
|
+
|
|
436
471
|
.split-pane-close svg {
|
|
437
472
|
width: 12px;
|
|
438
473
|
height: 12px;
|
|
@@ -470,6 +505,25 @@ body.pane-mode #input-area {
|
|
|
470
505
|
--split-worker-height: calc(30% - 4.8px);
|
|
471
506
|
}
|
|
472
507
|
|
|
508
|
+
#split-host:has(.split-pane-role-worker:nth-of-type(3)) {
|
|
509
|
+
display: flex;
|
|
510
|
+
flex-direction: column;
|
|
511
|
+
gap: var(--split-pane-gap);
|
|
512
|
+
background: transparent;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
#split-host:has(.split-pane-role-worker:nth-of-type(3)) .split-pane-role-driver,
|
|
516
|
+
#split-host:has(.split-pane-role-worker:nth-of-type(3)) .split-pane-role-worker {
|
|
517
|
+
grid-row: auto;
|
|
518
|
+
grid-column: auto;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
#split-host:has(.split-pane-role-worker:nth-of-type(3)) .split-pane-role-worker {
|
|
522
|
+
flex: 0 1 24%;
|
|
523
|
+
min-height: 104px;
|
|
524
|
+
order: -1;
|
|
525
|
+
}
|
|
526
|
+
|
|
473
527
|
#split-host.visible {
|
|
474
528
|
flex-direction: column;
|
|
475
529
|
gap: var(--split-pane-gap);
|
|
@@ -487,11 +541,11 @@ body.pane-mode #input-area {
|
|
|
487
541
|
}
|
|
488
542
|
|
|
489
543
|
.split-pane-role-worker {
|
|
490
|
-
order: -1;
|
|
544
|
+
order: var(--split-pane-order, -1);
|
|
491
545
|
}
|
|
492
546
|
|
|
493
547
|
.split-pane-role-driver {
|
|
494
|
-
order: 0;
|
|
548
|
+
order: var(--split-pane-order, 0);
|
|
495
549
|
}
|
|
496
550
|
|
|
497
551
|
/* A configured Worker is an execution summary; the Driver keeps the
|