clay-server 2.10.0 → 2.11.0-beta.2
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/dm.js +135 -0
- package/lib/project.js +142 -24
- package/lib/public/app.js +379 -5
- package/lib/public/css/icon-strip.css +162 -1
- package/lib/public/css/menus.css +23 -0
- package/lib/public/css/messages.css +182 -0
- package/lib/public/css/sidebar.css +4 -0
- package/lib/public/index.html +15 -0
- package/lib/public/modules/input.js +13 -2
- package/lib/public/modules/sidebar.js +105 -3
- package/lib/public/modules/tools.js +214 -1
- package/lib/sdk-bridge.js +76 -0
- package/lib/server.js +102 -0
- package/lib/sessions.js +26 -0
- package/lib/users.js +7 -0
- package/package.json +2 -2
package/lib/dm.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
var fs = require("fs");
|
|
2
|
+
var path = require("path");
|
|
3
|
+
var config = require("./config");
|
|
4
|
+
|
|
5
|
+
var DM_DIR = path.join(config.CONFIG_DIR, "dm");
|
|
6
|
+
|
|
7
|
+
// Ensure dm directory exists
|
|
8
|
+
function ensureDmDir() {
|
|
9
|
+
fs.mkdirSync(DM_DIR, { recursive: true });
|
|
10
|
+
config.chmodSafe(DM_DIR, 0o700);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Generate deterministic DM key from two user IDs (sorted, order-independent)
|
|
14
|
+
function dmKey(userId1, userId2) {
|
|
15
|
+
return [userId1, userId2].sort().join(":");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// File path for a DM conversation
|
|
19
|
+
function dmFilePath(key) {
|
|
20
|
+
// Replace : with _ for safe filename
|
|
21
|
+
return path.join(DM_DIR, key.replace(/:/g, "_") + ".jsonl");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Load DM history from JSONL file
|
|
25
|
+
function loadHistory(key) {
|
|
26
|
+
var filePath = dmFilePath(key);
|
|
27
|
+
if (!fs.existsSync(filePath)) return [];
|
|
28
|
+
try {
|
|
29
|
+
var content = fs.readFileSync(filePath, "utf8").trim();
|
|
30
|
+
if (!content) return [];
|
|
31
|
+
var lines = content.split("\n");
|
|
32
|
+
var messages = [];
|
|
33
|
+
for (var i = 0; i < lines.length; i++) {
|
|
34
|
+
if (!lines[i].trim()) continue;
|
|
35
|
+
try {
|
|
36
|
+
messages.push(JSON.parse(lines[i]));
|
|
37
|
+
} catch (e) {
|
|
38
|
+
// skip malformed lines
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return messages;
|
|
42
|
+
} catch (e) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Append a message to DM JSONL file
|
|
48
|
+
function appendMessage(key, message) {
|
|
49
|
+
ensureDmDir();
|
|
50
|
+
var filePath = dmFilePath(key);
|
|
51
|
+
var line = JSON.stringify(message) + "\n";
|
|
52
|
+
fs.appendFileSync(filePath, line);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Open a DM conversation (find or create)
|
|
56
|
+
function openDm(userId1, userId2) {
|
|
57
|
+
var key = dmKey(userId1, userId2);
|
|
58
|
+
var history = loadHistory(key);
|
|
59
|
+
return { dmKey: key, messages: history };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Send a DM message
|
|
63
|
+
function sendMessage(key, fromUserId, text) {
|
|
64
|
+
var message = {
|
|
65
|
+
type: "dm_message",
|
|
66
|
+
ts: Date.now(),
|
|
67
|
+
from: fromUserId,
|
|
68
|
+
text: text,
|
|
69
|
+
};
|
|
70
|
+
appendMessage(key, message);
|
|
71
|
+
return message;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Get list of all DM conversations for a user
|
|
75
|
+
// Returns: [{ dmKey, otherUserId, lastMessage, lastTs }]
|
|
76
|
+
function getDmList(userId) {
|
|
77
|
+
ensureDmDir();
|
|
78
|
+
var files;
|
|
79
|
+
try {
|
|
80
|
+
files = fs.readdirSync(DM_DIR).filter(function (f) {
|
|
81
|
+
return f.endsWith(".jsonl");
|
|
82
|
+
});
|
|
83
|
+
} catch (e) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
var dms = [];
|
|
88
|
+
for (var i = 0; i < files.length; i++) {
|
|
89
|
+
// Reconstruct dmKey from filename (replace _ back to :)
|
|
90
|
+
var key = files[i].replace(".jsonl", "").replace(/_/g, ":");
|
|
91
|
+
var parts = key.split(":");
|
|
92
|
+
if (parts.length !== 2) continue;
|
|
93
|
+
|
|
94
|
+
// Check if this user is a participant
|
|
95
|
+
var idx = parts.indexOf(userId);
|
|
96
|
+
if (idx === -1) continue;
|
|
97
|
+
|
|
98
|
+
var otherUserId = parts[idx === 0 ? 1 : 0];
|
|
99
|
+
|
|
100
|
+
// Get last message
|
|
101
|
+
var messages = loadHistory(key);
|
|
102
|
+
var lastMessage = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
103
|
+
|
|
104
|
+
dms.push({
|
|
105
|
+
dmKey: key,
|
|
106
|
+
otherUserId: otherUserId,
|
|
107
|
+
lastMessage: lastMessage ? lastMessage.text : null,
|
|
108
|
+
lastTs: lastMessage ? lastMessage.ts : 0,
|
|
109
|
+
messageCount: messages.length,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Sort by most recent activity
|
|
114
|
+
dms.sort(function (a, b) {
|
|
115
|
+
return b.lastTs - a.lastTs;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return dms;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Extension point: check if a user is a mate (AI persona)
|
|
122
|
+
// Returns false for now - will be implemented when Mates feature is added
|
|
123
|
+
function isMate(userId) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = {
|
|
128
|
+
dmKey: dmKey,
|
|
129
|
+
openDm: openDm,
|
|
130
|
+
sendMessage: sendMessage,
|
|
131
|
+
getDmList: getDmList,
|
|
132
|
+
loadHistory: loadHistory,
|
|
133
|
+
isMate: isMate,
|
|
134
|
+
DM_DIR: DM_DIR,
|
|
135
|
+
};
|
package/lib/project.js
CHANGED
|
@@ -979,7 +979,7 @@ function createProjectContext(opts) {
|
|
|
979
979
|
if (sm.currentModel) {
|
|
980
980
|
sendTo(ws, { type: "model_info", model: sm.currentModel, models: sm.availableModels || [] });
|
|
981
981
|
}
|
|
982
|
-
sendTo(ws, { type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
982
|
+
sendTo(ws, { type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
983
983
|
sendTo(ws, { type: "term_list", terminals: tm.list() });
|
|
984
984
|
sendTo(ws, { type: "notes_list", notes: nm.list() });
|
|
985
985
|
sendTo(ws, { type: "loop_registry_updated", records: getHubSchedules() });
|
|
@@ -1137,6 +1137,14 @@ function createProjectContext(opts) {
|
|
|
1137
1137
|
}
|
|
1138
1138
|
|
|
1139
1139
|
function handleMessage(ws, msg) {
|
|
1140
|
+
// --- DM messages (delegated to server-level handler) ---
|
|
1141
|
+
if (msg.type === "dm_open" || msg.type === "dm_send" || msg.type === "dm_list" || msg.type === "dm_typing") {
|
|
1142
|
+
if (typeof opts.onDmMessage === "function") {
|
|
1143
|
+
opts.onDmMessage(ws, msg);
|
|
1144
|
+
}
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1140
1148
|
if (msg.type === "push_subscribe") {
|
|
1141
1149
|
if (pushModule && msg.subscription) pushModule.addSubscription(msg.subscription, msg.replaceEndpoint);
|
|
1142
1150
|
return;
|
|
@@ -1179,17 +1187,31 @@ function createProjectContext(opts) {
|
|
|
1179
1187
|
if (msg.type === "resume_session") {
|
|
1180
1188
|
if (!msg.cliSessionId) return;
|
|
1181
1189
|
var cliSess = require("./cli-sessions");
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1190
|
+
// Try SDK for title first, then fall back to manual parsing
|
|
1191
|
+
var titlePromise = getSDK().then(function(sdkMod) {
|
|
1192
|
+
return sdkMod.getSessionInfo(msg.cliSessionId, { dir: cwd });
|
|
1193
|
+
}).then(function(info) {
|
|
1194
|
+
return (info && info.summary) ? info.summary.substring(0, 100) : null;
|
|
1195
|
+
}).catch(function() { return null; });
|
|
1196
|
+
|
|
1197
|
+
Promise.all([
|
|
1198
|
+
cliSess.readCliSessionHistory(cwd, msg.cliSessionId),
|
|
1199
|
+
titlePromise
|
|
1200
|
+
]).then(function(results) {
|
|
1201
|
+
var history = results[0];
|
|
1202
|
+
var sdkTitle = results[1];
|
|
1203
|
+
var title = sdkTitle || "Resumed session";
|
|
1204
|
+
if (!sdkTitle) {
|
|
1205
|
+
for (var i = 0; i < history.length; i++) {
|
|
1206
|
+
if (history[i].type === "user_message" && history[i].text) {
|
|
1207
|
+
title = history[i].text.substring(0, 50);
|
|
1208
|
+
break;
|
|
1209
|
+
}
|
|
1188
1210
|
}
|
|
1189
1211
|
}
|
|
1190
1212
|
var resumed = sm.resumeSession(msg.cliSessionId, { history: history, title: title }, ws);
|
|
1191
1213
|
if (resumed) ws._clayActiveSession = resumed.localId;
|
|
1192
|
-
}).catch(function
|
|
1214
|
+
}).catch(function() {
|
|
1193
1215
|
var resumed = sm.resumeSession(msg.cliSessionId, undefined, ws);
|
|
1194
1216
|
if (resumed) ws._clayActiveSession = resumed.localId;
|
|
1195
1217
|
});
|
|
@@ -1197,9 +1219,7 @@ function createProjectContext(opts) {
|
|
|
1197
1219
|
}
|
|
1198
1220
|
|
|
1199
1221
|
if (msg.type === "list_cli_sessions") {
|
|
1200
|
-
var cliSessions = require("./cli-sessions");
|
|
1201
1222
|
var _fs = require("fs");
|
|
1202
|
-
var _path = require("path");
|
|
1203
1223
|
// Collect session IDs already in relay (in-memory + persisted on disk)
|
|
1204
1224
|
var relayIds = {};
|
|
1205
1225
|
sm.sessions.forEach(function (s) {
|
|
@@ -1214,13 +1234,34 @@ function createProjectContext(opts) {
|
|
|
1214
1234
|
}
|
|
1215
1235
|
}
|
|
1216
1236
|
} catch (e) {}
|
|
1217
|
-
|
|
1218
|
-
|
|
1237
|
+
|
|
1238
|
+
getSDK().then(function(sdkMod) {
|
|
1239
|
+
return sdkMod.listSessions({ dir: cwd });
|
|
1240
|
+
}).then(function(sdkSessions) {
|
|
1241
|
+
var filtered = sdkSessions.filter(function(s) {
|
|
1219
1242
|
return !relayIds[s.sessionId];
|
|
1243
|
+
}).map(function(s) {
|
|
1244
|
+
return {
|
|
1245
|
+
sessionId: s.sessionId,
|
|
1246
|
+
firstPrompt: s.summary || s.firstPrompt || "",
|
|
1247
|
+
model: null,
|
|
1248
|
+
gitBranch: s.gitBranch || null,
|
|
1249
|
+
startTime: s.createdAt ? new Date(s.createdAt).toISOString() : null,
|
|
1250
|
+
lastActivity: s.lastModified ? new Date(s.lastModified).toISOString() : null,
|
|
1251
|
+
};
|
|
1220
1252
|
});
|
|
1221
1253
|
sendTo(ws, { type: "cli_session_list", sessions: filtered });
|
|
1222
|
-
}).catch(function
|
|
1223
|
-
|
|
1254
|
+
}).catch(function() {
|
|
1255
|
+
// Fallback to manual parsing if SDK fails
|
|
1256
|
+
var cliSessions = require("./cli-sessions");
|
|
1257
|
+
cliSessions.listCliSessions(cwd).then(function(sessions) {
|
|
1258
|
+
var filtered = sessions.filter(function(s) {
|
|
1259
|
+
return !relayIds[s.sessionId];
|
|
1260
|
+
});
|
|
1261
|
+
sendTo(ws, { type: "cli_session_list", sessions: filtered });
|
|
1262
|
+
}).catch(function() {
|
|
1263
|
+
sendTo(ws, { type: "cli_session_list", sessions: [] });
|
|
1264
|
+
});
|
|
1224
1265
|
});
|
|
1225
1266
|
return;
|
|
1226
1267
|
}
|
|
@@ -1256,6 +1297,14 @@ function createProjectContext(opts) {
|
|
|
1256
1297
|
s.title = String(msg.title).substring(0, 100);
|
|
1257
1298
|
sm.saveSessionFile(s);
|
|
1258
1299
|
sm.broadcastSessionList();
|
|
1300
|
+
// Sync title to SDK session
|
|
1301
|
+
if (s.cliSessionId) {
|
|
1302
|
+
getSDK().then(function(sdk) {
|
|
1303
|
+
sdk.renameSession(s.cliSessionId, s.title, { dir: cwd }).catch(function(e) {
|
|
1304
|
+
console.error("[project] SDK renameSession failed:", e.message);
|
|
1305
|
+
});
|
|
1306
|
+
}).catch(function() {});
|
|
1307
|
+
}
|
|
1259
1308
|
}
|
|
1260
1309
|
return;
|
|
1261
1310
|
}
|
|
@@ -1380,7 +1429,7 @@ function createProjectContext(opts) {
|
|
|
1380
1429
|
if (msg.type === "set_permission_mode" && msg.mode) {
|
|
1381
1430
|
// When dangerouslySkipPermissions is active, don't allow UI to change mode
|
|
1382
1431
|
if (dangerouslySkipPermissions) {
|
|
1383
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: "bypassPermissions", effort: sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1432
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: "bypassPermissions", effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1384
1433
|
return;
|
|
1385
1434
|
}
|
|
1386
1435
|
sm.currentPermissionMode = msg.mode;
|
|
@@ -1388,7 +1437,7 @@ function createProjectContext(opts) {
|
|
|
1388
1437
|
if (session) {
|
|
1389
1438
|
sdk.setPermissionMode(session, msg.mode);
|
|
1390
1439
|
}
|
|
1391
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1440
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1392
1441
|
return;
|
|
1393
1442
|
}
|
|
1394
1443
|
|
|
@@ -1402,7 +1451,7 @@ function createProjectContext(opts) {
|
|
|
1402
1451
|
if (session) {
|
|
1403
1452
|
sdk.setPermissionMode(session, msg.mode);
|
|
1404
1453
|
}
|
|
1405
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1454
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1406
1455
|
}
|
|
1407
1456
|
return;
|
|
1408
1457
|
}
|
|
@@ -1417,14 +1466,18 @@ function createProjectContext(opts) {
|
|
|
1417
1466
|
if (session) {
|
|
1418
1467
|
sdk.setPermissionMode(session, msg.mode);
|
|
1419
1468
|
}
|
|
1420
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1469
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1421
1470
|
}
|
|
1422
1471
|
return;
|
|
1423
1472
|
}
|
|
1424
1473
|
|
|
1425
1474
|
if (msg.type === "set_effort" && msg.effort) {
|
|
1426
1475
|
sm.currentEffort = msg.effort;
|
|
1427
|
-
|
|
1476
|
+
var session = getSessionForWs(ws);
|
|
1477
|
+
if (session) {
|
|
1478
|
+
sdk.setEffort(session, msg.effort);
|
|
1479
|
+
}
|
|
1480
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort, betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1428
1481
|
return;
|
|
1429
1482
|
}
|
|
1430
1483
|
|
|
@@ -1433,7 +1486,7 @@ function createProjectContext(opts) {
|
|
|
1433
1486
|
opts.onSetServerDefaultEffort(msg.effort);
|
|
1434
1487
|
}
|
|
1435
1488
|
sm.currentEffort = msg.effort;
|
|
1436
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort, betas: sm.currentBetas || [] });
|
|
1489
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort, betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1437
1490
|
return;
|
|
1438
1491
|
}
|
|
1439
1492
|
|
|
@@ -1442,13 +1495,20 @@ function createProjectContext(opts) {
|
|
|
1442
1495
|
opts.onSetProjectDefaultEffort(slug, msg.effort);
|
|
1443
1496
|
}
|
|
1444
1497
|
sm.currentEffort = msg.effort;
|
|
1445
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort, betas: sm.currentBetas || [] });
|
|
1498
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort, betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1446
1499
|
return;
|
|
1447
1500
|
}
|
|
1448
1501
|
|
|
1449
1502
|
if (msg.type === "set_betas") {
|
|
1450
1503
|
sm.currentBetas = msg.betas || [];
|
|
1451
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas });
|
|
1504
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas, thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
if (msg.type === "set_thinking") {
|
|
1509
|
+
sm.currentThinking = msg.thinking || "adaptive";
|
|
1510
|
+
if (msg.budgetTokens) sm.currentThinkingBudget = msg.budgetTokens;
|
|
1511
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1452
1512
|
return;
|
|
1453
1513
|
}
|
|
1454
1514
|
|
|
@@ -1549,6 +1609,34 @@ function createProjectContext(opts) {
|
|
|
1549
1609
|
return;
|
|
1550
1610
|
}
|
|
1551
1611
|
|
|
1612
|
+
if (msg.type === "fork_session" && msg.uuid) {
|
|
1613
|
+
var session = getSessionForWs(ws);
|
|
1614
|
+
if (!session || !session.cliSessionId) {
|
|
1615
|
+
sendTo(ws, { type: "error", text: "Cannot fork: no CLI session" });
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
var forkCliId = session.cliSessionId;
|
|
1619
|
+
var forkTitle = (session.title || "New Session") + " (fork)";
|
|
1620
|
+
getSDK().then(function(sdkMod) {
|
|
1621
|
+
return sdkMod.forkSession(forkCliId, {
|
|
1622
|
+
upToMessageId: msg.uuid,
|
|
1623
|
+
dir: cwd,
|
|
1624
|
+
});
|
|
1625
|
+
}).then(function(result) {
|
|
1626
|
+
var cliSess = require("./cli-sessions");
|
|
1627
|
+
return cliSess.readCliSessionHistory(cwd, result.sessionId).then(function(history) {
|
|
1628
|
+
var forked = sm.resumeSession(result.sessionId, { history: history, title: forkTitle }, ws);
|
|
1629
|
+
if (forked) {
|
|
1630
|
+
ws._clayActiveSession = forked.localId;
|
|
1631
|
+
sendTo(ws, { type: "fork_complete", sessionId: forked.localId });
|
|
1632
|
+
}
|
|
1633
|
+
});
|
|
1634
|
+
}).catch(function(e) {
|
|
1635
|
+
sendTo(ws, { type: "error", text: "Fork failed: " + (e.message || e) });
|
|
1636
|
+
});
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1552
1640
|
if (msg.type === "ask_user_response") {
|
|
1553
1641
|
var session = getSessionForWs(ws);
|
|
1554
1642
|
if (!session) return;
|
|
@@ -1583,7 +1671,7 @@ function createProjectContext(opts) {
|
|
|
1583
1671
|
if (decision === "allow_accept_edits") {
|
|
1584
1672
|
sdk.setPermissionMode(session, "acceptEdits");
|
|
1585
1673
|
sm.currentPermissionMode = "acceptEdits";
|
|
1586
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1674
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1587
1675
|
pending.resolve({ behavior: "allow", updatedInput: pending.toolInput });
|
|
1588
1676
|
sm.sendAndRecord(session, { type: "permission_resolved", requestId: requestId, decision: decision });
|
|
1589
1677
|
return;
|
|
@@ -1612,7 +1700,7 @@ function createProjectContext(opts) {
|
|
|
1612
1700
|
|
|
1613
1701
|
// Update permission mode for the new session
|
|
1614
1702
|
sm.currentPermissionMode = "acceptEdits";
|
|
1615
|
-
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1703
|
+
send({ type: "config_state", model: sm.currentModel || "", mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1616
1704
|
|
|
1617
1705
|
// Build prompt from plan content (sent from client) or plan file path
|
|
1618
1706
|
var clientPlanContent = msg.planContent || "";
|
|
@@ -1705,6 +1793,26 @@ function createProjectContext(opts) {
|
|
|
1705
1793
|
return;
|
|
1706
1794
|
}
|
|
1707
1795
|
|
|
1796
|
+
// --- MCP elicitation response ---
|
|
1797
|
+
if (msg.type === "elicitation_response") {
|
|
1798
|
+
var session = getSessionForWs(ws);
|
|
1799
|
+
if (!session) return;
|
|
1800
|
+
var pending = session.pendingElicitations && session.pendingElicitations[msg.requestId];
|
|
1801
|
+
if (!pending) return;
|
|
1802
|
+
delete session.pendingElicitations[msg.requestId];
|
|
1803
|
+
if (msg.action === "accept") {
|
|
1804
|
+
pending.resolve({ action: "accept", content: msg.content || {} });
|
|
1805
|
+
} else {
|
|
1806
|
+
pending.resolve({ action: "reject" });
|
|
1807
|
+
}
|
|
1808
|
+
sm.sendAndRecord(session, {
|
|
1809
|
+
type: "elicitation_resolved",
|
|
1810
|
+
requestId: msg.requestId,
|
|
1811
|
+
action: msg.action,
|
|
1812
|
+
});
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1708
1816
|
// --- Browse directories (for add-project autocomplete) ---
|
|
1709
1817
|
if (msg.type === "browse_dir") {
|
|
1710
1818
|
var rawPath = (msg.path || "").replace(/^~/, process.env.HOME || "/");
|
|
@@ -2654,6 +2762,14 @@ function createProjectContext(opts) {
|
|
|
2654
2762
|
session.title = (msg.text || "Image").substring(0, 50);
|
|
2655
2763
|
sm.saveSessionFile(session);
|
|
2656
2764
|
sm.broadcastSessionList();
|
|
2765
|
+
// Sync auto-title to SDK
|
|
2766
|
+
if (session.cliSessionId) {
|
|
2767
|
+
getSDK().then(function(sdk) {
|
|
2768
|
+
sdk.renameSession(session.cliSessionId, session.title, { dir: cwd }).catch(function(e) {
|
|
2769
|
+
console.error("[project] SDK renameSession failed:", e.message);
|
|
2770
|
+
});
|
|
2771
|
+
}).catch(function() {});
|
|
2772
|
+
}
|
|
2657
2773
|
}
|
|
2658
2774
|
|
|
2659
2775
|
var fullText = msg.text || "";
|
|
@@ -3154,6 +3270,8 @@ function createProjectContext(opts) {
|
|
|
3154
3270
|
},
|
|
3155
3271
|
warmup: function () {
|
|
3156
3272
|
sdk.warmup();
|
|
3273
|
+
// Migrate existing relay session titles to SDK format (one-time, async)
|
|
3274
|
+
sm.migrateSessionTitles(getSDK, cwd);
|
|
3157
3275
|
},
|
|
3158
3276
|
destroy: destroy,
|
|
3159
3277
|
};
|