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
|
@@ -10,11 +10,14 @@ var epoch = 0;
|
|
|
10
10
|
var queue = Promise.resolve();
|
|
11
11
|
var pending = 0;
|
|
12
12
|
var timer = null;
|
|
13
|
+
var cookieSync = null;
|
|
14
|
+
var cookieTimer = null;
|
|
15
|
+
var closeRequested = false;
|
|
13
16
|
var activeActivity = null;
|
|
14
17
|
var pointerSequence = 0;
|
|
15
18
|
var viewport = { width: 1280, height: 800 };
|
|
16
19
|
function emit(message) {
|
|
17
|
-
if (!closing && process.stdout.writableLength <
|
|
20
|
+
if (!closing && process.stdout.writableLength < 32 * 1024 * 1024) process.stdout.write(JSON.stringify(message) + "\n");
|
|
18
21
|
}
|
|
19
22
|
function state() {
|
|
20
23
|
return { url: page ? policy.visibleUrl(page.url()) : "", width: viewport.width, height: viewport.height };
|
|
@@ -33,7 +36,7 @@ async function capture() {
|
|
|
33
36
|
} catch (e) {}
|
|
34
37
|
if (!closing) timer = setTimeout(capture, 250);
|
|
35
38
|
}
|
|
36
|
-
async function start() {
|
|
39
|
+
async function start(message) {
|
|
37
40
|
var channels = ["chrome", "msedge", null];
|
|
38
41
|
for (var i = 0; i < channels.length; i++) {
|
|
39
42
|
try { browser = await chromium.launch({ channel: channels[i] || undefined, headless: true, chromiumSandbox: true, timeout: 15000 }); break; }
|
|
@@ -45,6 +48,15 @@ async function start() {
|
|
|
45
48
|
var version = await cdp.send("Browser.getVersion");
|
|
46
49
|
await cdp.detach();
|
|
47
50
|
context = await browser.newContext({ viewport: viewport, acceptDownloads: false, userAgent: version.userAgent.replace("HeadlessChrome/", "Chrome/") });
|
|
51
|
+
if (message.storage) {
|
|
52
|
+
cookieSync = require("./shared-browser-storage-sync").attachStorageSync(context, message.storage, emit);
|
|
53
|
+
await cookieSync.start();
|
|
54
|
+
scheduleCookieSync();
|
|
55
|
+
} else if (message.cookies) {
|
|
56
|
+
cookieSync = require("./shared-browser-cookie-sync").attachCookieSync(context, message.cookies, emit);
|
|
57
|
+
await cookieSync.start();
|
|
58
|
+
scheduleCookieSync();
|
|
59
|
+
}
|
|
48
60
|
await context.addInitScript(require("./vendor-login-browser-passkeys").disableLoginPasskeys);
|
|
49
61
|
await context.route("**/*", function (route) {
|
|
50
62
|
var protocol = new URL(route.request().url()).protocol;
|
|
@@ -55,13 +67,19 @@ async function start() {
|
|
|
55
67
|
opened.setDefaultTimeout(10000);
|
|
56
68
|
opened.on("dialog", function (dialog) { dialog.dismiss().catch(function () {}); });
|
|
57
69
|
opened.on("download", function (download) { download.cancel().catch(function () {}); });
|
|
58
|
-
opened.on("framenavigated", function (frame) { if (frame === opened.mainFrame() && page === opened) emit(Object.assign({ type: "
|
|
70
|
+
opened.on("framenavigated", function (frame) { if (frame === opened.mainFrame() && page === opened) emit(Object.assign({ type: "navigation", navigationUrl: opened.url() }, state())); });
|
|
59
71
|
opened.on("close", function () { var pages = context.pages(); page = pages.length ? pages[pages.length - 1] : null; emit(Object.assign({ type: "state" }, state())); });
|
|
60
72
|
});
|
|
61
73
|
page = await context.newPage();
|
|
62
74
|
emit(Object.assign({ type: "ready" }, state()));
|
|
63
75
|
capture();
|
|
64
76
|
}
|
|
77
|
+
function scheduleCookieSync() {
|
|
78
|
+
if (closeRequested || closing) return;
|
|
79
|
+
cookieTimer = setTimeout(function () {
|
|
80
|
+
queue = queue.then(function () { return cookieSync.sync(); }).catch(function () { emit({ type: "error", error: "Could not save personal browser site data" }); }).finally(scheduleCookieSync);
|
|
81
|
+
}, 2000);
|
|
82
|
+
}
|
|
65
83
|
function reportActivity(phase) {
|
|
66
84
|
if (activeActivity) emit({ type: "activity", epoch: activeActivity.epoch, generation: activeActivity.generation,
|
|
67
85
|
activity: { id: activeActivity.id, text: activeActivity.text, phase: phase } });
|
|
@@ -126,6 +144,9 @@ async function command(message) {
|
|
|
126
144
|
}
|
|
127
145
|
async function close() {
|
|
128
146
|
if (closing) return;
|
|
147
|
+
closeRequested = true;
|
|
148
|
+
clearTimeout(cookieTimer);
|
|
149
|
+
if (cookieSync) await cookieSync.sync().catch(function () {});
|
|
129
150
|
closing = true;
|
|
130
151
|
clearTimeout(timer);
|
|
131
152
|
if (browser) await browser.close().catch(function () {});
|
|
@@ -133,11 +154,14 @@ async function close() {
|
|
|
133
154
|
}
|
|
134
155
|
var lines = require("readline").createInterface({ input: process.stdin });
|
|
135
156
|
lines.on("line", function (line) {
|
|
136
|
-
if (line.length >
|
|
157
|
+
if (line.length > 32 * 1024 * 1024 || closing) return;
|
|
137
158
|
var msg;
|
|
138
159
|
try { msg = JSON.parse(line); } catch (e) { return; }
|
|
160
|
+
if (msg.type === "cookies" || msg.type === "storage") { if (cookieSync) cookieSync.receive(msg); return; }
|
|
161
|
+
if (msg.type === "close") { closeRequested = true; clearTimeout(cookieTimer); queue = queue.then(close); return; }
|
|
162
|
+
if (closeRequested) return;
|
|
139
163
|
if (msg.type === "start") {
|
|
140
|
-
if (!browser) queue = queue.then(start).catch(function (e) { emit({ type: "error", error: e.message }); });
|
|
164
|
+
if (!browser) queue = queue.then(function () { return start(msg); }).catch(function (e) { emit({ type: "error", error: e.message }); });
|
|
141
165
|
} else if (msg.type === "viewing") viewing = !!msg.value;
|
|
142
166
|
else if (msg.type === "control") {
|
|
143
167
|
epoch = msg.epoch;
|
|
@@ -147,17 +171,29 @@ lines.on("line", function (line) {
|
|
|
147
171
|
});
|
|
148
172
|
} else if (msg.type === "settle") {
|
|
149
173
|
// Resolves only after every earlier queued command has finished and reported its telemetry.
|
|
150
|
-
queue = queue.then(function () {
|
|
174
|
+
queue = queue.then(async function () {
|
|
175
|
+
if (cookieSync) await cookieSync.sync();
|
|
176
|
+
emit({ type: "result", id: msg.id, value: { through: msg.id } });
|
|
177
|
+
}).catch(function (error) { emit({ type: "result", id: msg.id, error: error.message }); });
|
|
151
178
|
} else if (msg.type === "command") {
|
|
152
179
|
if (pending >= 80) { emit({ type: "result", id: msg.id, error: "Browser is busy; retry shortly" }); return; }
|
|
153
180
|
pending++;
|
|
154
|
-
queue = queue.then(
|
|
181
|
+
queue = queue.then(async function () {
|
|
182
|
+
if (cookieSync) await cookieSync.sync();
|
|
183
|
+
try { return await command(msg); }
|
|
184
|
+
finally { if (cookieSync) await cookieSync.sync(); }
|
|
185
|
+
}).then(function (value) {
|
|
155
186
|
reportActivity("complete"); activeActivity = null;
|
|
156
187
|
emit({ type: "result", id: msg.id, value: value });
|
|
157
188
|
emit(Object.assign({ type: "state" }, state()));
|
|
158
189
|
}, function (e) { reportActivity("failed"); activeActivity = null; emit({ type: "result", id: msg.id, error: e.message }); }).finally(function () { pending--; });
|
|
159
190
|
}
|
|
160
191
|
});
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
192
|
+
function requestClose() {
|
|
193
|
+
if (closeRequested) return;
|
|
194
|
+
closeRequested = true; clearTimeout(cookieTimer);
|
|
195
|
+
queue = queue.then(close);
|
|
196
|
+
}
|
|
197
|
+
lines.on("close", requestClose);
|
|
198
|
+
process.on("SIGTERM", requestClose);
|
|
199
|
+
process.on("SIGINT", requestClose);
|
package/lib/terminal-manager.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
var { createTerminal } = require("./terminal");
|
|
2
|
+
var crypto = require("crypto");
|
|
2
3
|
|
|
3
4
|
var MAX_TERMINALS = 10;
|
|
4
5
|
var SCROLLBACK_MAX = 50 * 1024; // 50 KB per terminal
|
|
@@ -48,6 +49,7 @@ function createTerminalManager(opts) {
|
|
|
48
49
|
var id = nextId++;
|
|
49
50
|
var session = {
|
|
50
51
|
id: id,
|
|
52
|
+
identity: crypto.randomUUID(),
|
|
51
53
|
pty: pty,
|
|
52
54
|
scrollback: [],
|
|
53
55
|
scrollbackSize: 0,
|
|
@@ -59,8 +61,11 @@ function createTerminalManager(opts) {
|
|
|
59
61
|
lastActivityAt: Date.now(),
|
|
60
62
|
exited: false,
|
|
61
63
|
exitCode: null,
|
|
64
|
+
exitWaiters: [],
|
|
62
65
|
subscribers: new Set(),
|
|
63
66
|
ownerWs: ownerWs || null,
|
|
67
|
+
ownerId: ownerWs && ownerWs._clayUser ? ownerWs._clayUser.id : opts && opts.ownerId || null,
|
|
68
|
+
osIdentity: osUserInfo ? JSON.stringify([osUserInfo.user, osUserInfo.uid, osUserInfo.gid, osUserInfo.home]) : null,
|
|
64
69
|
onExitHook: (opts && typeof opts.onExit === "function") ? opts.onExit : null,
|
|
65
70
|
onDataHook: (opts && typeof opts.onData === "function") ? opts.onData : null,
|
|
66
71
|
};
|
|
@@ -95,6 +100,7 @@ function createTerminalManager(opts) {
|
|
|
95
100
|
session.exited = true;
|
|
96
101
|
session.exitCode = e && e.exitCode != null ? e.exitCode : null;
|
|
97
102
|
session.pty = null;
|
|
103
|
+
session.exitWaiters.splice(0).forEach(function (resolve) { resolve(true); });
|
|
98
104
|
|
|
99
105
|
var msg = JSON.stringify({ type: "term_exited", id: id });
|
|
100
106
|
for (var ws of session.subscribers) {
|
|
@@ -204,6 +210,34 @@ function createTerminalManager(opts) {
|
|
|
204
210
|
if (terminals.size === 0) nextId = 1;
|
|
205
211
|
}
|
|
206
212
|
|
|
213
|
+
// Keep the terminal registered until its actual exit acknowledges shutdown.
|
|
214
|
+
async function closeAndWait(id, control) {
|
|
215
|
+
var session = terminals.get(id);
|
|
216
|
+
if (!session) throw new Error("Terminal closure cannot be confirmed: runtime is missing.");
|
|
217
|
+
if (control) { control.revalidate(); if (session.identity !== control.identity) throw new Error('The exact terminal identity changed.'); }
|
|
218
|
+
if (!session.exited) {
|
|
219
|
+
if (!session.pty) throw new Error("Terminal closure is unconfirmed.");
|
|
220
|
+
var timer, waiter;
|
|
221
|
+
var exited = new Promise(function (resolve, reject) {
|
|
222
|
+
waiter = resolve; session.exitWaiters.push(waiter);
|
|
223
|
+
timer = setTimeout(function () { reject(new Error("Terminal exit acknowledgement timed out.")); }, 5000);
|
|
224
|
+
});
|
|
225
|
+
try { session.pty.kill(); await exited; }
|
|
226
|
+
catch (error) { exited.catch(function () {}); throw error; }
|
|
227
|
+
finally { clearTimeout(timer); var index = session.exitWaiters.indexOf(waiter); if (index >= 0) session.exitWaiters.splice(index, 1); }
|
|
228
|
+
}
|
|
229
|
+
if (terminals.get(id) !== session) {
|
|
230
|
+
var replaced = new Error('Terminal was replaced during shutdown.');
|
|
231
|
+
if (control) replaced.productControlResult = { runtimeEffect: session.exited ? 'exited' : 'closure_unconfirmed', replacementRetained: true, retrySafe: false };
|
|
232
|
+
throw replaced;
|
|
233
|
+
}
|
|
234
|
+
if (control) {
|
|
235
|
+
try { control.revalidate(); }
|
|
236
|
+
catch (error) { error.productControlResult = { runtimeEffect: 'exited', retained: true, retrySafe: false }; throw error; }
|
|
237
|
+
}
|
|
238
|
+
close(id); return true;
|
|
239
|
+
}
|
|
240
|
+
|
|
207
241
|
function rename(id, title) {
|
|
208
242
|
var session = terminals.get(id);
|
|
209
243
|
if (!session) return;
|
|
@@ -298,6 +332,24 @@ function createTerminalManager(opts) {
|
|
|
298
332
|
write: write,
|
|
299
333
|
resize: resize,
|
|
300
334
|
close: close,
|
|
335
|
+
closeAndWait: closeAndWait,
|
|
336
|
+
inspect: function (id) {
|
|
337
|
+
var terminal = terminals.get(id);
|
|
338
|
+
return terminal ? { id: id, identity: terminal.identity, ownerId: terminal.ownerId, osIdentity: terminal.osIdentity, title: terminal.title, kind: terminal.kind, exited: terminal.exited, cols: terminal.cols, rows: terminal.rows, totalBytesWritten: terminal.totalBytesWritten } : null;
|
|
339
|
+
},
|
|
340
|
+
resizeExact: function (id, cols, rows, identity, revalidate) {
|
|
341
|
+
revalidate();
|
|
342
|
+
var terminal = terminals.get(id);
|
|
343
|
+
if (!terminal || terminal.identity !== identity || !terminal.pty) throw new Error('The exact terminal is unavailable for resizing.');
|
|
344
|
+
terminal.pty.resize(cols, rows);
|
|
345
|
+
revalidate();
|
|
346
|
+
if (terminals.get(id) !== terminal) throw new Error('Terminal was replaced during resize.');
|
|
347
|
+
terminal.cols = cols; terminal.rows = rows;
|
|
348
|
+
var message = JSON.stringify({ type: 'term_resized', id: id, cols: cols, rows: rows });
|
|
349
|
+
terminal.subscribers.forEach(function (ws) { if (ws.readyState === 1) ws.send(message); });
|
|
350
|
+
return true;
|
|
351
|
+
},
|
|
352
|
+
identity: function (id) { var terminal = terminals.get(id); return terminal ? terminal.identity : null; },
|
|
301
353
|
rename: rename,
|
|
302
354
|
list: list,
|
|
303
355
|
getScrollback: getScrollback,
|
package/lib/users-permissions.js
CHANGED
|
@@ -64,15 +64,12 @@ function attachPermissions(deps) {
|
|
|
64
64
|
// --- Project access helpers ---
|
|
65
65
|
|
|
66
66
|
function canAccessProject(userId, project) {
|
|
67
|
-
if (!project) return false;
|
|
67
|
+
if (!project || !userId || !findUserById(userId) || project.ownershipRecovery === "required") return false;
|
|
68
68
|
if (project.isMate === true || (typeof project.slug === "string" && project.slug.indexOf("mate-") === 0)) {
|
|
69
69
|
return !!userId && !!project.ownerId && project.ownerId === userId;
|
|
70
70
|
}
|
|
71
71
|
// Public projects are accessible to all authenticated users
|
|
72
72
|
if (!project.visibility || project.visibility === "public") return true;
|
|
73
|
-
// Admin always has access
|
|
74
|
-
var user = findUserById(userId);
|
|
75
|
-
if (user && user.role === "admin") return true;
|
|
76
73
|
// Owner always has access to their own project
|
|
77
74
|
if (project.ownerId && project.ownerId === userId) return true;
|
|
78
75
|
// Private project -- check allowedUsers
|
|
@@ -96,10 +93,7 @@ function attachPermissions(deps) {
|
|
|
96
93
|
return !!userId && !!session.ownerId && session.ownerId === userId;
|
|
97
94
|
}
|
|
98
95
|
if (session.userKnowledgeOwnerId) return !!userId && session.userKnowledgeOwnerId === userId && session.ownerId === userId;
|
|
99
|
-
//
|
|
100
|
-
var user = findUserById(userId);
|
|
101
|
-
if (user && user.role === "admin") return true;
|
|
102
|
-
// Sessions without ownerId are legacy -- only admin can see them
|
|
96
|
+
// Unowned historical sessions require explicit recovery; role is not ownership.
|
|
103
97
|
if (!session.ownerId) return false;
|
|
104
98
|
// Owner can always see their own sessions
|
|
105
99
|
if (session.ownerId === userId) return true;
|
package/lib/users.js
CHANGED
|
@@ -155,6 +155,10 @@ function getOtherUsers(excludeUserId) {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
function removeUser(userId) {
|
|
158
|
+
var registered = require("./config").loadConfig();
|
|
159
|
+
if (registered && (registered.projects || []).some(function (project) {
|
|
160
|
+
return !require("./project-ownership").isPersonal(project) && project.ownerId === userId;
|
|
161
|
+
})) return { error: "Transfer ordinary owned projects before deleting this account." };
|
|
158
162
|
var data = loadUsers();
|
|
159
163
|
var before = data.users.length;
|
|
160
164
|
data.users = data.users.filter(function (u) { return u.id !== userId; });
|
|
@@ -96,7 +96,10 @@ function attachWorkspaceQueryAccess(deps) {
|
|
|
96
96
|
// as ownership would let a stale status skip the authoritative record.
|
|
97
97
|
var access = record(status);
|
|
98
98
|
if (!access) return denied;
|
|
99
|
-
if (access.ownerId && access.ownerId === principal.userId)
|
|
99
|
+
if (access.ownerId && access.ownerId === principal.userId) {
|
|
100
|
+
var ownerPermitted = permitted(principal.userId, access);
|
|
101
|
+
return { owned: ownerPermitted, accessible: ownerPermitted };
|
|
102
|
+
}
|
|
100
103
|
return { owned: false, accessible: permitted(principal.userId, access) };
|
|
101
104
|
}
|
|
102
105
|
|
package/lib/ws-schema.js
CHANGED
|
@@ -495,10 +495,11 @@ var schema = {
|
|
|
495
495
|
"note_written": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Agent created or updated a sticky note" },
|
|
496
496
|
"note_update": { direction: "c2s", handler: "lib/project-user-message.js", description: "Update a sticky note" },
|
|
497
497
|
"note_updated": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Sticky note was updated" },
|
|
498
|
-
"
|
|
498
|
+
"note_update_result": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Correlated sticky note update result" },
|
|
499
|
+
"note_close": { direction: "c2s", handler: "lib/project-user-message.js", description: "Close a sticky note; human draft-aware requests remove empty notes, tool and legacy closes stay reversible" },
|
|
499
500
|
"note_reopen": { direction: "c2s", handler: "lib/project-user-message.js", description: "Reopen a closed sticky note" },
|
|
500
501
|
"note_delete": { direction: "c2s", handler: "lib/project-user-message.js", description: "Retired: older clients still send this; handled as a non-destructive close" },
|
|
501
|
-
"note_deleted": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "
|
|
502
|
+
"note_deleted": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "A sticky note was permanently removed after a human-authorized storage transaction" },
|
|
502
503
|
"note_list_request": { direction: "c2s", handler: "lib/project-user-message.js", description: "Request the full notes list" },
|
|
503
504
|
"note_bring_front": { direction: "c2s", handler: "lib/project-user-message.js", description: "Bring a note to front (update z-order)" },
|
|
504
505
|
"notes_list": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Full list of sticky notes" },
|
|
@@ -809,6 +810,11 @@ var schema = {
|
|
|
809
810
|
"default_vendor_get": { direction: "c2s", handler: "lib/server-default-vendor.js", description: "Read the authenticated user's New session vendor preference" },
|
|
810
811
|
"default_vendor_set": { direction: "c2s", handler: "lib/server-default-vendor.js", description: "Validate and persist the authenticated user's New session vendor preference" },
|
|
811
812
|
"default_vendor_state": { direction: "s2c", handler: "lib/public/modules/default-vendor.js", description: "Correlated or same-user-broadcast New session vendor preference" },
|
|
813
|
+
"clay_ui_ready": { direction: "c2s", handler: "lib/server-owner-ui.js", description: "Advertise exact owner UI navigation support on this socket" },
|
|
814
|
+
"clay_navigation_offer": { direction: "s2c", handler: "lib/public/modules/clay-owner-navigation.js", description: "Offer one exact reviewed navigation to a selected owner connection" },
|
|
815
|
+
"clay_navigation_claim": { direction: "c2s", handler: "lib/server-owner-ui.js", description: "Claim an offered navigation with live source/target revalidation" },
|
|
816
|
+
"clay_navigation_apply": { direction: "s2c", handler: "lib/public/modules/clay-owner-navigation.js", description: "Invoke the shared conversation navigator after live claim" },
|
|
817
|
+
"clay_navigation_ack": { direction: "c2s", handler: "lib/server-owner-ui.js", description: "Client invocation acknowledgement; never proof of visible rendering" },
|
|
812
818
|
"context_view_get": { direction: "c2s", handler: "lib/server-context-view.js", description: "Read the authenticated user's context display preference" },
|
|
813
819
|
"context_view_set": { direction: "c2s", handler: "lib/server-context-view.js", description: "Persist the authenticated user's context display preference" },
|
|
814
820
|
"context_view_state": { direction: "s2c", handler: "lib/public/modules/context-view-preference.js", description: "Correlated or same-user-broadcast context display preference" },
|
|
@@ -50,7 +50,7 @@ function fetchOpenCodeResolvedConfig(binaryPath, cwd, env) {
|
|
|
50
50
|
return new Promise(function(resolve, reject) {
|
|
51
51
|
execFile(binaryPath, ["debug", "config"], {
|
|
52
52
|
cwd: cwd || process.cwd(),
|
|
53
|
-
env: Object.assign({}, process.env,
|
|
53
|
+
env: env ? Object.assign({}, env) : process.env,
|
|
54
54
|
timeout: 30000,
|
|
55
55
|
maxBuffer: 4 * 1024 * 1024,
|
|
56
56
|
}, function(err, stdout) {
|
|
@@ -141,7 +141,7 @@ var ACP_AGENT_PROFILES = {
|
|
|
141
141
|
});
|
|
142
142
|
},
|
|
143
143
|
buildProcessOptions: function(ctx, base) {
|
|
144
|
-
var existing =
|
|
144
|
+
var existing = base.env ? base.env.OPENCODE_CONFIG_CONTENT : process.env.OPENCODE_CONFIG_CONTENT;
|
|
145
145
|
var config = {};
|
|
146
146
|
if (existing) config = JSON.parse(existing);
|
|
147
147
|
var agent = Object.assign({}, config.agent || {});
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// This is the ONLY file (besides claude-worker.js) that imports the SDK.
|
|
5
5
|
// Also manages worker processes for OS-level user isolation.
|
|
6
6
|
|
|
7
|
+
var attachWorkerStartup = require("../claude-worker-startup").attachWorkerStartup;
|
|
7
8
|
var bindQueryAbort = require("../query-abort").bindAbort;
|
|
8
9
|
var path = require("path");
|
|
9
10
|
var fs = require("fs");
|
|
@@ -600,6 +601,8 @@ function createQueryHandle(rawQuery, messageQueue, abortController) {
|
|
|
600
601
|
var correlation = claudeCorrelation.createCorrelation();
|
|
601
602
|
var closed = false;
|
|
602
603
|
var removeAbort = function () {};
|
|
604
|
+
var resolveStopped;
|
|
605
|
+
var stopped = new Promise(function(resolve) { resolveStopped = resolve; });
|
|
603
606
|
var handle = {
|
|
604
607
|
// Opaque adapter state (null for in-process queries)
|
|
605
608
|
_adapterState: null,
|
|
@@ -610,12 +613,13 @@ function createQueryHandle(rawQuery, messageQueue, abortController) {
|
|
|
610
613
|
return {
|
|
611
614
|
next: function() {
|
|
612
615
|
return rawIter.next().then(function(result) {
|
|
613
|
-
if (result.done) { closed = true; removeAbort(); }
|
|
616
|
+
if (result.done) { closed = true; removeAbort(); resolveStopped(); }
|
|
614
617
|
if (result.done) return result;
|
|
615
618
|
return { value: correlation.result(result.value, flattenEvent(result.value)), done: false };
|
|
616
619
|
}, function(err) {
|
|
617
620
|
closed = true;
|
|
618
621
|
removeAbort();
|
|
622
|
+
resolveStopped();
|
|
619
623
|
throw err;
|
|
620
624
|
});
|
|
621
625
|
},
|
|
@@ -715,6 +719,11 @@ function createQueryHandle(rawQuery, messageQueue, abortController) {
|
|
|
715
719
|
}
|
|
716
720
|
},
|
|
717
721
|
|
|
722
|
+
stopAndWait: function() {
|
|
723
|
+
handle.abort();
|
|
724
|
+
return stopped;
|
|
725
|
+
},
|
|
726
|
+
|
|
718
727
|
close: function() {
|
|
719
728
|
closed = true;
|
|
720
729
|
removeAbort();
|
|
@@ -818,9 +827,7 @@ function spawnWorker(linuxUser, workerScriptPath, cwd) {
|
|
|
818
827
|
buffer: "",
|
|
819
828
|
};
|
|
820
829
|
|
|
821
|
-
worker
|
|
822
|
-
worker._readyResolve = resolve;
|
|
823
|
-
});
|
|
830
|
+
attachWorkerStartup(worker);
|
|
824
831
|
|
|
825
832
|
// Resolves when the worker process actually exits.
|
|
826
833
|
// Used to prevent spawning a new worker before the old one finishes
|
|
@@ -860,7 +867,15 @@ function spawnWorker(linuxUser, workerScriptPath, cwd) {
|
|
|
860
867
|
});
|
|
861
868
|
connection.on("error", function(err) {
|
|
862
869
|
console.error("[yoke/claude] Worker connection error:", err.message);
|
|
870
|
+
if (worker._readyReject) worker._readyReject(err);
|
|
863
871
|
});
|
|
872
|
+
connection.on("close", function() {
|
|
873
|
+
if (worker._readyReject) worker._readyReject(new Error("Claude worker connection closed before ready."));
|
|
874
|
+
});
|
|
875
|
+
});
|
|
876
|
+
worker.server.on("error", function(error) {
|
|
877
|
+
if (worker._readyReject) worker._readyReject(error);
|
|
878
|
+
cleanupWorker(worker);
|
|
864
879
|
});
|
|
865
880
|
|
|
866
881
|
worker.server.listen(socketPath, function() {
|
|
@@ -892,6 +907,14 @@ function spawnWorker(linuxUser, workerScriptPath, cwd) {
|
|
|
892
907
|
});
|
|
893
908
|
worker.process = spawn(workerSpawn.command, workerSpawn.args, workerSpawn.options);
|
|
894
909
|
|
|
910
|
+
worker.process.on("error", function(error) {
|
|
911
|
+
if (worker._readyReject) worker._readyReject(error);
|
|
912
|
+
worker.messageHandlers.forEach(function(handler) { handler({ type: "query_error", error: error.message, _fallback: true }); });
|
|
913
|
+
cleanupWorker(worker);
|
|
914
|
+
// Only a spawn failure proves that no child execution exists. Other
|
|
915
|
+
// ChildProcess errors (for example a failed signal) are not exit evidence.
|
|
916
|
+
if (!worker.process.pid && worker._exitResolve) { worker._exitResolve(); worker._exitResolve = null; }
|
|
917
|
+
});
|
|
895
918
|
worker.process.stdout.on("data", function(data) {
|
|
896
919
|
console.log("[sdk-worker:" + linuxUser + "] " + data.toString().trim());
|
|
897
920
|
});
|
|
@@ -905,9 +928,8 @@ function spawnWorker(linuxUser, workerScriptPath, cwd) {
|
|
|
905
928
|
worker.process.on("exit", function(code, signal) {
|
|
906
929
|
console.log("[yoke/claude] Worker for " + linuxUser + " exited (code=" + code + ", signal=" + signal + ")" + (worker._stderrBuf ? " stderr: " + worker._stderrBuf.trim() : ""));
|
|
907
930
|
// Reject readyPromise if worker dies before becoming ready
|
|
908
|
-
if (!worker.ready && worker.
|
|
909
|
-
worker.
|
|
910
|
-
// Let the readyPromise hang; the query_error handler will clean up
|
|
931
|
+
if (!worker.ready && worker._readyReject) {
|
|
932
|
+
worker._readyReject(new Error("Claude worker exited before ready (code=" + code + ")."));
|
|
911
933
|
}
|
|
912
934
|
// Notify message handlers about unexpected exit so sessions don't hang.
|
|
913
935
|
// Always dispatch a fallback query_error. The handler is idempotent:
|
|
@@ -1082,6 +1104,9 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool,
|
|
|
1082
1104
|
var iterWaiting = null;
|
|
1083
1105
|
var iterEnded = false;
|
|
1084
1106
|
var iterError = null;
|
|
1107
|
+
var resolveStopped;
|
|
1108
|
+
var stopped = new Promise(function(resolve) { resolveStopped = resolve; });
|
|
1109
|
+
if (worker.exitPromise) worker.exitPromise.then(resolveStopped);
|
|
1085
1110
|
|
|
1086
1111
|
// Pending request/response correlation for handle methods that need a
|
|
1087
1112
|
// result from the worker (e.g. rewindFiles). Each entry is keyed by a
|
|
@@ -1299,6 +1324,8 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool,
|
|
|
1299
1324
|
}
|
|
1300
1325
|
|
|
1301
1326
|
case "query_done":
|
|
1327
|
+
if (worker._abortTimeout) { clearTimeout(worker._abortTimeout); worker._abortTimeout = null; }
|
|
1328
|
+
resolveStopped();
|
|
1302
1329
|
rejectPendingPermissionModes(new Error("Worker query ended while changing permission mode"));
|
|
1303
1330
|
console.log("[yoke/claude] IPC query_done received, pid=" + (worker.process ? worker.process.pid : "?"));
|
|
1304
1331
|
worker._queryEnded = true;
|
|
@@ -1306,6 +1333,10 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool,
|
|
|
1306
1333
|
break;
|
|
1307
1334
|
|
|
1308
1335
|
case "query_error": {
|
|
1336
|
+
if (!msg._fallback) {
|
|
1337
|
+
if (worker._abortTimeout) { clearTimeout(worker._abortTimeout); worker._abortTimeout = null; }
|
|
1338
|
+
resolveStopped();
|
|
1339
|
+
}
|
|
1309
1340
|
rejectPendingPermissionModes(new Error(msg.error || "Worker exited while changing permission mode"));
|
|
1310
1341
|
console.log("[yoke/claude] IPC query_error received, pid=" + (worker.process ? worker.process.pid : "?") + " _fallback=" + !!msg._fallback + " _queryEnded=" + worker._queryEnded + " error=" + (msg.error || "").substring(0, 100));
|
|
1311
1342
|
// Skip fallback errors from exit handler if we already handled the real one
|
|
@@ -1472,6 +1503,11 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool,
|
|
|
1472
1503
|
}, 5000);
|
|
1473
1504
|
},
|
|
1474
1505
|
|
|
1506
|
+
stopAndWait: function() {
|
|
1507
|
+
handle.abort();
|
|
1508
|
+
return stopped;
|
|
1509
|
+
},
|
|
1510
|
+
|
|
1475
1511
|
close: function() {
|
|
1476
1512
|
rejectPendingPermissionModes(new Error("Worker query closed while changing permission mode"));
|
|
1477
1513
|
// End the iterator
|
|
@@ -1909,7 +1945,10 @@ function createClaudeAdapter(opts) {
|
|
|
1909
1945
|
|
|
1910
1946
|
// Wait for worker to be ready before sending query_start
|
|
1911
1947
|
if (!reusingWorker) {
|
|
1912
|
-
await worker.readyPromise;
|
|
1948
|
+
try { await worker.readyPromise; } catch (error) {
|
|
1949
|
+
worker.kill();
|
|
1950
|
+
throw error;
|
|
1951
|
+
}
|
|
1913
1952
|
}
|
|
1914
1953
|
|
|
1915
1954
|
// Build serializable query options (no callbacks, no AbortController).
|