clay-server 4.1.0-beta.4 → 4.1.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/autonomous-run-record.js +32 -0
- package/lib/autonomous-run-scheduler.js +92 -0
- package/lib/durable-scheduler-record.js +61 -0
- package/lib/durable-scheduler-store.js +185 -0
- package/lib/durable-scheduler.js +495 -0
- package/lib/loop-cron.js +47 -0
- package/lib/loop-durable-schedule.js +159 -0
- package/lib/loop-guidance.js +35 -0
- package/lib/loop-registry-occurrence.js +76 -0
- package/lib/project-autonomous-run.js +498 -0
- package/lib/project-connection.js +4 -1
- package/lib/project-full-access.js +86 -0
- package/lib/project-http.js +3 -1
- package/lib/project-loop-interview.js +163 -0
- package/lib/project-loop.js +150 -64
- package/lib/project-pair-autonomous-stop.js +16 -0
- package/lib/project-pair-owned-stop.js +18 -0
- package/lib/project-pair-task-control.js +14 -1
- package/lib/project-scheduled-messages.js +316 -0
- package/lib/project-scheduled-task-execution.js +236 -0
- package/lib/project-scheduled-tasks.js +483 -0
- package/lib/project-session-pair.js +16 -19
- package/lib/project-sessions.js +60 -28
- package/lib/project-user-message.js +24 -18
- package/lib/project.js +260 -52
- package/lib/public/app.js +60 -23
- package/lib/public/css/home-hub.css +15 -2
- package/lib/public/css/home-sidebar.css +50 -2
- package/lib/public/css/input.css +71 -0
- package/lib/public/css/mates.css +0 -1
- package/lib/public/css/pane.css +58 -7
- package/lib/public/css/rewind.css +11 -2
- package/lib/public/css/scheduled-tasks.css +123 -0
- package/lib/public/css/sticky-notes.css +24 -4
- package/lib/public/index.html +19 -134
- package/lib/public/modules/app-loop-ui.js +4 -8
- package/lib/public/modules/app-messages.js +22 -6
- package/lib/public/modules/app-projects.js +2 -0
- package/lib/public/modules/app-rate-limit.js +8 -5
- package/lib/public/modules/autonomous-run.js +285 -0
- package/lib/public/modules/home-sidebar.js +16 -8
- package/lib/public/modules/home-surface.js +5 -0
- package/lib/public/modules/input.js +5 -4
- package/lib/public/modules/loop-interview.js +151 -0
- package/lib/public/modules/project-logs.js +2 -2
- package/lib/public/modules/scheduled-message-state.js +46 -0
- package/lib/public/modules/scheduled-task-edit-state.js +7 -0
- package/lib/public/modules/scheduled-task-engine.js +98 -0
- package/lib/public/modules/scheduled-task-form.js +122 -0
- package/lib/public/modules/scheduled-task-recurrence.js +46 -0
- package/lib/public/modules/scheduled-task-schedule-rule.js +115 -0
- package/lib/public/modules/scheduled-tasks.js +468 -0
- package/lib/public/modules/scheduler-config.js +6 -52
- package/lib/public/modules/scheduler.js +9 -21
- package/lib/public/modules/sidebar.js +0 -11
- package/lib/public/modules/split-view.js +2 -0
- package/lib/public/modules/sticky-notes-browser.js +1 -1
- package/lib/public/modules/sticky-notes.js +117 -4
- package/lib/public/modules/tool-palette-order.js +2 -3
- package/lib/public/modules/tools.js +5 -2
- package/lib/public/style.css +1 -0
- package/lib/record-revision.js +11 -0
- package/lib/schedule-rule.js +151 -0
- package/lib/schedule-validation.js +124 -0
- package/lib/scheduled-run-state.js +87 -0
- package/lib/scheduled-task-records.js +127 -0
- package/lib/scheduler.js +179 -196
- package/lib/sdk-bridge.js +123 -11
- package/lib/sdk-message-processor.js +3 -0
- package/lib/server-durable-scheduler.js +26 -0
- package/lib/server.js +22 -0
- package/lib/session-pair-factory.js +42 -4
- package/lib/session-pair-query-start.js +22 -0
- package/lib/session-query-tool-bridge.js +52 -0
- package/lib/session-split-groups.js +35 -1
- package/lib/sessions.js +51 -3
- package/lib/users-home-surface-preferences.js +2 -1
- package/lib/users-scheduled-task-preferences.js +44 -0
- package/lib/users.js +6 -0
- package/lib/ws-schema.js +25 -0
- package/lib/yoke/adapters/antigravity.js +1 -0
- package/lib/yoke/adapters/claude-worker.js +7 -4
- package/lib/yoke/adapters/claude.js +31 -1
- package/lib/yoke/adapters/codex.js +3 -0
- package/lib/yoke/claude-user-input.js +2 -0
- package/lib/yoke/index.js +2 -0
- package/lib/yoke/mcp-bridge-server.js +7 -1
- package/lib/yoke/session-tool-transport.js +53 -0
- package/lib/yoke/user-input.js +21 -7
- package/package.json +1 -1
- package/lib/public/modules/app-loop-wizard.js +0 -439
package/lib/project.js
CHANGED
|
@@ -35,9 +35,15 @@ var { attachFilesystem } = require("./project-filesystem");
|
|
|
35
35
|
var { attachSessions } = require("./project-sessions");
|
|
36
36
|
var { attachModels } = require("./project-models");
|
|
37
37
|
var { attachUserMessage } = require("./project-user-message");
|
|
38
|
+
var { attachLoopInterview } = require("./project-loop-interview");
|
|
39
|
+
var { attachScheduledTasks, authorizeStoredOwner } = require("./project-scheduled-tasks");
|
|
40
|
+
var { attachScheduledTaskExecution } = require("./project-scheduled-task-execution");
|
|
41
|
+
var { createFullAccessService } = require("./project-full-access");
|
|
42
|
+
var { attachAutonomousRun } = require("./project-autonomous-run");
|
|
38
43
|
var { attachShellCommand } = require("./project-shell-command");
|
|
39
44
|
var { attachVendorLogin } = require("./project-vendor-login");
|
|
40
45
|
var { attachConnection } = require("./project-connection");
|
|
46
|
+
var { attachProjectScheduledMessages } = require("./project-scheduled-messages");
|
|
41
47
|
var { attachMcp } = require("./project-mcp");
|
|
42
48
|
var { createLocalMcp } = require("./mcp-local");
|
|
43
49
|
var { attachEmail: attachEmailModule } = require("./project-email");
|
|
@@ -149,6 +155,7 @@ function validateEnvString(str) {
|
|
|
149
155
|
|
|
150
156
|
// YOKE adapter (replaces direct SDK access)
|
|
151
157
|
var yoke = require("./yoke");
|
|
158
|
+
var createSessionQueryToolBridge = require("./session-query-tool-bridge").createSessionQueryToolBridge;
|
|
152
159
|
|
|
153
160
|
// --- Shared constants ---
|
|
154
161
|
var IGNORED_DIRS = new Set(["node_modules", ".git", ".next", "__pycache__", ".cache", "dist", "build", ".clay", ".claude-relay"]);
|
|
@@ -210,7 +217,14 @@ function createProjectContext(opts) {
|
|
|
210
217
|
var moveScheduleToProject = opts.moveScheduleToProject || function () { return { ok: false, error: "Not supported" }; };
|
|
211
218
|
var moveAllSchedulesToProject = opts.moveAllSchedulesToProject || function () { return { ok: false, error: "Not supported" }; };
|
|
212
219
|
var getScheduleCount = opts.getScheduleCount || function () { return 0; };
|
|
213
|
-
var
|
|
220
|
+
var notifyProcessingChanged = opts.onProcessingChanged || function () {};
|
|
221
|
+
var _scheduledMessages = null;
|
|
222
|
+
var _scheduledTasks = null;
|
|
223
|
+
var _scheduledTaskExecution = null;
|
|
224
|
+
function onProcessingChanged() {
|
|
225
|
+
notifyProcessingChanged();
|
|
226
|
+
if (_scheduledMessages) _scheduledMessages.notify();
|
|
227
|
+
}
|
|
214
228
|
var onSessionDone = opts.onSessionDone || function () {};
|
|
215
229
|
var onPresenceChange = opts.onPresenceChange || function () {};
|
|
216
230
|
var updateChannel = opts.updateChannel || "stable";
|
|
@@ -589,6 +603,8 @@ function createProjectContext(opts) {
|
|
|
589
603
|
sm.defaultVendor = defaultVendor;
|
|
590
604
|
|
|
591
605
|
var sdk = null;
|
|
606
|
+
var _autonomousRun = null;
|
|
607
|
+
var _fullAccess = createFullAccessService({ sm: sm });
|
|
592
608
|
var _splitGroups = attachSplitGroups({
|
|
593
609
|
sm: sm,
|
|
594
610
|
clients: clients,
|
|
@@ -749,6 +765,10 @@ function createProjectContext(opts) {
|
|
|
749
765
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
750
766
|
onProcessingChanged: onProcessingChanged,
|
|
751
767
|
adapters: adapters,
|
|
768
|
+
onPartnerResult: function (driver, worker, token) {
|
|
769
|
+
if (_scheduledTaskExecution) _scheduledTaskExecution.onPartnerResult(driver, worker, token);
|
|
770
|
+
if (_autonomousRun) _autonomousRun.onPartnerResult(driver, worker, token);
|
|
771
|
+
},
|
|
752
772
|
});
|
|
753
773
|
var _sessionSpawn = attachSessionSpawn({
|
|
754
774
|
cwd: cwd,
|
|
@@ -1137,17 +1157,28 @@ function createProjectContext(opts) {
|
|
|
1137
1157
|
getWorkerPermissionRouter: function () {
|
|
1138
1158
|
return isMate ? null : _sessionPair.workerPermission;
|
|
1139
1159
|
},
|
|
1160
|
+
isDriverOperatedSession: function (session) {
|
|
1161
|
+
return !isMate && _sessionPair.workerPermission.isDriverOperated(session);
|
|
1162
|
+
},
|
|
1140
1163
|
onProcessingChanged: onProcessingChanged,
|
|
1164
|
+
onSessionAvailable: function () { if (_scheduledMessages) _scheduledMessages.notify(); },
|
|
1141
1165
|
onTurnDone: function (session, preview) {
|
|
1142
1166
|
if (isMate) digestDmTurn(session, preview);
|
|
1143
1167
|
else _sessionPair.handleTurnDone(session);
|
|
1168
|
+
if (_scheduledTaskExecution) _scheduledTaskExecution.onTurnDone(session);
|
|
1169
|
+
if (_autonomousRun) _autonomousRun.onTurnDone(session);
|
|
1144
1170
|
if (session && typeof session.onTurnDone === "function") session.onTurnDone(session, preview);
|
|
1145
1171
|
},
|
|
1172
|
+
onRateLimitRejected: function (session, resetsAt) {
|
|
1173
|
+
if (_autonomousRun) _autonomousRun.onRateLimit(session, resetsAt);
|
|
1174
|
+
},
|
|
1146
1175
|
scheduleMessage: function (session, text, resetsAt) {
|
|
1147
|
-
|
|
1176
|
+
var owner = session && session.ownerId ? usersModule.findUserById(session.ownerId) : null;
|
|
1177
|
+
scheduleMessage(session, text, resetsAt, owner, null);
|
|
1148
1178
|
},
|
|
1149
1179
|
saveImageFile: saveImageFile,
|
|
1150
1180
|
getAutoContinueSetting: function (session) {
|
|
1181
|
+
if (session && session.autonomousRun && ["armed", "running", "reviewing", "waiting-worker", "waiting-user", "paused"].indexOf(session.autonomousRun.state) !== -1) return false;
|
|
1151
1182
|
// Per-user setting in multi-user mode
|
|
1152
1183
|
if (usersModule.isMultiUser() && session && session.ownerId) {
|
|
1153
1184
|
return usersModule.getAutoContinue(session.ownerId);
|
|
@@ -1167,7 +1198,9 @@ function createProjectContext(opts) {
|
|
|
1167
1198
|
_sessionDocument.getSystemPrompt(session),
|
|
1168
1199
|
_capsuleCatalog.getSystemPrompt(session),
|
|
1169
1200
|
_projectLogs.getSystemPrompt(session),
|
|
1201
|
+
_scheduledTasks ? _scheduledTasks.getSystemPrompt(session) : "",
|
|
1170
1202
|
_mateKnowledge.getSystemPrompt(session),
|
|
1203
|
+
_autonomousRun ? _autonomousRun.getSystemPrompt(session) : "",
|
|
1171
1204
|
]);
|
|
1172
1205
|
},
|
|
1173
1206
|
getRuntimeEnv: getRuntimeEnvForSession,
|
|
@@ -1184,7 +1217,81 @@ function createProjectContext(opts) {
|
|
|
1184
1217
|
.concat(_workspaceQuery.getDynamicToolDefs(session))
|
|
1185
1218
|
.concat(_workspaceQuery.getHistoryDynamicToolDefs(session))
|
|
1186
1219
|
.concat(_projectLogs.getDynamicToolDefs(session))
|
|
1187
|
-
.concat(_mateKnowledge.getDynamicToolDefs(session))
|
|
1220
|
+
.concat(_mateKnowledge.getDynamicToolDefs(session))
|
|
1221
|
+
.concat(_loopInterview ? _loopInterview.getToolDefs(session) : [])
|
|
1222
|
+
.concat(_scheduledTasks ? _scheduledTasks.getToolDefs(session) : [])
|
|
1223
|
+
.concat(_scheduledTaskExecution ? _scheduledTaskExecution.getToolDefs(session) : [])
|
|
1224
|
+
.concat(_autonomousRun ? _autonomousRun.getToolDefs(session) : []);
|
|
1225
|
+
},
|
|
1226
|
+
canUseSessionTools: function (session) {
|
|
1227
|
+
if (!session || sm.sessions.get(session.localId) !== session) return false;
|
|
1228
|
+
if (!usersModule.isMultiUser()) return true;
|
|
1229
|
+
if (!session.ownerId) return false;
|
|
1230
|
+
var owner = usersModule.findUserById(session.ownerId);
|
|
1231
|
+
if (!owner) return false;
|
|
1232
|
+
var access = opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
1233
|
+
if (!usersModule.canAccessSession(session.ownerId, session, access)) return false;
|
|
1234
|
+
return !osUsers || !!getLinuxUserForSession(session);
|
|
1235
|
+
},
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
_autonomousRun = attachAutonomousRun({
|
|
1239
|
+
sm: sm,
|
|
1240
|
+
isMate: isMate,
|
|
1241
|
+
sendTo: sendTo,
|
|
1242
|
+
fullAccess: _fullAccess,
|
|
1243
|
+
getSdk: function () { return sdk; },
|
|
1244
|
+
getSessionForWs: getSessionForWs,
|
|
1245
|
+
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
1246
|
+
onProcessingChanged: onProcessingChanged,
|
|
1247
|
+
isDriverOperatedSession: function (session) { return _sessionPair.workerPermission.isDriverOperated(session); },
|
|
1248
|
+
canAccess: function (ws, session) {
|
|
1249
|
+
return !usersModule.isMultiUser() || !ws._clayUser || usersModule.canAccessSession(ws._clayUser.id, session, { visibility: "public" });
|
|
1250
|
+
},
|
|
1251
|
+
stopPair: function (session) { return _sessionPair.stopAutonomousWork(session); },
|
|
1252
|
+
stopBarrier: function (session) { return _sessionPair.stopBarrier(session); },
|
|
1253
|
+
durableScheduler: opts.durableScheduler,
|
|
1254
|
+
projectSlug: slug,
|
|
1255
|
+
isMultiUser: function () { return usersModule.isMultiUser(); },
|
|
1256
|
+
authorizeSession: function (session) {
|
|
1257
|
+
if (!session || sm.sessions.get(session.localId) !== session) return false;
|
|
1258
|
+
if (!usersModule.isMultiUser()) return !session.ownerId;
|
|
1259
|
+
var owner = session.ownerId && usersModule.findUserById(session.ownerId);
|
|
1260
|
+
if (!owner) return false;
|
|
1261
|
+
var access = opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
1262
|
+
if (!usersModule.canAccessSession(owner.id, session, access)) return false;
|
|
1263
|
+
return !osUsers || !!getLinuxUserForSession(session);
|
|
1264
|
+
},
|
|
1265
|
+
});
|
|
1266
|
+
var _loopInterview = attachLoopInterview({
|
|
1267
|
+
sm: sm, sendTo: sendTo, sendToSession: sendToSession, sdk: sdk, autonomousRun: _autonomousRun, isMate: isMate,
|
|
1268
|
+
getSessionForWs: getSessionForWs,
|
|
1269
|
+
onProcessingChanged: onProcessingChanged, ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
1270
|
+
canAccess: function (ws, session) {
|
|
1271
|
+
return !usersModule.isMultiUser() || !ws._clayUser || usersModule.canAccessSession(ws._clayUser.id, session, { visibility: "public" });
|
|
1272
|
+
},
|
|
1273
|
+
isDriverOperatedSession: function (session) { return !isMate && _sessionPair.workerPermission.isDriverOperated(session); },
|
|
1274
|
+
});
|
|
1275
|
+
|
|
1276
|
+
_scheduledMessages = attachProjectScheduledMessages({
|
|
1277
|
+
scheduler: opts.durableScheduler,
|
|
1278
|
+
slug: slug,
|
|
1279
|
+
isMate: isMate,
|
|
1280
|
+
osUsers: osUsers,
|
|
1281
|
+
sm: sm,
|
|
1282
|
+
sdk: sdk,
|
|
1283
|
+
usersModule: usersModule,
|
|
1284
|
+
sendTo: sendTo,
|
|
1285
|
+
sendToSession: sendToSession,
|
|
1286
|
+
onProcessingChanged: onProcessingChanged,
|
|
1287
|
+
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
1288
|
+
getProjectAccess: function () {
|
|
1289
|
+
if (isMate) return { visibility: "private", ownerId: projectOwnerId || null, allowedUsers: [] };
|
|
1290
|
+
return opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
1291
|
+
},
|
|
1292
|
+
canAccessProjectSlug: opts.canAccessProjectSlug || function () { return !usersModule.isMultiUser(); },
|
|
1293
|
+
isDriverOperatedSession: function (session) {
|
|
1294
|
+
return !isMate && _sessionPair.workerPermission.isDriverOperated(session);
|
|
1188
1295
|
},
|
|
1189
1296
|
});
|
|
1190
1297
|
|
|
@@ -1202,8 +1309,39 @@ function createProjectContext(opts) {
|
|
|
1202
1309
|
sendToSession: sendToSession,
|
|
1203
1310
|
pushModule: pushModule,
|
|
1204
1311
|
notificationsModule: _notifications,
|
|
1312
|
+
durableScheduler: opts.durableScheduler,
|
|
1313
|
+
isMultiUser: function () { return usersModule.isMultiUser(); },
|
|
1314
|
+
requiresLinuxUser: function () { return osUsers; },
|
|
1205
1315
|
getHubSchedules: getHubSchedules,
|
|
1206
1316
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
1317
|
+
getScheduleActor: function (ws) {
|
|
1318
|
+
var scheduleSession = getSessionForWs(ws);
|
|
1319
|
+
var scheduleUser = ws && ws._clayUser ? usersModule.findUserById(ws._clayUser.id) : null;
|
|
1320
|
+
if (usersModule.isMultiUser() && (!scheduleSession || !scheduleUser || scheduleSession.ownerId !== scheduleUser.id)) return null;
|
|
1321
|
+
return {
|
|
1322
|
+
ownerId: scheduleUser && scheduleUser.id || null,
|
|
1323
|
+
ownerName: scheduleUser && (scheduleUser.displayName || scheduleUser.username) || null,
|
|
1324
|
+
sessionId: scheduleSession && scheduleSession.localId || null,
|
|
1325
|
+
};
|
|
1326
|
+
},
|
|
1327
|
+
authorizeScheduledRun: function (record) {
|
|
1328
|
+
return authorizeStoredOwner(record, {
|
|
1329
|
+
usersModule: usersModule,
|
|
1330
|
+
osUsers: osUsers,
|
|
1331
|
+
projectAccess: opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null },
|
|
1332
|
+
resolveLinuxUser: getOsUserInfoForLinuxUser,
|
|
1333
|
+
grantProjectAccess: function (linuxUser) { grantProjectAccess(cwd, linuxUser); },
|
|
1334
|
+
});
|
|
1335
|
+
},
|
|
1336
|
+
prepareScheduledTask: function (record, source) {
|
|
1337
|
+
return _scheduledTaskExecution ? _scheduledTaskExecution.prepare(record, source) : { ok: false, error: "Scheduled execution is not ready." };
|
|
1338
|
+
},
|
|
1339
|
+
executeScheduledTask: function (record, source, prepared) {
|
|
1340
|
+
return _scheduledTaskExecution ? _scheduledTaskExecution.trigger(record, source, prepared) : { ok: false, error: "Scheduled execution is not ready." };
|
|
1341
|
+
},
|
|
1342
|
+
canExecuteScheduledTask: function (record) {
|
|
1343
|
+
return !!(_scheduledTaskExecution && _scheduledTaskExecution.runnable(record).ok);
|
|
1344
|
+
},
|
|
1207
1345
|
onProcessingChanged: onProcessingChanged,
|
|
1208
1346
|
hydrateImageRefs: hydrateImageRefs,
|
|
1209
1347
|
});
|
|
@@ -1214,6 +1352,75 @@ function createProjectContext(opts) {
|
|
|
1214
1352
|
var stopLoop = _loop.stopLoop;
|
|
1215
1353
|
var resumeLoop = _loop.resumeLoop;
|
|
1216
1354
|
|
|
1355
|
+
_scheduledTaskExecution = attachScheduledTaskExecution({
|
|
1356
|
+
cwd: cwd, sm: sm, registry: loopRegistry, sessionPair: _sessionPair,
|
|
1357
|
+
getSdk: function () { return sdk; }, getLinuxUserForSession: getLinuxUserForSession,
|
|
1358
|
+
requiresLinuxUser: function () { return osUsers; },
|
|
1359
|
+
onProcessingChanged: onProcessingChanged,
|
|
1360
|
+
authorize: function (record) {
|
|
1361
|
+
return authorizeStoredOwner(record, {
|
|
1362
|
+
usersModule: usersModule, osUsers: osUsers,
|
|
1363
|
+
projectAccess: opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null },
|
|
1364
|
+
resolveLinuxUser: getOsUserInfoForLinuxUser,
|
|
1365
|
+
grantProjectAccess: function (linuxUser) { grantProjectAccess(cwd, linuxUser); },
|
|
1366
|
+
});
|
|
1367
|
+
},
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
_scheduledTasks = attachScheduledTasks({
|
|
1371
|
+
cwd: cwd,
|
|
1372
|
+
projectSlug: slug,
|
|
1373
|
+
projectTitle: title || project,
|
|
1374
|
+
isMate: isMate,
|
|
1375
|
+
sm: sm,
|
|
1376
|
+
sdk: sdk,
|
|
1377
|
+
registry: loopRegistry,
|
|
1378
|
+
usersModule: usersModule,
|
|
1379
|
+
sendTo: sendTo,
|
|
1380
|
+
sendToSession: sendToSession,
|
|
1381
|
+
getSessionForWs: getSessionForWs,
|
|
1382
|
+
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
1383
|
+
onProcessingChanged: onProcessingChanged,
|
|
1384
|
+
isDriverOperatedSession: function (session) { return !isMate && _sessionPair.workerPermission.isDriverOperated(session); },
|
|
1385
|
+
canUseSession: function (session) {
|
|
1386
|
+
if (!session || sm.sessions.get(session.localId) !== session) return false;
|
|
1387
|
+
if (!usersModule.isMultiUser()) return !session.ownerId;
|
|
1388
|
+
if (!session.ownerId) return false;
|
|
1389
|
+
var sessionOwner = usersModule.findUserById(session.ownerId);
|
|
1390
|
+
if (!sessionOwner || !usersModule.getEffectivePermissions(sessionOwner, osUsers).scheduledTasks) return false;
|
|
1391
|
+
var access = opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
1392
|
+
if (!usersModule.canAccessSession(session.ownerId, session, access)) return false;
|
|
1393
|
+
return !osUsers || !!getLinuxUserForSession(session);
|
|
1394
|
+
},
|
|
1395
|
+
canAccessRecord: function (session, record) {
|
|
1396
|
+
if (!usersModule.isMultiUser()) return !record.ownerId;
|
|
1397
|
+
if (record.ownerId) return record.ownerId === session.ownerId;
|
|
1398
|
+
var user = session && session.ownerId ? usersModule.findUserById(session.ownerId) : null;
|
|
1399
|
+
var access = opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
1400
|
+
return !!(user && (user.role === "admin" || access.ownerId === session.ownerId));
|
|
1401
|
+
},
|
|
1402
|
+
canClaimOwner: function (session) {
|
|
1403
|
+
if (!usersModule.isMultiUser() || !session || !session.ownerId) return false;
|
|
1404
|
+
var user = usersModule.findUserById(session.ownerId);
|
|
1405
|
+
var access = opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
1406
|
+
return !!(user && (user.role === "admin" || access.ownerId === session.ownerId));
|
|
1407
|
+
},
|
|
1408
|
+
canAccess: function (ws, session) {
|
|
1409
|
+
return !usersModule.isMultiUser() || !ws._clayUser || usersModule.canAccessSession(ws._clayUser.id, session, { visibility: "public" });
|
|
1410
|
+
},
|
|
1411
|
+
hasPermission: function (ws) {
|
|
1412
|
+
if (!ws._clayUser) return true;
|
|
1413
|
+
return !!usersModule.getEffectivePermissions(ws._clayUser, osUsers).scheduledTasks;
|
|
1414
|
+
},
|
|
1415
|
+
getEngineCatalog: function (ws, vendor) { return _models.getVendorCatalog(ws, vendor); },
|
|
1416
|
+
scheduledExecution: _scheduledTaskExecution,
|
|
1417
|
+
preflightRuntime: _sessionPair.preflightRuntime,
|
|
1418
|
+
resolveOwnerName: function (ownerId) {
|
|
1419
|
+
var user = ownerId ? usersModule.findUserById(ownerId) : null;
|
|
1420
|
+
return user && (user.displayName || user.username) || null;
|
|
1421
|
+
},
|
|
1422
|
+
});
|
|
1423
|
+
|
|
1217
1424
|
// Mate CLAUDE.md crisis safety watcher
|
|
1218
1425
|
var crisisWatcher = null;
|
|
1219
1426
|
var crisisDebounce = null;
|
|
@@ -1270,51 +1477,16 @@ function createProjectContext(opts) {
|
|
|
1270
1477
|
}
|
|
1271
1478
|
|
|
1272
1479
|
// --- Schedule / cancel a message (used by WS handler and auto-continue) ---
|
|
1273
|
-
function scheduleMessage(session, text, resetsAt) {
|
|
1274
|
-
|
|
1275
|
-
// Cancel any existing scheduled message
|
|
1276
|
-
if (session.scheduledMessage && session.scheduledMessage.timer) {
|
|
1277
|
-
clearTimeout(session.scheduledMessage.timer);
|
|
1278
|
-
}
|
|
1279
|
-
var isPastReset = resetsAt <= Date.now();
|
|
1280
|
-
var schedDelay = isPastReset ? 5000 : Math.max(0, resetsAt - Date.now()) + 60000; // +1min buffer after reset, or 5s for immediate
|
|
1281
|
-
var sendsAt = Date.now() + schedDelay;
|
|
1282
|
-
var schedEntry = {
|
|
1283
|
-
type: "scheduled_message_queued",
|
|
1284
|
-
text: text,
|
|
1285
|
-
resetsAt: sendsAt,
|
|
1286
|
-
scheduledAt: Date.now(),
|
|
1287
|
-
};
|
|
1288
|
-
sm.sendAndRecord(session, schedEntry);
|
|
1289
|
-
session.scheduledMessage = {
|
|
1290
|
-
text: text,
|
|
1291
|
-
resetsAt: resetsAt,
|
|
1292
|
-
timer: setTimeout(function () {
|
|
1293
|
-
session.scheduledMessage = null;
|
|
1294
|
-
if (session.destroying) return;
|
|
1295
|
-
console.log("[project] Scheduled message firing for session " + session.localId);
|
|
1296
|
-
sm.sendAndRecord(session, { type: "scheduled_message_sent" });
|
|
1297
|
-
var schedUserMsg = { type: "user_message", text: text, _ts: Date.now() };
|
|
1298
|
-
session.history.push(schedUserMsg);
|
|
1299
|
-
sm.appendToSessionFile(session, schedUserMsg);
|
|
1300
|
-
sendToSession(session.localId, schedUserMsg);
|
|
1301
|
-
session.isProcessing = true;
|
|
1302
|
-
onProcessingChanged();
|
|
1303
|
-
sendToSession(session.localId, { type: "status", status: "processing" });
|
|
1304
|
-
sdk.startQuery(session, text, null, ensureProjectAccessForSession(session));
|
|
1305
|
-
sm.broadcastSessionList();
|
|
1306
|
-
}, schedDelay),
|
|
1307
|
-
};
|
|
1480
|
+
function scheduleMessage(session, text, resetsAt, actorUser, targetWs) {
|
|
1481
|
+
return _scheduledMessages ? _scheduledMessages.schedule(session, text, resetsAt, actorUser, targetWs) : null;
|
|
1308
1482
|
}
|
|
1309
1483
|
|
|
1310
|
-
function cancelScheduledMessage(session) {
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
sm.sendAndRecord(session, { type: "scheduled_message_cancelled" });
|
|
1317
|
-
}
|
|
1484
|
+
function cancelScheduledMessage(session, actorUser, targetWs, correlation) {
|
|
1485
|
+
return _scheduledMessages ? _scheduledMessages.cancel(session, actorUser, targetWs, null, correlation) : false;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
function sendScheduledMessageNow(session, actorUser, targetWs, correlation) {
|
|
1489
|
+
return _scheduledMessages ? _scheduledMessages.sendNow(session, actorUser, targetWs, correlation) : false;
|
|
1318
1490
|
}
|
|
1319
1491
|
|
|
1320
1492
|
function handleMessage(ws, msg) {
|
|
@@ -1442,6 +1614,9 @@ function createProjectContext(opts) {
|
|
|
1442
1614
|
if (_sessionHandoff.handleMessage(ws, msg)) return;
|
|
1443
1615
|
if (_splitGroups.handleMessage(ws, msg)) return;
|
|
1444
1616
|
if (_models.handleMessage(ws, msg)) return;
|
|
1617
|
+
if (_scheduledTasks.handleMessage(ws, msg)) return;
|
|
1618
|
+
if (_loopInterview.handleMessage(ws, msg)) return;
|
|
1619
|
+
if (_autonomousRun.handleMessage(ws, msg)) return;
|
|
1445
1620
|
if (_sessions.handleSessionsMessage(ws, msg)) return;
|
|
1446
1621
|
|
|
1447
1622
|
// --- Filesystem, settings, env (delegated to project-filesystem.js) ---
|
|
@@ -1643,7 +1818,13 @@ function createProjectContext(opts) {
|
|
|
1643
1818
|
matesModule: matesModule,
|
|
1644
1819
|
pushModule: pushModule,
|
|
1645
1820
|
getSessionForWs: getSessionForWs,
|
|
1646
|
-
|
|
1821
|
+
canCreateScheduledTaskInterview: function (ws, session) { return !!(_scheduledTasks && _scheduledTasks.canCreateInterview(ws, session)); },
|
|
1822
|
+
canStartScheduledTaskInterview: function (ws, session) { return !!(_scheduledTasks && _scheduledTasks.canStartInterview(ws, session)); },
|
|
1823
|
+
onHumanPairStop: function (session) {
|
|
1824
|
+
var stopped = _sessionPair.handleHumanStop(session);
|
|
1825
|
+
if (_scheduledTaskExecution) _scheduledTaskExecution.stopForSession(session, "The human stopped this scheduled run.");
|
|
1826
|
+
return stopped;
|
|
1827
|
+
},
|
|
1647
1828
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
1648
1829
|
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
1649
1830
|
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
@@ -1651,6 +1832,8 @@ function createProjectContext(opts) {
|
|
|
1651
1832
|
onProcessingChanged: onProcessingChanged,
|
|
1652
1833
|
broadcastPresence: broadcastPresence,
|
|
1653
1834
|
adapter: adapter,
|
|
1835
|
+
fullAccessService: _fullAccess,
|
|
1836
|
+
autonomousRun: _autonomousRun,
|
|
1654
1837
|
getProjectList: getProjectList,
|
|
1655
1838
|
getProjectCount: getProjectCount,
|
|
1656
1839
|
getScheduleCount: getScheduleCount,
|
|
@@ -1661,6 +1844,7 @@ function createProjectContext(opts) {
|
|
|
1661
1844
|
isNewer: isNewer,
|
|
1662
1845
|
scheduleMessage: scheduleMessage,
|
|
1663
1846
|
cancelScheduledMessage: cancelScheduledMessage,
|
|
1847
|
+
sendScheduledMessageNow: sendScheduledMessageNow,
|
|
1664
1848
|
getProjectOwnerId: function () { return projectOwnerId; },
|
|
1665
1849
|
setProjectOwnerId: function (id) { projectOwnerId = id; },
|
|
1666
1850
|
getUpdateChannel: function () { return updateChannel; },
|
|
@@ -1730,6 +1914,7 @@ function createProjectContext(opts) {
|
|
|
1730
1914
|
return _sessionPair.workerPermission.isDriverOperated(session);
|
|
1731
1915
|
},
|
|
1732
1916
|
beginHumanPairTurn: function (session) { return _sessionPair.beginHumanTurn(session); },
|
|
1917
|
+
autonomousRun: _autonomousRun,
|
|
1733
1918
|
cwd: cwd,
|
|
1734
1919
|
slug: slug,
|
|
1735
1920
|
isMate: isMate,
|
|
@@ -1827,8 +2012,9 @@ function createProjectContext(opts) {
|
|
|
1827
2012
|
// Provides list_tools and call_tool operations over HTTP for mcp-bridge-server.js.
|
|
1828
2013
|
// The normal Codex bridge excludes local MCP servers it manages natively;
|
|
1829
2014
|
// Kiro's session-only bridge exposes only tools bound to its Clay session.
|
|
1830
|
-
function getMcpBridgeHandler(sessionId, sessionOnly) {
|
|
2015
|
+
function getMcpBridgeHandler(sessionId, sessionOnly, queryGeneration) {
|
|
1831
2016
|
var boundSession = Number.isInteger(sessionId) ? sm.sessions.get(sessionId) : null;
|
|
2017
|
+
var queryToolBridge = createSessionQueryToolBridge({ session: boundSession, sdk: sdk });
|
|
1832
2018
|
// Build set of local MCP server names to exclude (Codex handles these natively)
|
|
1833
2019
|
var localMcpNames = {};
|
|
1834
2020
|
try {
|
|
@@ -1875,6 +2061,8 @@ function createProjectContext(opts) {
|
|
|
1875
2061
|
}
|
|
1876
2062
|
|
|
1877
2063
|
if (boundSession) {
|
|
2064
|
+
var queryTools = queryToolBridge.listTools(queryGeneration);
|
|
2065
|
+
for (var qti = 0; qti < queryTools.length; qti++) tools.push(queryTools[qti]);
|
|
1878
2066
|
var pairTools = _sessionPair.getToolDefs(boundSession);
|
|
1879
2067
|
for (var pti = 0; pti < pairTools.length; pti++) {
|
|
1880
2068
|
tools.push({
|
|
@@ -1923,6 +2111,14 @@ function createProjectContext(opts) {
|
|
|
1923
2111
|
for (var plti = 0; plti < logsTools.length; plti++) tools.push(logsTools[plti]);
|
|
1924
2112
|
var knowledgeTools = _mateKnowledge.getBridgeTools(boundSession, normalizeToolSchema);
|
|
1925
2113
|
for (var mkti = 0; mkti < knowledgeTools.length; mkti++) tools.push(knowledgeTools[mkti]);
|
|
2114
|
+
var interviewTools = _loopInterview ? _loopInterview.getToolDefs(boundSession) : [];
|
|
2115
|
+
for (var liti = 0; liti < interviewTools.length; liti++) {
|
|
2116
|
+
tools.push({ server: "clay-until-complete", name: interviewTools[liti].name, description: interviewTools[liti].description, inputSchema: normalizeToolSchema(interviewTools[liti].inputSchema) });
|
|
2117
|
+
}
|
|
2118
|
+
var autonomousTools = _autonomousRun ? _autonomousRun.getToolDefs(boundSession) : [];
|
|
2119
|
+
for (var ati = 0; ati < autonomousTools.length; ati++) {
|
|
2120
|
+
tools.push({ server: "clay-until-complete", name: autonomousTools[ati].name, description: autonomousTools[ati].description, inputSchema: normalizeToolSchema(autonomousTools[ati].inputSchema) });
|
|
2121
|
+
}
|
|
1926
2122
|
}
|
|
1927
2123
|
|
|
1928
2124
|
if (sessionOnly) return Promise.resolve(tools);
|
|
@@ -1957,6 +2153,8 @@ function createProjectContext(opts) {
|
|
|
1957
2153
|
return Promise.resolve(tools);
|
|
1958
2154
|
},
|
|
1959
2155
|
callTool: function (serverName, toolName, args) {
|
|
2156
|
+
var queryCall = queryToolBridge.callTool(queryGeneration, serverName, toolName, args);
|
|
2157
|
+
if (queryCall) return queryCall;
|
|
1960
2158
|
if (boundSession && serverName === "clay-sessions") {
|
|
1961
2159
|
var pairTools = _sessionPair.getToolDefs(boundSession);
|
|
1962
2160
|
for (var pti = 0; pti < pairTools.length; pti++) {
|
|
@@ -1989,6 +2187,16 @@ function createProjectContext(opts) {
|
|
|
1989
2187
|
}
|
|
1990
2188
|
}
|
|
1991
2189
|
}
|
|
2190
|
+
if (boundSession && serverName === "clay-until-complete") {
|
|
2191
|
+
var interviewTools = _loopInterview ? _loopInterview.getToolDefs(boundSession) : [];
|
|
2192
|
+
for (var iti = 0; iti < interviewTools.length; iti++) {
|
|
2193
|
+
if (interviewTools[iti].name === toolName && typeof interviewTools[iti].handler === "function") return Promise.resolve(interviewTools[iti].handler(args || {}));
|
|
2194
|
+
}
|
|
2195
|
+
var autonomousTools = _autonomousRun ? _autonomousRun.getToolDefs(boundSession) : [];
|
|
2196
|
+
for (var ati = 0; ati < autonomousTools.length; ati++) {
|
|
2197
|
+
if (autonomousTools[ati].name === toolName && typeof autonomousTools[ati].handler === "function") return Promise.resolve(autonomousTools[ati].handler(args || {}));
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
1992
2200
|
if (boundSession && serverName === "clay-debate") {
|
|
1993
2201
|
return _debateProposal.callBridgeTool(boundSession, toolName, args);
|
|
1994
2202
|
}
|
|
@@ -2082,6 +2290,7 @@ function createProjectContext(opts) {
|
|
|
2082
2290
|
_notifications: _notifications,
|
|
2083
2291
|
_splitGroups: _splitGroups,
|
|
2084
2292
|
_vendorLogin: _vendorLogin,
|
|
2293
|
+
autonomousRun: _autonomousRun,
|
|
2085
2294
|
resolveSessionForView: _sessions.resolveSessionForView,
|
|
2086
2295
|
hydrateImageRefs: hydrateImageRefs,
|
|
2087
2296
|
broadcastClientCount: broadcastClientCount,
|
|
@@ -2092,6 +2301,7 @@ function createProjectContext(opts) {
|
|
|
2092
2301
|
saveContextSources: saveContextSources,
|
|
2093
2302
|
_email: _email,
|
|
2094
2303
|
restoreDebateState: restoreDebateState,
|
|
2304
|
+
scheduledMessages: _scheduledMessages,
|
|
2095
2305
|
stopFileWatch: stopFileWatch,
|
|
2096
2306
|
stopAllDirWatches: stopAllDirWatches,
|
|
2097
2307
|
getProjectOwnerId: function () { return projectOwnerId; },
|
|
@@ -2119,6 +2329,8 @@ function createProjectContext(opts) {
|
|
|
2119
2329
|
|
|
2120
2330
|
// --- Destroy ---
|
|
2121
2331
|
function destroy() {
|
|
2332
|
+
if (_scheduledMessages) _scheduledMessages.shutdown();
|
|
2333
|
+
if (_autonomousRun) _autonomousRun.shutdown();
|
|
2122
2334
|
_loop.stopTimer();
|
|
2123
2335
|
_email.destroy();
|
|
2124
2336
|
stopFileWatch();
|
|
@@ -2130,10 +2342,6 @@ function createProjectContext(opts) {
|
|
|
2130
2342
|
clearTimeout(session.autoContinueTimer);
|
|
2131
2343
|
session.autoContinueTimer = null;
|
|
2132
2344
|
}
|
|
2133
|
-
if (session.scheduledMessage && session.scheduledMessage.timer) {
|
|
2134
|
-
clearTimeout(session.scheduledMessage.timer);
|
|
2135
|
-
session.scheduledMessage = null;
|
|
2136
|
-
}
|
|
2137
2345
|
if (session.abortController) {
|
|
2138
2346
|
try { session.abortController.abort(); } catch (e) {}
|
|
2139
2347
|
}
|