clay-server 5.2.0-beta.3 → 5.2.0-beta.5
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/account-auth-socket.js +1 -0
- package/lib/builtin-mates.js +19 -16
- package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +28 -0
- package/lib/clay-mate-chat-receipts.js +26 -0
- package/lib/clay-mate-chat.js +87 -0
- package/lib/clay-mate-knowledge-input.js +26 -0
- package/lib/clay-mate-knowledge.js +95 -0
- package/lib/clay-mate-lifecycle.js +95 -0
- package/lib/clay-product-control-input.js +33 -0
- package/lib/clay-product-control-tools.js +51 -0
- package/lib/clay-product-control.js +237 -0
- package/lib/clay-project-lifecycle.js +154 -0
- package/lib/clay-project-record-input.js +44 -0
- package/lib/clay-project-records.js +83 -0
- package/lib/clay-scheduling-input.js +21 -0
- package/lib/clay-scheduling-receipts.js +26 -0
- package/lib/clay-scheduling.js +119 -0
- package/lib/clay-screen-controls.js +96 -0
- package/lib/clay-workspace-controls.js +83 -0
- package/lib/clay-workspace-input.js +17 -0
- package/lib/clay-workspace-receipts.js +26 -0
- package/lib/daemon-project-access.js +11 -0
- package/lib/daemon-project-lifecycle-callbacks.js +15 -0
- package/lib/daemon-project-lifecycle.js +262 -0
- package/lib/daemon-projects.js +1 -1
- package/lib/daemon.js +73 -221
- package/lib/issues-service.js +29 -15
- package/lib/knowledge-db-import.js +5 -4
- package/lib/knowledge-db-service.js +9 -6
- package/lib/knowledge-document-index.js +2 -1
- package/lib/knowledge-file-store.js +7 -1
- package/lib/knowledge-product-operations.js +46 -0
- package/lib/mate-avatar-catalog.js +12 -0
- package/lib/mate-avatar-migration.js +41 -0
- package/lib/mate-creation-mcp-server.js +2 -0
- package/lib/mate-knowledge-canonical-access.js +10 -0
- package/lib/mate-knowledge-service.js +7 -4
- package/lib/mate-lifecycle-service.js +94 -0
- package/lib/mate-message-delivery.js +43 -0
- package/lib/mate-ready-creation.js +9 -1
- package/lib/mate-schedule-input.js +29 -0
- package/lib/mate-schedule-lifecycle.js +151 -0
- package/lib/mate-scheduling.js +103 -0
- package/lib/mates.js +18 -6
- package/lib/mcp-agent-tools.js +117 -0
- package/lib/mcp-connection-store.js +119 -15
- package/lib/mcp-import-credentials.js +31 -0
- package/lib/mcp-local-transport.js +13 -0
- package/lib/mcp-oauth.js +8 -6
- package/lib/mcp-query-bridge.js +30 -0
- package/lib/mcp-remote-connections.js +74 -20
- package/lib/mcp-source-adapters.js +91 -0
- package/lib/mcp-source-context.js +42 -0
- package/lib/mcp-source-discovery.js +169 -0
- package/lib/mcp-source-plugins.js +68 -0
- package/lib/mcp-source-restrictions.js +47 -0
- package/lib/mcp-tool-policy.js +34 -0
- package/lib/notes-checklist.js +50 -0
- package/lib/notes.js +49 -3
- package/lib/os-users.js +20 -5
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +8 -4
- package/lib/project-debate.js +1 -0
- package/lib/project-delegated-follow-up.js +2 -1
- package/lib/project-directory-claim.js +65 -0
- package/lib/project-file-operations.js +61 -0
- package/lib/project-filesystem.js +13 -87
- package/lib/project-full-access.js +23 -2
- package/lib/project-knowledge.js +32 -18
- package/lib/project-lifecycle-operations.js +98 -0
- package/lib/project-lifecycle-process-witness.js +32 -0
- package/lib/project-lifecycle-runtime.js +50 -0
- package/lib/project-linux-access.js +22 -0
- package/lib/project-logs-canonical-clay.js +27 -0
- package/lib/project-logs-clay-query.js +16 -0
- package/lib/project-logs-schema.js +4 -2
- package/lib/project-logs-service.js +8 -7
- package/lib/project-logs.js +1 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-mate-chat-control.js +55 -0
- package/lib/project-mate-creation-proposal.js +18 -3
- package/lib/project-mate-interaction.js +8 -0
- package/lib/project-mcp.js +54 -16
- package/lib/project-models.js +14 -31
- package/lib/project-notifications.js +74 -16
- package/lib/project-ownership.js +77 -0
- package/lib/project-pair-result-delivery.js +14 -3
- package/lib/project-pending-message-queue.js +1 -0
- package/lib/project-product-control.js +87 -0
- package/lib/project-product-session-queue.js +46 -0
- package/lib/project-push-access.js +28 -0
- package/lib/project-scheduled-message-queue.js +30 -0
- package/lib/project-scheduled-messages.js +63 -64
- package/lib/project-scheduled-task-control.js +83 -0
- package/lib/project-scheduled-tasks.js +13 -2
- package/lib/project-scheduling-access.js +10 -0
- package/lib/project-session-actions.js +65 -0
- package/lib/project-session-delete.js +8 -1
- package/lib/project-session-document.js +8 -3
- package/lib/project-session-github.js +63 -19
- package/lib/project-session-history-actions.js +165 -0
- package/lib/project-session-linear.js +14 -6
- package/lib/project-session-notes.js +7 -3
- package/lib/project-session-runtime-actions.js +63 -0
- package/lib/project-session-vendor.js +54 -0
- package/lib/project-sessions.js +68 -241
- package/lib/project-shared-browser.js +56 -12
- package/lib/project-user-message.js +30 -1
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +9 -2
- package/lib/project.js +144 -37
- package/lib/public/app.js +5 -0
- package/lib/public/appearance-bootstrap.js +14 -0
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/clay-workspace.css +29 -0
- package/lib/public/css/home-debate-planning.css +2 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/mate-avatar-gallery.css +12 -0
- package/lib/public/css/mate-conversation.css +10 -5
- package/lib/public/css/overlays.css +4 -2
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +46 -1
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/css/sticky-notes.css +61 -1
- package/lib/public/index.html +11 -5
- package/lib/public/mate-avatars/B01.png +0 -0
- package/lib/public/mate-avatars/B02.png +0 -0
- package/lib/public/mate-avatars/B03.png +0 -0
- package/lib/public/mate-avatars/B04.png +0 -0
- package/lib/public/mate-avatars/B05.png +0 -0
- package/lib/public/mate-avatars/B06.png +0 -0
- package/lib/public/mate-avatars/B07.png +0 -0
- package/lib/public/mate-avatars/B08.png +0 -0
- package/lib/public/mate-avatars/B09.png +0 -0
- package/lib/public/mate-avatars/B10.png +0 -0
- package/lib/public/mate-avatars/B11.png +0 -0
- package/lib/public/mate-avatars/B12.png +0 -0
- package/lib/public/mate-avatars/B13.png +0 -0
- package/lib/public/mate-avatars/B14.png +0 -0
- package/lib/public/mate-avatars/B15.png +0 -0
- package/lib/public/mate-avatars/B16.png +0 -0
- package/lib/public/mate-avatars/B17.png +0 -0
- package/lib/public/mate-avatars/B18.png +0 -0
- package/lib/public/mate-avatars/B19.png +0 -0
- package/lib/public/mate-avatars/B20.png +0 -0
- package/lib/public/mate-avatars/B21.png +0 -0
- package/lib/public/mate-avatars/B22.png +0 -0
- package/lib/public/mate-avatars/B23.png +0 -0
- package/lib/public/mate-avatars/B24.png +0 -0
- package/lib/public/mate-avatars/B25.png +0 -0
- package/lib/public/mate-avatars/B26.png +0 -0
- package/lib/public/mate-avatars/B27.png +0 -0
- package/lib/public/mate-avatars/B28.png +0 -0
- package/lib/public/mate-avatars/B29.png +0 -0
- package/lib/public/mate-avatars/B30.png +0 -0
- package/lib/public/mate-avatars/B31.png +0 -0
- package/lib/public/mate-avatars/B32.png +0 -0
- package/lib/public/mate-avatars/B33.png +0 -0
- package/lib/public/mate-avatars/B34.png +0 -0
- package/lib/public/mate-avatars/B35.png +0 -0
- package/lib/public/mate-avatars/B36.png +0 -0
- package/lib/public/mate-avatars/B37.png +0 -0
- package/lib/public/mate-avatars/B38.png +0 -0
- package/lib/public/mate-avatars/B39.png +0 -0
- package/lib/public/mate-avatars/B40.png +0 -0
- package/lib/public/mate-avatars/B41.png +0 -0
- package/lib/public/mate-avatars/B42.png +0 -0
- package/lib/public/mate-avatars/B43.png +0 -0
- package/lib/public/mate-avatars/B44.png +0 -0
- package/lib/public/mate-avatars/B45.png +0 -0
- package/lib/public/mate-avatars/B46.png +0 -0
- package/lib/public/mate-avatars/B47.png +0 -0
- package/lib/public/mate-avatars/B48.png +0 -0
- package/lib/public/mate-avatars/C01.png +0 -0
- package/lib/public/mate-avatars/C02.png +0 -0
- package/lib/public/mate-avatars/C03.png +0 -0
- package/lib/public/mate-avatars/C04.png +0 -0
- package/lib/public/mate-avatars/C05.png +0 -0
- package/lib/public/mate-avatars/C06.png +0 -0
- package/lib/public/mate-avatars/C07.png +0 -0
- package/lib/public/mate-avatars/C08.png +0 -0
- package/lib/public/mate-avatars/C09.png +0 -0
- package/lib/public/mate-avatars/C10.png +0 -0
- package/lib/public/mate-avatars/C11.png +0 -0
- package/lib/public/mate-avatars/C12.png +0 -0
- package/lib/public/mate-avatars/C13.png +0 -0
- package/lib/public/mate-avatars/C14.png +0 -0
- package/lib/public/mate-avatars/C15.png +0 -0
- package/lib/public/mate-avatars/C16.png +0 -0
- package/lib/public/mate-avatars/C17.png +0 -0
- package/lib/public/mate-avatars/C18.png +0 -0
- package/lib/public/mate-avatars/C19.png +0 -0
- package/lib/public/mate-avatars/C20.png +0 -0
- package/lib/public/mate-avatars/C21.png +0 -0
- package/lib/public/mate-avatars/C22.png +0 -0
- package/lib/public/mate-avatars/C23.png +0 -0
- package/lib/public/mate-avatars/C24.png +0 -0
- package/lib/public/mate-avatars/C25.png +0 -0
- package/lib/public/mate-avatars/C26.png +0 -0
- package/lib/public/mate-avatars/C27.png +0 -0
- package/lib/public/mate-avatars/C28.png +0 -0
- package/lib/public/mate-avatars/C29.png +0 -0
- package/lib/public/mate-avatars/C30.png +0 -0
- package/lib/public/mate-avatars/C31.png +0 -0
- package/lib/public/mate-avatars/C32.png +0 -0
- package/lib/public/mate-avatars/C33.png +0 -0
- package/lib/public/mate-avatars/C34.png +0 -0
- package/lib/public/mate-avatars/C35.png +0 -0
- package/lib/public/mate-avatars/C36.png +0 -0
- package/lib/public/mate-avatars/C37.png +0 -0
- package/lib/public/mate-avatars/C38.png +0 -0
- package/lib/public/mate-avatars/C39.png +0 -0
- package/lib/public/mate-avatars/C40.png +0 -0
- package/lib/public/mate-avatars/C41.png +0 -0
- package/lib/public/mate-avatars/C42.png +0 -0
- package/lib/public/mate-avatars/C43.png +0 -0
- package/lib/public/mate-avatars/C44.png +0 -0
- package/lib/public/mate-avatars/C45.png +0 -0
- package/lib/public/mate-avatars/C46.png +0 -0
- package/lib/public/mate-avatars/C47.png +0 -0
- package/lib/public/mate-avatars/C48.png +0 -0
- package/lib/public/mate-avatars/catalog.json +482 -0
- package/lib/public/mate-avatars/lead-clay.png +0 -0
- package/lib/public/modules/admin-settings-projects.js +6 -2
- package/lib/public/modules/app-connection.js +8 -1
- package/lib/public/modules/app-message-router.js +4 -0
- package/lib/public/modules/app-messages.js +31 -5
- package/lib/public/modules/app-projects.js +5 -0
- package/lib/public/modules/app-rendering.js +1 -1
- package/lib/public/modules/avatar.js +15 -41
- package/lib/public/modules/chat-render-runtime.js +10 -1
- package/lib/public/modules/clay-browser-links.js +47 -0
- package/lib/public/modules/clay-log-links.js +1 -1
- package/lib/public/modules/clay-owner-navigation.js +27 -0
- package/lib/public/modules/clay-tool-activity.js +140 -0
- package/lib/public/modules/clay-tool-presentation.js +338 -0
- package/lib/public/modules/command-palette.js +2 -2
- package/lib/public/modules/debate.js +1 -0
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/history-replay-batch.js +5 -1
- package/lib/public/modules/home-debate-live.js +2 -0
- package/lib/public/modules/home-debate-planning.js +7 -7
- package/lib/public/modules/home-mate-avatar-editor.js +127 -208
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/home-mate-settings.js +19 -12
- package/lib/public/modules/markdown.js +4 -0
- package/lib/public/modules/mate-avatar-catalog.js +97 -0
- package/lib/public/modules/mate-management.js +40 -7
- package/lib/public/modules/mcp-connection-view.js +31 -13
- package/lib/public/modules/mcp-discovery-view.js +31 -0
- package/lib/public/modules/mcp-ui.js +23 -4
- package/lib/public/modules/mention.js +3 -0
- package/lib/public/modules/pane-browser-bridge.js +20 -0
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/profile.js +1 -238
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/project-mate-navigation.js +99 -14
- package/lib/public/modules/search-clay-chat.js +16 -2
- package/lib/public/modules/session-folder-layout.js +1 -1
- package/lib/public/modules/session-folder-view-menu.js +9 -0
- package/lib/public/modules/session-github.js +85 -14
- package/lib/public/modules/session-work-primary.js +51 -0
- package/lib/public/modules/shared-browser-settings.js +112 -0
- package/lib/public/modules/shared-browser-tabs.js +13 -3
- package/lib/public/modules/shared-browser.js +27 -6
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- package/lib/public/modules/split-view.js +2 -0
- package/lib/public/modules/sticky-note-markdown.js +72 -6
- package/lib/public/modules/sticky-notes-actions.js +30 -0
- package/lib/public/modules/sticky-notes-browser.js +9 -2
- package/lib/public/modules/sticky-notes-card.js +23 -7
- package/lib/public/modules/sticky-notes-checklist.js +71 -0
- package/lib/public/modules/sticky-notes-editor.js +108 -44
- package/lib/public/modules/sticky-notes-shared.js +50 -2
- package/lib/public/modules/sticky-notes-state.js +66 -0
- package/lib/public/modules/sticky-notes.js +34 -51
- package/lib/public/modules/theme.js +8 -1
- package/lib/public/modules/thinking-lifecycle.js +33 -3
- package/lib/public/modules/thinking-view.js +23 -1
- package/lib/public/modules/tools.js +36 -7
- package/lib/public/modules/user-settings-appearance.js +10 -3
- package/lib/public/modules/user-settings-editors.js +1 -1
- package/lib/public/modules/user-settings-layout.js +11 -2
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +12 -2
- package/lib/public/modules/user-settings.js +3 -2
- package/lib/public/style.css +3 -0
- package/lib/public/sw.js +3 -1
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +228 -23
- package/lib/sdk-message-processor.js +2 -0
- package/lib/sdk-response-recovery.js +155 -0
- package/lib/server-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-dm.js +2 -1
- package/lib/server-global-ws.js +10 -20
- package/lib/server-home-chat-events.js +18 -4
- package/lib/server-home-chat.js +12 -16
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +14 -0
- package/lib/server-mates.js +25 -62
- package/lib/server-owner-ui.js +77 -0
- package/lib/server-path-access.js +38 -0
- package/lib/server-project-removal.js +22 -0
- package/lib/server-settings.js +4 -1
- package/lib/server.js +144 -41
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-github.js +9 -2
- package/lib/session-visibility.js +5 -2
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +13 -0
- package/lib/shared-browser-cookie-sync.js +32 -0
- package/lib/shared-browser-cookies.js +79 -0
- package/lib/shared-browser-runtime.js +25 -9
- package/lib/shared-browser-storage-sync.js +43 -0
- package/lib/shared-browser-storage.js +101 -0
- package/lib/shared-browser-tools.js +2 -1
- package/lib/shared-browser-worker.js +46 -10
- package/lib/terminal-manager.js +52 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +4 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/ws-schema.js +8 -2
- package/lib/yoke/acp-agent-profiles.js +2 -2
- package/lib/yoke/adapters/claude.js +47 -8
- package/lib/yoke/adapters/codex.js +52 -111
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/session-tool-transport.js +3 -0
- package/package.json +5 -1
package/lib/public/style.css
CHANGED
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
@import url("css/home-debate-planning.css");
|
|
60
60
|
@import url("css/home-mate-creation.css");
|
|
61
61
|
@import url("css/home-mate-settings.css");
|
|
62
|
+
@import url("css/mate-avatar-gallery.css");
|
|
62
63
|
@import url("css/home-mate-model-picker.css");
|
|
63
64
|
@import url("css/project-mate-creation.css");
|
|
64
65
|
@import url("css/home-debate-live.css");
|
|
@@ -87,3 +88,5 @@
|
|
|
87
88
|
@import url("css/server-settings-system.css");
|
|
88
89
|
|
|
89
90
|
@import url("css/project-settings-modal.css");
|
|
91
|
+
|
|
92
|
+
@import url("css/clay-tool-activity.css");
|
package/lib/public/sw.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var CACHE_NAME = "clay-offline-
|
|
1
|
+
var CACHE_NAME = "clay-offline-v5";
|
|
2
2
|
|
|
3
3
|
self.addEventListener("install", function (event) {
|
|
4
4
|
event.waitUntil(self.skipWaiting());
|
|
@@ -23,6 +23,8 @@ self.addEventListener("activate", function (event) {
|
|
|
23
23
|
function shouldCache(request, response) {
|
|
24
24
|
if (request.method !== "GET") return false;
|
|
25
25
|
if (!response || !response.ok) return false;
|
|
26
|
+
var cacheControl = response.headers && response.headers.get("Cache-Control") || "";
|
|
27
|
+
if (/(^|,)\s*(private|no-store)(?:\s*=\s*[^,]*)?(?=\s*(?:,|$))/i.test(cacheControl)) return false;
|
|
26
28
|
// Cache same-origin static assets and CDN resources (jsdelivr, fonts)
|
|
27
29
|
var url = new URL(request.url);
|
|
28
30
|
if (url.origin === self.location.origin) return true;
|
|
@@ -18,6 +18,7 @@ function createScheduledTaskRecords(ctx) {
|
|
|
18
18
|
var runs = Array.isArray(record.runs) ? record.runs : [];
|
|
19
19
|
var readiness = ctx.runtimeStatus ? ctx.runtimeStatus(record) : null;
|
|
20
20
|
return {
|
|
21
|
+
createdBy: record.createdBy || null, updatedBy: record.updatedBy || null,
|
|
21
22
|
id: record.id, revision: Number(record.updatedAt || 0), name: record.name || "",
|
|
22
23
|
instructions: record.task || record.prompt || record.instructions || "",
|
|
23
24
|
cron: record.cron || null, date: record.date || null, time: record.time || null,
|
|
@@ -49,7 +50,7 @@ function createScheduledTaskRecords(ctx) {
|
|
|
49
50
|
return { ok: true, record: publicRecord(record) };
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
function update(session, id, revision, patch) {
|
|
53
|
+
function update(session, id, revision, patch, actor) {
|
|
53
54
|
if (typeof id !== "string" || !ID_PATTERN.test(id)) return { ok: false, error: "Scheduled task id is invalid." };
|
|
54
55
|
var record = ctx.registry.getById(id);
|
|
55
56
|
if (!record) return { ok: false, error: "Scheduled task not found." };
|
|
@@ -94,6 +95,7 @@ function createScheduledTaskRecords(ctx) {
|
|
|
94
95
|
}
|
|
95
96
|
try {
|
|
96
97
|
var updateData = Object.assign({}, checked.value);
|
|
98
|
+
if (actor) updateData.updatedBy = actor;
|
|
97
99
|
if (claimOwner) { updateData.ownerId = session.ownerId; updateData.enabled = true; }
|
|
98
100
|
if (updateData.cron) {
|
|
99
101
|
updateData.date = record.cron && !record.scheduleRule ? record.date || null : null;
|
package/lib/scheduler.js
CHANGED
|
@@ -239,6 +239,7 @@ function createLoopRegistry(opts) {
|
|
|
239
239
|
|
|
240
240
|
function register(data) {
|
|
241
241
|
var rec = {
|
|
242
|
+
createdBy: data.createdBy || null, updatedBy: data.updatedBy || null, creationFingerprint: data.creationFingerprint || null,
|
|
242
243
|
id: data.id || ("loop_" + Date.now() + "_" + require("crypto").randomBytes(3).toString("hex")),
|
|
243
244
|
name: data.name || "Untitled",
|
|
244
245
|
task: data.task || "",
|
|
@@ -297,6 +298,7 @@ function createLoopRegistry(opts) {
|
|
|
297
298
|
if (!rec) return null;
|
|
298
299
|
var previous = Object.assign({}, rec);
|
|
299
300
|
|
|
301
|
+
if (data.updatedBy !== undefined) rec.updatedBy = data.updatedBy;
|
|
300
302
|
if (data.name !== undefined) rec.name = data.name;
|
|
301
303
|
if (data.cron !== undefined) rec.cron = data.cron;
|
|
302
304
|
if (data.enabled !== undefined) rec.enabled = data.enabled;
|
package/lib/sdk-bridge.js
CHANGED
|
@@ -323,6 +323,7 @@ function createSDKBridge(opts) {
|
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
function stopIdleReaper() {
|
|
326
|
+
responseRecovery.dispose();
|
|
326
327
|
if (_idleReaperTimer) {
|
|
327
328
|
clearInterval(_idleReaperTimer);
|
|
328
329
|
_idleReaperTimer = null;
|
|
@@ -389,6 +390,17 @@ function createSDKBridge(opts) {
|
|
|
389
390
|
var sendAndRecord = msgProcessor.sendAndRecord;
|
|
390
391
|
var sendToSession = msgProcessor.sendToSession;
|
|
391
392
|
|
|
393
|
+
var responseRecovery = require("./sdk-response-recovery").attachResponseRecovery(Object.assign({
|
|
394
|
+
sessions: sm.sessions,
|
|
395
|
+
changed: onProcessingChanged,
|
|
396
|
+
record: sendAndRecord,
|
|
397
|
+
send: sendToSession,
|
|
398
|
+
broadcast: function() { if (sm.broadcastSessionList) sm.broadcastSessionList(); },
|
|
399
|
+
restart: function(session, payload, state) {
|
|
400
|
+
return startQuery(session, payload.text, payload.images, payload.linuxUser, payload.beforePush, null, state);
|
|
401
|
+
},
|
|
402
|
+
}, opts.responseRecovery || {}));
|
|
403
|
+
|
|
392
404
|
// --- MCP elicitation ---
|
|
393
405
|
|
|
394
406
|
function handleElicitation(session, request, opts) {
|
|
@@ -417,6 +429,7 @@ function createSDKBridge(opts) {
|
|
|
417
429
|
|
|
418
430
|
if (pushModule) {
|
|
419
431
|
pushModule.sendPush({
|
|
432
|
+
sessionId: session.localId,
|
|
420
433
|
type: "elicitation",
|
|
421
434
|
slug: slug,
|
|
422
435
|
title: (request.serverName || "MCP Server") + " needs input",
|
|
@@ -467,6 +480,7 @@ function createSDKBridge(opts) {
|
|
|
467
480
|
|
|
468
481
|
if (pushModule) {
|
|
469
482
|
pushModule.sendPush({
|
|
483
|
+
sessionId: session.localId,
|
|
470
484
|
type: "user_dialog",
|
|
471
485
|
slug: slug,
|
|
472
486
|
title: "Claude needs a decision",
|
|
@@ -745,6 +759,34 @@ function createSDKBridge(opts) {
|
|
|
745
759
|
// Workspace inspection and proposal posting are session-bound. Keep this
|
|
746
760
|
// list exact so a future execution/mutation tool cannot inherit approval.
|
|
747
761
|
var safeWorkspaceTools = {
|
|
762
|
+
"mcp__clay-workspace__read_owner_screen": true,
|
|
763
|
+
"mcp__clay-workspace__inspect_owner_screen_change": true,
|
|
764
|
+
"mcp__clay-workspace__control_owner_screen": true,
|
|
765
|
+
"mcp__clay-workspace__discover_product_controls": true,
|
|
766
|
+
"mcp__clay-workspace__list_owned_mates": true,
|
|
767
|
+
"mcp__clay-workspace__begin_schedule_control_interview": true,
|
|
768
|
+
"mcp__clay-workspace__read_schedule_controls": true,
|
|
769
|
+
"mcp__clay-workspace__inspect_schedule_change": true,
|
|
770
|
+
"mcp__clay-workspace__control_schedules": true,
|
|
771
|
+
"mcp__clay-workspace__read_mate_chat_control": true,
|
|
772
|
+
"mcp__clay-workspace__inspect_mate_chat_change": true,
|
|
773
|
+
"mcp__clay-workspace__control_mate_chat": true,
|
|
774
|
+
"mcp__clay-workspace__read_project_workspace": true,
|
|
775
|
+
"mcp__clay-workspace__read_workspace_receipt": true,
|
|
776
|
+
"mcp__clay-workspace__inspect_workspace_change": true,
|
|
777
|
+
"mcp__clay-workspace__control_project_workspace": true,
|
|
778
|
+
"mcp__clay-workspace__read_project_records": true,
|
|
779
|
+
"mcp__clay-workspace__inspect_project_record_change": true,
|
|
780
|
+
"mcp__clay-workspace__control_project_records": true,
|
|
781
|
+
"mcp__clay-workspace__read_mate_knowledge_control": true,
|
|
782
|
+
"mcp__clay-workspace__inspect_mate_knowledge_change": true,
|
|
783
|
+
"mcp__clay-workspace__control_mate_knowledge": true,
|
|
784
|
+
"mcp__clay-workspace__inspect_mate_control": true,
|
|
785
|
+
"mcp__clay-workspace__control_mate_lifecycle": true,
|
|
786
|
+
"mcp__clay-workspace__inspect_project_control": true,
|
|
787
|
+
"mcp__clay-workspace__control_project_lifecycle": true,
|
|
788
|
+
"mcp__clay-workspace__inspect_session_control": true,
|
|
789
|
+
"mcp__clay-workspace__control_project_session": true,
|
|
748
790
|
"mcp__clay-workspace__list_projects": true,
|
|
749
791
|
"mcp__clay-workspace__list_project_sessions": true,
|
|
750
792
|
"mcp__clay-workspace__search_project_history": true,
|
|
@@ -902,6 +944,7 @@ function createSDKBridge(opts) {
|
|
|
902
944
|
|
|
903
945
|
if (pushModule) {
|
|
904
946
|
pushModule.sendPush({
|
|
947
|
+
sessionId: session.localId,
|
|
905
948
|
type: "permission_request",
|
|
906
949
|
slug: slug,
|
|
907
950
|
requestId: requestId,
|
|
@@ -1006,6 +1049,7 @@ function createSDKBridge(opts) {
|
|
|
1006
1049
|
function recordRuntimeEffectivePermissionMode(session, queryInstance, queryGeneration, message) {
|
|
1007
1050
|
if (!message || (message.yokeType !== "init" && message.yokeType !== "status") || !message.permissionMode) return false;
|
|
1008
1051
|
if (!ownsQueryRuntime(session, queryInstance, queryGeneration)) return false;
|
|
1052
|
+
session._permissionObservationRevision = Number(session._permissionObservationRevision || 0) + 1;
|
|
1009
1053
|
session.effectivePermissionMode = message.permissionMode;
|
|
1010
1054
|
session.permissionModeFallbackReason = null;
|
|
1011
1055
|
sm.saveSessionFile(session);
|
|
@@ -1047,7 +1091,7 @@ function createSDKBridge(opts) {
|
|
|
1047
1091
|
try {
|
|
1048
1092
|
for await (var msg of myQueryInstance) {
|
|
1049
1093
|
// An old iterator may drain after Stop or after a replacement query starts.
|
|
1050
|
-
if (!ownsQueryRuntime(session, myQueryInstance, myQueryGeneration)) continue;
|
|
1094
|
+
if (!ownsQueryRuntime(session, myQueryInstance, myQueryGeneration) || responseRecovery.stopping(session)) continue;
|
|
1051
1095
|
if ((session.taskStopRequested || (myAbortController && myAbortController.signal.aborted))
|
|
1052
1096
|
&& msg && msg.yokeType !== "error" && msg.yokeType !== "interrupted") continue;
|
|
1053
1097
|
if (msg && msg.yokeType !== "text_delta" && msg.yokeType !== "thinking_delta" && msg.yokeType !== "tool_input_delta") {
|
|
@@ -1091,6 +1135,7 @@ function createSDKBridge(opts) {
|
|
|
1091
1135
|
if (continuationIdentity && !ownsQueryRuntime(session, myQueryInstance, myQueryGeneration)) {
|
|
1092
1136
|
continue;
|
|
1093
1137
|
}
|
|
1138
|
+
responseRecovery.event(session, msg);
|
|
1094
1139
|
processSDKMessage(session, msg);
|
|
1095
1140
|
if (continuationIdentity) {
|
|
1096
1141
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, true, null);
|
|
@@ -1120,7 +1165,7 @@ function createSDKBridge(opts) {
|
|
|
1120
1165
|
// Stream ended normally after a task stop — no "result" message was sent,
|
|
1121
1166
|
// so the session is still marked as processing. Send interrupted feedback.
|
|
1122
1167
|
console.log("[sdk-bridge] processQueryStream ended: isProcessing=" + session.isProcessing + " taskStopRequested=" + session.taskStopRequested);
|
|
1123
|
-
var stillOwnsRuntime = session.queryInstance === myQueryInstance;
|
|
1168
|
+
var stillOwnsRuntime = session.queryInstance === myQueryInstance && !responseRecovery.stopping(session);
|
|
1124
1169
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, false, "The successor query ended before initialization.");
|
|
1125
1170
|
if (session.isProcessing && session.taskStopRequested && stillOwnsRuntime) {
|
|
1126
1171
|
session._lastTurnInterrupted = true;
|
|
@@ -1158,7 +1203,7 @@ function createSDKBridge(opts) {
|
|
|
1158
1203
|
}
|
|
1159
1204
|
} catch (err) {
|
|
1160
1205
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, false, err.message || "The successor query failed before initialization.");
|
|
1161
|
-
if (session.isProcessing && session.queryInstance === myQueryInstance) {
|
|
1206
|
+
if (session.isProcessing && session.queryInstance === myQueryInstance && !responseRecovery.stopping(session)) {
|
|
1162
1207
|
session.isProcessing = false;
|
|
1163
1208
|
session._awaitingTurnResult = false;
|
|
1164
1209
|
session._queuedTurnCount = 0;
|
|
@@ -1272,7 +1317,8 @@ function createSDKBridge(opts) {
|
|
|
1272
1317
|
}
|
|
1273
1318
|
if (session.messageQueue === myMessageQueue) session.messageQueue = null;
|
|
1274
1319
|
if (session.abortController === myAbortController) session.abortController = null;
|
|
1275
|
-
if (ownsRuntime) {
|
|
1320
|
+
if (ownsRuntime && !responseRecovery.stopping(session)) {
|
|
1321
|
+
responseRecovery.cancel(session);
|
|
1276
1322
|
session.taskStopRequested = false;
|
|
1277
1323
|
session.pendingPermissions = {};
|
|
1278
1324
|
// Preserve only restored legacy MCP entries. Canonical Yoke requests
|
|
@@ -1321,7 +1367,7 @@ function createSDKBridge(opts) {
|
|
|
1321
1367
|
}
|
|
1322
1368
|
}
|
|
1323
1369
|
}
|
|
1324
|
-
if (!session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1370
|
+
if (!responseRecovery.stopping(session) && !session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1325
1371
|
}
|
|
1326
1372
|
}
|
|
1327
1373
|
|
|
@@ -1442,22 +1488,70 @@ function createSDKBridge(opts) {
|
|
|
1442
1488
|
|
|
1443
1489
|
// Wrapper: marks the boot window so pushMessage can buffer instead of
|
|
1444
1490
|
// dropping messages that arrive while createQuery is still awaiting.
|
|
1445
|
-
async function startQuery(session, text, images, linuxUser, beforePush, onAccepted) {
|
|
1491
|
+
async function startQuery(session, text, images, linuxUser, beforePush, onAccepted, retryState) {
|
|
1492
|
+
if (opts.isLifecycleExecutionPaused && opts.isLifecycleExecutionPaused()) {
|
|
1493
|
+
sendAndRecord(session, { type: "error", text: "Project execution is paused for lifecycle recovery. Reconcile the saved operation, or send a new owner message after restoring the registration." });
|
|
1494
|
+
session.isProcessing = false; onProcessingChanged(); sendAndRecord(session, { type: "done", code: 1 }); return false;
|
|
1495
|
+
}
|
|
1496
|
+
if (session._responseRecoveryStopPending && !retryState) {
|
|
1497
|
+
session.isProcessing = false;
|
|
1498
|
+
onProcessingChanged();
|
|
1499
|
+
sendAndRecord(session, { type: "error", text: "The previous Claude attempt has not confirmed stopped. Check the connection before sending this message again." });
|
|
1500
|
+
sendAndRecord(session, { type: "done", code: 1 });
|
|
1501
|
+
return false;
|
|
1502
|
+
}
|
|
1503
|
+
if (responseRecovery.stopping(session) && !retryState) return false;
|
|
1446
1504
|
delete session._lastTurnInterrupted;
|
|
1505
|
+
var claude = (session.vendor || adapter.vendor) === "claude";
|
|
1506
|
+
var payload = { text: text, images: images, linuxUser: linuxUser, beforePush: beforePush };
|
|
1507
|
+
var recoveryState = claude ? responseRecovery.begin(session, payload, retryState) : null;
|
|
1508
|
+
if (recoveryState) recoveryState.handle = null;
|
|
1509
|
+
var guardedPush = function() {
|
|
1510
|
+
return !session.destroying && !session.taskStopRequested
|
|
1511
|
+
&& (!recoveryState || responseRecovery.valid(session, recoveryState) && !recoveryState.stopping)
|
|
1512
|
+
&& (typeof beforePush !== "function" || beforePush() === true);
|
|
1513
|
+
};
|
|
1514
|
+
guardedPush.exactProductDelivery = !!(beforePush && beforePush.exactProductDelivery);
|
|
1447
1515
|
session._queryGeneration = (session._queryGeneration || 0) + 1;
|
|
1448
1516
|
session._queryStarting = true;
|
|
1517
|
+
var starting = startQueryInner(session, text, images, linuxUser, guardedPush, onAccepted, recoveryState);
|
|
1518
|
+
if (recoveryState) recoveryState.starting = starting;
|
|
1449
1519
|
try {
|
|
1450
|
-
|
|
1520
|
+
var accepted = await starting;
|
|
1521
|
+
if (accepted === false && (!recoveryState || !recoveryState.stopping)) {
|
|
1522
|
+
responseRecovery.cancel(session);
|
|
1523
|
+
session.isProcessing = false;
|
|
1524
|
+
onProcessingChanged();
|
|
1525
|
+
}
|
|
1526
|
+
return accepted;
|
|
1527
|
+
} catch (error) {
|
|
1528
|
+
// Includes synchronous input queue failures, before stream consumption.
|
|
1529
|
+
var failedHandle = session.queryInstance;
|
|
1530
|
+
if (failedHandle) {
|
|
1531
|
+
try { if (typeof failedHandle.abort === "function") failedHandle.abort(); } catch (e) {}
|
|
1532
|
+
try { if (typeof failedHandle.close === "function") failedHandle.close(); } catch (e) {}
|
|
1533
|
+
}
|
|
1534
|
+
session.queryInstance = null;
|
|
1535
|
+
session.abortController = null;
|
|
1536
|
+
session.messageQueue = null;
|
|
1537
|
+
session.isProcessing = false;
|
|
1538
|
+
session._awaitingTurnResult = false;
|
|
1539
|
+
session._queuedTurnCount = 0;
|
|
1540
|
+
taskLifecycle.clearAll(session);
|
|
1541
|
+
if (!recoveryState || !recoveryState.stopping) {
|
|
1542
|
+
responseRecovery.cancel(session);
|
|
1543
|
+
sendAndRecord(session, { type: "error", text: "The agent connection failed while delivering your message. Please retry or check the connection." });
|
|
1544
|
+
sendAndRecord(session, { type: "done", code: 1 });
|
|
1545
|
+
onProcessingChanged();
|
|
1546
|
+
sm.broadcastSessionList();
|
|
1547
|
+
}
|
|
1548
|
+
return false;
|
|
1451
1549
|
} finally {
|
|
1452
1550
|
session._queryStarting = false;
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
session.pendingPush = [];
|
|
1458
|
-
}
|
|
1459
|
-
if (!session.queryInstance && !session.isProcessing) session.taskStopRequested = false;
|
|
1460
|
-
if (!session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1551
|
+
delete session._codexRecoveryWaiting;
|
|
1552
|
+
if (!session.queryInstance && session.pendingPush && session.pendingPush.length) session.pendingPush = [];
|
|
1553
|
+
if (!session.queryInstance && !session.isProcessing && !session._pendingMessageDrainPaused && !responseRecovery.stopping(session)) session.taskStopRequested = false;
|
|
1554
|
+
if (!responseRecovery.stopping(session) && !session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1461
1555
|
}
|
|
1462
1556
|
}
|
|
1463
1557
|
|
|
@@ -1501,7 +1595,7 @@ function createSDKBridge(opts) {
|
|
|
1501
1595
|
};
|
|
1502
1596
|
}
|
|
1503
1597
|
|
|
1504
|
-
async function startQueryInner(session, text, images, linuxUser, beforePush, onAccepted) {
|
|
1598
|
+
async function startQueryInner(session, text, images, linuxUser, beforePush, onAccepted, recoveryState) {
|
|
1505
1599
|
var sessionRuntimeEnv = getRuntimeEnv(session);
|
|
1506
1600
|
var resumedAtQueryStart = !!session.cliSessionId;
|
|
1507
1601
|
async function ensureVendorReady(vendor) {
|
|
@@ -1812,7 +1906,7 @@ function createSDKBridge(opts) {
|
|
|
1812
1906
|
}
|
|
1813
1907
|
var hasSharedBrowserCatalog = sessionToolDefs.some(function (definition) { return definition.name === "shared_browser"; });
|
|
1814
1908
|
var recoverCodexBrowserTools = sessionAdapter.vendor === "codex" && !!session.cliSessionId
|
|
1815
|
-
&& hasSharedBrowserCatalog && Number(session.codexSharedBrowserToolCatalogVersion || 0) <
|
|
1909
|
+
&& hasSharedBrowserCatalog && Number(session.codexSharedBrowserToolCatalogVersion || 0) < 6;
|
|
1816
1910
|
var recoverCodexIssueTools = sessionAdapter.vendor === "codex"
|
|
1817
1911
|
&& !!session.cliSessionId
|
|
1818
1912
|
&& hasIssueCatalog
|
|
@@ -1822,13 +1916,15 @@ function createSDKBridge(opts) {
|
|
|
1822
1916
|
if (sm && sm.sessions && typeof sm.sessions.get === "function" && sm.sessions.get(session.localId) !== session) return false;
|
|
1823
1917
|
return canUseSessionTools(session) === true;
|
|
1824
1918
|
}
|
|
1919
|
+
var hasMateScheduleTool = sessionToolDefs.some(function (tool) { return yoke.sessionTools.MATE_SCHEDULE_TOOLS.indexOf(tool.name) !== -1; });
|
|
1920
|
+
var recoverCodexMateSchedules = sessionAdapter.vendor === "codex" && !!session.cliSessionId && hasMateScheduleTool && queryContextAvailable();
|
|
1825
1921
|
var hasScheduleTool = false;
|
|
1826
1922
|
var hasScheduleInterviewTool = false;
|
|
1827
1923
|
var scheduleInterviewActive = null;
|
|
1828
1924
|
var scheduleQuestionLimit = null;
|
|
1829
1925
|
for (var sessionToolIndex = 0; sessionToolIndex < sessionToolDefs.length; sessionToolIndex++) {
|
|
1830
1926
|
if (yoke.sessionTools.SCHEDULE_TOOLS.indexOf(sessionToolDefs[sessionToolIndex].name) !== -1) hasScheduleTool = true;
|
|
1831
|
-
if (sessionToolDefs[sessionToolIndex].name
|
|
1927
|
+
if (["begin_scheduled_task_interview", "begin_mate_schedule_interview", "begin_schedule_control_interview"].indexOf(sessionToolDefs[sessionToolIndex].name) >= 0) {
|
|
1832
1928
|
hasScheduleInterviewTool = true;
|
|
1833
1929
|
scheduleInterviewActive = sessionToolDefs[sessionToolIndex].scheduleInterviewActive || null;
|
|
1834
1930
|
scheduleQuestionLimit = sessionToolDefs[sessionToolIndex].structuredQuestionLimit || null;
|
|
@@ -1860,9 +1956,10 @@ function createSDKBridge(opts) {
|
|
|
1860
1956
|
return "Ask exactly one question at a time, wait for the answer, then ask the next question.";
|
|
1861
1957
|
}
|
|
1862
1958
|
var sessionUserInputHandler = function(request, respond) {
|
|
1863
|
-
if (!structuredInputContextAvailable()) {
|
|
1959
|
+
if (queryRetired() || !structuredInputContextAvailable()) {
|
|
1864
1960
|
return respond.cancel("This structured-input request belongs to an unavailable or older query.");
|
|
1865
1961
|
}
|
|
1962
|
+
responseRecovery.progress(session);
|
|
1866
1963
|
var questionError = scheduleQuestionError(request);
|
|
1867
1964
|
if (questionError) return respond.cancel(questionError);
|
|
1868
1965
|
if (request.presentation === "elicitation" && request.diagnostics && request.diagnostics.elicitation) {
|
|
@@ -1895,6 +1992,11 @@ function createSDKBridge(opts) {
|
|
|
1895
1992
|
}
|
|
1896
1993
|
}
|
|
1897
1994
|
}
|
|
1995
|
+
if (sessionAdapter.vendor === "claude" && hasMateScheduleTool && typeof sessionAdapter.createToolServer === "function") {
|
|
1996
|
+
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1997
|
+
localMcpServers["clay-mate-schedules"] = sessionAdapter.createToolServer({ name: "clay-mate-schedules", version: "1.0.0",
|
|
1998
|
+
tools: sessionToolDefs.filter(function (tool) { return yoke.sessionTools.MATE_SCHEDULE_TOOLS.indexOf(tool.name) !== -1; }) });
|
|
1999
|
+
}
|
|
1898
2000
|
if (selectedUserInputMode === "fallback") {
|
|
1899
2001
|
var userInputServer = yoke.userInput.createFallbackServer(sessionAdapter, sessionUserInputHandler, { force: true, maxQuestions: scheduleQuestionLimit });
|
|
1900
2002
|
if (userInputServer) {
|
|
@@ -1931,6 +2033,12 @@ function createSDKBridge(opts) {
|
|
|
1931
2033
|
return snapshotDef;
|
|
1932
2034
|
}
|
|
1933
2035
|
|
|
2036
|
+
var externalQueryBridge = require('./mcp-query-bridge').createQueryBridge({ valid: queryContextAvailable,
|
|
2037
|
+
getServers: function () { return getRemoteMcpServers ? getRemoteMcpServers(session) || {} : {}; } });
|
|
2038
|
+
var externalToolDefs = sessionAdapter.vendor === 'codex' ? externalQueryBridge.dynamicDefs() : [];
|
|
2039
|
+
if (externalToolDefs.length) { sessionToolDefs = sessionToolDefs.concat(externalToolDefs); queryToolSnapshots.set(session, { generation: queryGeneration, defs: sessionToolDefs.slice() }); }
|
|
2040
|
+
var recoverCodexExternalTools = sessionAdapter.vendor === 'codex' && !!session.cliSessionId && (externalToolDefs.length > 0 || isMate);
|
|
2041
|
+
|
|
1934
2042
|
// Give fresh queries an immediate provisional label. The visible user
|
|
1935
2043
|
// message in history wins over `text`, which may contain an internal
|
|
1936
2044
|
// provider wrapper rather than what the person typed.
|
|
@@ -1945,6 +2053,11 @@ function createSDKBridge(opts) {
|
|
|
1945
2053
|
}
|
|
1946
2054
|
|
|
1947
2055
|
var modelSwitchGeneration = session._queryGeneration;
|
|
2056
|
+
function queryRetired() {
|
|
2057
|
+
if (sessionAdapter.vendor !== "claude") return false;
|
|
2058
|
+
return Number(session._sdkQueryGeneration || 0) !== queryGeneration || session.taskStopRequested
|
|
2059
|
+
|| session.destroying || responseRecovery.stopping(session) || (handle && session.queryInstance !== handle);
|
|
2060
|
+
}
|
|
1948
2061
|
var queryOpts = {
|
|
1949
2062
|
onModelSwitch: function(change) {
|
|
1950
2063
|
if (session._queryGeneration !== modelSwitchGeneration || session.taskStopRequested) return;
|
|
@@ -1986,7 +2099,18 @@ function createSDKBridge(opts) {
|
|
|
1986
2099
|
dynamicTools: sessionToolDefs,
|
|
1987
2100
|
// Codex persists dynamic tools with a thread. A stale authorized Driver
|
|
1988
2101
|
// gets this exact-query bridge; its handlers still reauthorize live.
|
|
1989
|
-
sessionMcpServer: (recoverCodexIssueTools || recoverCodexQuestionTools || recoverCodexBrowserTools || recoverCodexLinearTools || recoverCodexYouTools) ? getCodexSessionMcpServer(session, queryGeneration) : undefined,
|
|
2102
|
+
sessionMcpServer: (recoverCodexMateSchedules || recoverCodexIssueTools || recoverCodexQuestionTools || recoverCodexBrowserTools || recoverCodexLinearTools || recoverCodexYouTools || recoverCodexExternalTools) ? getCodexSessionMcpServer(session, queryGeneration) : undefined,
|
|
2103
|
+
onRecoveryAdmission: function(waiting) {
|
|
2104
|
+
if (!queryContextAvailable()) return;
|
|
2105
|
+
if (waiting) session._codexRecoveryWaiting = queryGeneration;
|
|
2106
|
+
else delete session._codexRecoveryWaiting;
|
|
2107
|
+
},
|
|
2108
|
+
onRecoveryWaiting: function(waiting) {
|
|
2109
|
+
if (!queryContextAvailable()) return;
|
|
2110
|
+
sendAndRecord(session, { type: 'informational', level: 'info', content: waiting
|
|
2111
|
+
? 'Codex recovery is waiting for this conversation’s runtime to become safely available. Your message is retained; Stop cancels the wait.'
|
|
2112
|
+
: 'Codex recovery is ready. Continuing your retained message.' });
|
|
2113
|
+
},
|
|
1990
2114
|
callDynamicTool: function (toolName, args) {
|
|
1991
2115
|
var toolDef = findSessionToolDef(toolName);
|
|
1992
2116
|
if (toolDef && typeof toolDef.handler === "function") {
|
|
@@ -1997,6 +2121,8 @@ function createSDKBridge(opts) {
|
|
|
1997
2121
|
resumeSessionId: session.cliSessionId || undefined,
|
|
1998
2122
|
abortController: linuxUser ? undefined : session.abortController,
|
|
1999
2123
|
canUseTool: function(toolName, input, toolOpts) {
|
|
2124
|
+
if (queryRetired()) return { behavior: "deny", message: "This attempt has stopped." };
|
|
2125
|
+
responseRecovery.progress(session);
|
|
2000
2126
|
var nativeQuestionError = toolName === "AskUserQuestion" ? scheduleQuestionError(input) : null;
|
|
2001
2127
|
if (nativeQuestionError) return { behavior: "deny", message: nativeQuestionError };
|
|
2002
2128
|
var permissionName = toolName;
|
|
@@ -2005,6 +2131,8 @@ function createSDKBridge(opts) {
|
|
|
2005
2131
|
return handleCanUseTool(session, permissionName, input, toolOpts);
|
|
2006
2132
|
},
|
|
2007
2133
|
preToolUsePolicy: function(toolName, input) {
|
|
2134
|
+
if (queryRetired()) return Promise.resolve({ behavior: "deny", message: "This attempt has stopped." });
|
|
2135
|
+
responseRecovery.progress(session);
|
|
2008
2136
|
var nativeQuestionError = toolName === "AskUserQuestion" ? scheduleQuestionError(input) : null;
|
|
2009
2137
|
if (nativeQuestionError) return Promise.resolve({ behavior: "deny", message: nativeQuestionError });
|
|
2010
2138
|
var permissionName = toolName;
|
|
@@ -2018,12 +2146,18 @@ function createSDKBridge(opts) {
|
|
|
2018
2146
|
validateUserInputRequest: scheduleQuestionError,
|
|
2019
2147
|
userInputMode: selectedUserInputMode,
|
|
2020
2148
|
onElicitation: function(request, elicitOpts) {
|
|
2149
|
+
if (queryRetired()) return Promise.resolve({ action: "cancel" });
|
|
2150
|
+
responseRecovery.progress(session);
|
|
2021
2151
|
return handleElicitation(session, request, elicitOpts);
|
|
2022
2152
|
},
|
|
2023
2153
|
onUserDialog: function(dialogRequest, dialogOpts) {
|
|
2154
|
+
if (queryRetired()) return Promise.resolve({ behavior: "cancelled" });
|
|
2155
|
+
responseRecovery.progress(session);
|
|
2024
2156
|
return handleUserDialog(session, dialogRequest, dialogOpts);
|
|
2025
2157
|
},
|
|
2026
2158
|
callMcpTool: function(serverName, toolName, args) {
|
|
2159
|
+
if (queryRetired()) return Promise.reject(new Error("This attempt has stopped."));
|
|
2160
|
+
responseRecovery.progress(session);
|
|
2027
2161
|
return callMcpToolHandler(mergedMcpServers, serverName, toolName, args);
|
|
2028
2162
|
},
|
|
2029
2163
|
adapterOptions: {
|
|
@@ -2055,10 +2189,28 @@ function createSDKBridge(opts) {
|
|
|
2055
2189
|
},
|
|
2056
2190
|
};
|
|
2057
2191
|
|
|
2192
|
+
if (recoveryState) {
|
|
2193
|
+
if (!recoveryState.context) recoveryState.context = { appendSystemPrompt: queryOpts.appendSystemPrompt, model: queryOpts.model, effort: queryOpts.effort };
|
|
2194
|
+
Object.assign(queryOpts, recoveryState.context);
|
|
2195
|
+
}
|
|
2058
2196
|
var handle;
|
|
2197
|
+
var startupHandle = session.queryInstance;
|
|
2059
2198
|
console.log("[sdk-bridge] calling adapter.createQuery... vendor=" + sessionAdapter.vendor);
|
|
2060
2199
|
try {
|
|
2061
2200
|
handle = await sessionAdapter.createQuery(queryOpts);
|
|
2201
|
+
// A guarded delivery must still own the exact startup after provider
|
|
2202
|
+
// creation. Never replace a newer handle or publish to a deleted target.
|
|
2203
|
+
if (beforePush && beforePush.exactProductDelivery) {
|
|
2204
|
+
var startupCurrent = false;
|
|
2205
|
+
try { startupCurrent = sm.sessions.get(session.localId) === session && session.queryInstance === startupHandle && Number(session._sdkQueryGeneration || 0) === queryGeneration && beforePush() === true; } catch (guardError) {}
|
|
2206
|
+
if (!startupCurrent) {
|
|
2207
|
+
try { if (handle.abort) handle.abort(); } catch (abortError) {}
|
|
2208
|
+
try { if (handle.close) handle.close(); } catch (closeError) {}
|
|
2209
|
+
if (session.queryInstance === startupHandle) session.isProcessing = false;
|
|
2210
|
+
return false;
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
if (recoveryState) recoveryState.handle = handle;
|
|
2062
2214
|
console.log("[sdk-bridge] createQuery returned handle, vendor=" + sessionAdapter.vendor);
|
|
2063
2215
|
// SDK accepted the explicit title. Provisional labels remain eligible
|
|
2064
2216
|
// for semantic generation after the first Home exchange (or the normal
|
|
@@ -2078,6 +2230,7 @@ function createSDKBridge(opts) {
|
|
|
2078
2230
|
console.error("[sdk-bridge] Failed to create query for session " + session.localId + ":", e.message || e);
|
|
2079
2231
|
console.error("[sdk-bridge] cliSessionId:", session.cliSessionId, "resume:", !!session.cliSessionId);
|
|
2080
2232
|
console.error("[sdk-bridge] Stack:", e.stack || "(no stack)");
|
|
2233
|
+
if (beforePush && beforePush.exactProductDelivery && (sm.sessions.get(session.localId) !== session || session.queryInstance !== startupHandle || Number(session._sdkQueryGeneration || 0) !== queryGeneration)) return false;
|
|
2081
2234
|
session.isProcessing = false;
|
|
2082
2235
|
session._awaitingTurnResult = false;
|
|
2083
2236
|
session._queuedTurnCount = 0;
|
|
@@ -2132,6 +2285,7 @@ function createSDKBridge(opts) {
|
|
|
2132
2285
|
}
|
|
2133
2286
|
|
|
2134
2287
|
if (typeof beforePush === "function" && beforePush() !== true) {
|
|
2288
|
+
try { if (typeof handle.abort === "function") handle.abort(); } catch (e) {}
|
|
2135
2289
|
try { handle.close(); } catch (e) {}
|
|
2136
2290
|
if (session.queryInstance === handle) session.queryInstance = null;
|
|
2137
2291
|
session.messageQueue = null;
|
|
@@ -2141,6 +2295,13 @@ function createSDKBridge(opts) {
|
|
|
2141
2295
|
session._queuedTurnCount = 0;
|
|
2142
2296
|
taskLifecycle.clearAll(session);
|
|
2143
2297
|
onProcessingChanged();
|
|
2298
|
+
if (recoveryState && !responseRecovery.stopping(session)) {
|
|
2299
|
+
sendAndRecord(session, { type: "thinking_stop" });
|
|
2300
|
+
sendAndRecord(session, { type: session.taskStopRequested ? "info" : "error", text: session.taskStopRequested
|
|
2301
|
+
? "Stopped before sending your message."
|
|
2302
|
+
: "This request is no longer eligible for delivery. Please review it and send it again." });
|
|
2303
|
+
sendAndRecord(session, { type: "done", code: session.taskStopRequested ? 0 : 1 });
|
|
2304
|
+
}
|
|
2144
2305
|
sm.broadcastSessionList();
|
|
2145
2306
|
return false;
|
|
2146
2307
|
}
|
|
@@ -2208,7 +2369,7 @@ function createSDKBridge(opts) {
|
|
|
2208
2369
|
if (hasYouCatalog) codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, youVersion: 1 });
|
|
2209
2370
|
if (hasLinearCatalog) codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, linearVersion: 1 });
|
|
2210
2371
|
if (hasSharedBrowserCatalog) {
|
|
2211
|
-
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, sharedBrowserVersion:
|
|
2372
|
+
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, sharedBrowserVersion: 6 });
|
|
2212
2373
|
}
|
|
2213
2374
|
if (hasIssueCatalog) {
|
|
2214
2375
|
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, {
|
|
@@ -2229,6 +2390,19 @@ function createSDKBridge(opts) {
|
|
|
2229
2390
|
// dropped messages in both gap windows, which is what made a session show
|
|
2230
2391
|
// the processing indicator without ever answering until a second send.
|
|
2231
2392
|
function pushMessage(session, text, images, deliveryMeta) {
|
|
2393
|
+
if (session._responseRecoveryStopPending && !responseRecovery.stopping(session)) return false;
|
|
2394
|
+
function trackDelivery() {
|
|
2395
|
+
if ((session.vendor || adapter.vendor) === "claude") responseRecovery.enqueue(session, {
|
|
2396
|
+
text: text, images: images, linuxUser: session.lastLinuxUser || null,
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
if (responseRecovery.stopping(session)) {
|
|
2400
|
+
// Keep admission serialized while the old execution is terminating.
|
|
2401
|
+
session.pendingPush = session.pendingPush || [];
|
|
2402
|
+
session.pendingPush.push(Object.assign({ text: text, images: images || null }, deliveryMeta || {}));
|
|
2403
|
+
trackDelivery();
|
|
2404
|
+
return true;
|
|
2405
|
+
}
|
|
2232
2406
|
session.lastActivityAt = Date.now();
|
|
2233
2407
|
if (session._runtimeRefreshRequested && !session._queryStarting) {
|
|
2234
2408
|
session._runtimeRefreshRequested = false;
|
|
@@ -2255,6 +2429,7 @@ function createSDKBridge(opts) {
|
|
|
2255
2429
|
console.error("[sdk-bridge] QueryHandle rejected message for session " + session.localId + ":", e.message || e);
|
|
2256
2430
|
}
|
|
2257
2431
|
if (delivered) {
|
|
2432
|
+
trackDelivery();
|
|
2258
2433
|
delete session._lastTurnInterrupted;
|
|
2259
2434
|
if (session._awaitingTurnResult) {
|
|
2260
2435
|
session._queuedTurnCount = (session._queuedTurnCount || 0) + 1;
|
|
@@ -2279,6 +2454,7 @@ function createSDKBridge(opts) {
|
|
|
2279
2454
|
if (session._queryStarting) {
|
|
2280
2455
|
session.pendingPush = session.pendingPush || [];
|
|
2281
2456
|
session.pendingPush.push(Object.assign({ text: text, images: images || null }, deliveryMeta || {}));
|
|
2457
|
+
trackDelivery();
|
|
2282
2458
|
return true;
|
|
2283
2459
|
}
|
|
2284
2460
|
return false;
|
|
@@ -2489,7 +2665,20 @@ function createSDKBridge(opts) {
|
|
|
2489
2665
|
sendModelInfoForVendor(null, defaultVendor, defaultModelForVendor(defaultVendor));
|
|
2490
2666
|
}
|
|
2491
2667
|
|
|
2492
|
-
async function setModel(session, model) {
|
|
2668
|
+
async function setModel(session, model, options) {
|
|
2669
|
+
if (options && typeof options.revalidate === "function") {
|
|
2670
|
+
var vendor = session.vendor || sm.defaultVendor || "claude";
|
|
2671
|
+
return require("./session-config-transition").applySessionConfig({
|
|
2672
|
+
sm: sm, session: session, revalidate: options.revalidate, method: "setModel", nativeValue: model, changes: { model: model },
|
|
2673
|
+
publish: function () {
|
|
2674
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
2675
|
+
sm.defaultModelByVendor[vendor] = model;
|
|
2676
|
+
sm.broadcastSessionList();
|
|
2677
|
+
sendModelInfoForVendor(session, vendor, model);
|
|
2678
|
+
sendToSession(session, { type: "config_state", sessionId: session.localId, vendor: vendor, model: model, effort: session.effort || sm.currentEffort || "medium", mode: session.permissionMode || sm.currentPermissionMode || "default", betas: sm.currentBetas || [] });
|
|
2679
|
+
},
|
|
2680
|
+
});
|
|
2681
|
+
}
|
|
2493
2682
|
// Normalize to string id in case a { value, displayName } object slips in
|
|
2494
2683
|
if (model && typeof model !== "string") {
|
|
2495
2684
|
model = modelEntryValue(model);
|
|
@@ -2525,7 +2714,22 @@ function createSDKBridge(opts) {
|
|
|
2525
2714
|
}
|
|
2526
2715
|
}
|
|
2527
2716
|
|
|
2528
|
-
async function setEffort(session, effort) {
|
|
2717
|
+
async function setEffort(session, effort, options) {
|
|
2718
|
+
if (options && typeof options.revalidate === "function") {
|
|
2719
|
+
var vendor = session.vendor || sm.defaultVendor || "claude";
|
|
2720
|
+
var value = yoke.clampEffort(vendor, effort);
|
|
2721
|
+
if (!value || value !== effort) throw new Error("Unsupported reasoning effort.");
|
|
2722
|
+
return require("./session-config-transition").applySessionConfig({
|
|
2723
|
+
sm: sm, session: session, revalidate: options.revalidate, method: "setEffort", nativeValue: value, changes: { effort: value },
|
|
2724
|
+
publish: function () {
|
|
2725
|
+
sm.currentEffortByVendor = sm.currentEffortByVendor || {};
|
|
2726
|
+
sm.currentEffortByVendor[vendor] = value;
|
|
2727
|
+
sm.currentEffort = value;
|
|
2728
|
+
sm.broadcastSessionList();
|
|
2729
|
+
sendToSession(session, { type: "config_state", sessionId: session.localId, vendor: vendor, effort: value, model: session.model || "", mode: session.permissionMode || sm.currentPermissionMode || "default", betas: sm.currentBetas || [] });
|
|
2730
|
+
},
|
|
2731
|
+
});
|
|
2732
|
+
}
|
|
2529
2733
|
// Remember the pick per vendor (clamped) so vendor switches don't leak
|
|
2530
2734
|
// unsupported levels across sessions; sm.currentEffort stays as the
|
|
2531
2735
|
// display value for the session the user just configured.
|
|
@@ -2794,6 +2998,7 @@ function createSDKBridge(opts) {
|
|
|
2794
2998
|
startQuery: startQuery,
|
|
2795
2999
|
startQueryWithAcceptance: startQueryWithAcceptance,
|
|
2796
3000
|
pushMessage: pushMessage,
|
|
3001
|
+
cancelResponseRecovery: responseRecovery.cancel,
|
|
2797
3002
|
refreshSessionRuntime: refreshSessionRuntime,
|
|
2798
3003
|
refreshEnvironmentRuntime: refreshEnvironmentRuntime,
|
|
2799
3004
|
setModel: setModel,
|
|
@@ -430,6 +430,7 @@ function attachMessageProcessor(ctx) {
|
|
|
430
430
|
if (pushModule && block.name === "AskUserQuestion" && input.questions) {
|
|
431
431
|
var q = input.questions[0];
|
|
432
432
|
pushModule.sendPush({
|
|
433
|
+
sessionId: session.localId,
|
|
433
434
|
type: "ask_user",
|
|
434
435
|
slug: slug,
|
|
435
436
|
title: (mateDisplayName || "Claude") + " has a question",
|
|
@@ -715,6 +716,7 @@ function attachMessageProcessor(ctx) {
|
|
|
715
716
|
|
|
716
717
|
if (pushModule && !session._delegatedBy && !_suppressResponseNotification) {
|
|
717
718
|
pushModule.sendPush({
|
|
719
|
+
sessionId: session.localId,
|
|
718
720
|
type: "done",
|
|
719
721
|
slug: slug,
|
|
720
722
|
title: _doneTitle,
|