clay-server 5.2.0-beta.4 → 5.2.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/account-auth-socket.js +1 -0
- package/lib/builtin-mates.js +17 -14
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +1 -239
- package/lib/claude-jsonl-watcher.js +1 -204
- 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-skill-install.js +1 -33
- 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/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- 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 +78 -276
- package/lib/default-ai-runtime.js +4 -8
- package/lib/email-mcp-server.js +1 -1
- package/lib/issues-service.js +29 -15
- package/lib/kiro-defaults.js +1 -22
- 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-product-operations.js +46 -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 +4 -3
- package/lib/mcp-proxy.js +2 -32
- package/lib/mcp-query-bridge.js +1 -1
- package/lib/mcp-source-adapters.js +1 -91
- package/lib/mcp-source-context.js +1 -42
- package/lib/mcp-source-discovery.js +1 -169
- package/lib/mcp-source-plugins.js +1 -68
- package/lib/mcp-source-restrictions.js +1 -47
- package/lib/mcp-tool-policy.js +1 -26
- package/lib/notes-checklist.js +50 -0
- package/lib/notes.js +49 -3
- package/lib/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +24 -70
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +4 -2
- package/lib/project-connection.js +8 -7
- 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-http.js +4 -4
- 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-mcp.js +2 -2
- 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-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +4 -1
- 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-github.js +47 -12
- package/lib/project-session-history-actions.js +167 -0
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +64 -0
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +55 -0
- package/lib/project-sessions.js +82 -267
- package/lib/project-user-message.js +31 -1
- package/lib/project-vendor-login.js +6 -36
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +9 -2
- package/lib/project.js +95 -3
- package/lib/public/app.js +1 -0
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/messages.css +6 -2
- 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 +3 -0
- package/lib/public/css/sticky-notes.css +61 -1
- package/lib/public/index.html +1 -1
- package/lib/public/modules/admin-settings-projects.js +6 -2
- package/lib/public/modules/app-connection.js +8 -1
- package/lib/public/modules/app-favicon.js +11 -2
- package/lib/public/modules/app-header.js +4 -2
- package/lib/public/modules/app-loop-ui.js +2 -0
- package/lib/public/modules/app-message-router.js +1 -1
- package/lib/public/modules/app-messages.js +54 -8
- package/lib/public/modules/app-notifications.js +1 -2
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-projects.js +5 -0
- package/lib/public/modules/app-rate-limit.js +7 -27
- package/lib/public/modules/chat-render-runtime.js +3 -0
- 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 +1 -1
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/home-debate-planning.js +5 -5
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/mcp-connection-view.js +1 -1
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/session-create-form.js +10 -10
- 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 +65 -8
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- 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/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/tui-grab.js +1 -2
- 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/modules/vendor-login-browser.js +5 -3
- package/lib/public/modules/vendor-login.js +2 -2
- package/lib/public/modules/vendor-priority.js +15 -1
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +2 -0
- package/lib/safe-bash-commands.js +3 -45
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +334 -403
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +52 -17
- package/lib/sdk-quota-snapshot.js +1 -1
- package/lib/sdk-response-recovery.js +1 -0
- package/lib/sdk-worker.js +2 -677
- package/lib/server-admin.js +63 -16
- package/lib/server-dm.js +1 -1
- package/lib/server-global-ws.js +10 -20
- package/lib/server-home-chat-events.js +7 -3
- package/lib/server-home-chat.js +4 -16
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +3 -3
- package/lib/server-mates.js +25 -67
- 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.js +100 -30
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-fork-history.js +21 -0
- package/lib/session-github.js +9 -2
- package/lib/session-hygiene.js +3 -35
- package/lib/session-permission-mode.js +4 -3
- package/lib/session-skill-scope.js +11 -0
- package/lib/session-visibility.js +5 -2
- package/lib/sessions.js +27 -89
- package/lib/terminal-manager.js +52 -0
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +4 -0
- package/lib/vendor-login-browser.js +1 -11
- package/lib/workspace-query-access.js +4 -1
- package/lib/ws-schema.js +8 -2
- package/lib/yoke/acp-agent-profiles.js +5 -3
- package/lib/yoke/adapters/antigravity.js +3 -14
- package/lib/yoke/adapters/claude-query-contract.js +9 -0
- package/lib/yoke/adapters/claude.js +54 -50
- package/lib/yoke/adapters/codex-query-contract.js +24 -0
- package/lib/yoke/adapters/codex.js +53 -111
- package/lib/yoke/adapters/kiro.js +3 -1
- package/lib/yoke/adapters/muse-query-contract.js +7 -0
- package/lib/yoke/adapters/muse.js +122 -0
- package/lib/yoke/auth-events.js +17 -0
- package/lib/yoke/claude-hook-installer.js +267 -0
- package/lib/yoke/claude-jsonl-watcher.js +204 -0
- package/lib/yoke/claude-maintenance.js +55 -0
- package/lib/yoke/claude-permission-patterns.js +53 -0
- package/lib/yoke/claude-response-recovery.js +155 -0
- package/lib/yoke/claude-transcript-hygiene.js +34 -0
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/clay-skill-install.js +33 -0
- package/lib/yoke/cli-sessions.js +300 -0
- package/lib/yoke/codex-app-server.js +7 -12
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/configuration.js +13 -0
- package/lib/yoke/discovery.js +70 -0
- package/lib/yoke/errors.js +8 -0
- package/lib/yoke/host-environment.js +7 -0
- package/lib/yoke/index.js +9 -51
- package/lib/yoke/interface.js +116 -0
- package/lib/yoke/kiro-acp-server.js +5 -5
- package/lib/yoke/legacy-sessions.js +89 -0
- package/lib/yoke/login-protocol.js +25 -0
- package/lib/yoke/maintenance.js +12 -0
- package/lib/yoke/mcp-proxy.js +32 -0
- package/lib/yoke/mcp-source-adapters.js +91 -0
- package/lib/yoke/mcp-source-context.js +42 -0
- package/lib/yoke/mcp-source-discovery.js +169 -0
- package/lib/yoke/mcp-source-plugins.js +68 -0
- package/lib/yoke/mcp-source-restrictions.js +47 -0
- package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
- package/lib/yoke/model-preferences.js +6 -0
- package/lib/yoke/muse-artifacts.js +36 -0
- package/lib/yoke/muse-controls.js +50 -0
- package/lib/yoke/muse-input.js +64 -0
- package/lib/yoke/muse-items.js +157 -0
- package/lib/yoke/muse-policy.js +52 -0
- package/lib/yoke/muse-query.js +428 -0
- package/lib/yoke/muse-runtime.js +211 -0
- package/lib/yoke/muse-services.js +79 -0
- package/lib/yoke/muse-skills.js +79 -0
- package/lib/yoke/muse-turns.js +71 -0
- package/lib/yoke/options/acp.js +2 -0
- package/lib/yoke/options/antigravity.js +2 -0
- package/lib/yoke/options/claude.js +21 -0
- package/lib/yoke/options/codex-defaults.js +29 -0
- package/lib/yoke/options/codex-settings.js +21 -0
- package/lib/yoke/options/codex.js +6 -0
- package/lib/yoke/options/kiro-defaults.js +22 -0
- package/lib/yoke/options/kiro.js +5 -0
- package/lib/yoke/options/muse.js +5 -0
- package/lib/yoke/provider-contract.js +5 -0
- package/lib/yoke/providers/antigravity-executable.js +8 -0
- package/lib/yoke/providers/claude-executable.js +40 -0
- package/lib/yoke/providers/claude-model-descriptions.js +14 -0
- package/lib/yoke/providers/claude-process.js +97 -0
- package/lib/yoke/providers/claude-provision.js +75 -0
- package/lib/yoke/providers/codex-errors.js +8 -0
- package/lib/yoke/providers/muse-executable.js +17 -0
- package/lib/yoke/provisioning.js +6 -0
- package/lib/yoke/query-options.js +10 -0
- package/lib/yoke/response-recovery.js +41 -0
- package/lib/yoke/sdk-mcp-descriptors.js +37 -0
- package/lib/yoke/sdk-server-factory.js +7 -0
- package/lib/yoke/session-history.js +8 -0
- package/lib/yoke/session-tool-transport.js +34 -13
- package/lib/yoke/settings.js +23 -0
- package/lib/yoke/source-locations.js +4 -0
- package/lib/yoke/title-query.js +18 -7
- package/lib/yoke/tui-transcript-index.js +132 -0
- package/lib/yoke/usage.js +48 -0
- package/lib/yoke/user-input.js +13 -0
- package/lib/yoke/vendor-registry.js +81 -1
- package/package.json +3 -2
package/lib/sessions.js
CHANGED
|
@@ -3,7 +3,7 @@ var path = require("path");
|
|
|
3
3
|
var config = require("./config");
|
|
4
4
|
var utils = require("./utils");
|
|
5
5
|
var users = require("./users");
|
|
6
|
-
var
|
|
6
|
+
var providerDefaults = require("./yoke/settings").defaults();
|
|
7
7
|
var hygiene = require("./session-hygiene");
|
|
8
8
|
var backgroundTaskTiming = require("./background-task-timing");
|
|
9
9
|
var sessionProvenance = require("./session-provenance");
|
|
@@ -39,16 +39,16 @@ function createSessionManager(opts) {
|
|
|
39
39
|
var permissionRequestIndex = {}; // requestId -> sessionLocalId (O(1) lookup)
|
|
40
40
|
var capabilitiesByVendor = null; // set by sdk-bridge after adapter init
|
|
41
41
|
var defaultVendor = null; // set by sdk-bridge
|
|
42
|
-
var codexApproval =
|
|
43
|
-
var codexSandbox =
|
|
44
|
-
var codexWebSearch =
|
|
42
|
+
var codexApproval = providerDefaults.codexApproval;
|
|
43
|
+
var codexSandbox = providerDefaults.codexSandbox;
|
|
44
|
+
var codexWebSearch = providerDefaults.codexWebSearch;
|
|
45
45
|
|
|
46
46
|
// --- Session persistence (centralized in ~/.clay/sessions/{encoded-cwd}/) ---
|
|
47
47
|
var sessionsBase = opts.sessionsBase || path.join(config.CONFIG_DIR, "sessions");
|
|
48
48
|
var encodedCwd = utils.resolveEncodedDir(sessionsBase, cwd);
|
|
49
49
|
var sessionsDir = path.join(sessionsBase, encodedCwd);
|
|
50
50
|
fs.mkdirSync(sessionsDir, { recursive: true });
|
|
51
|
-
var cliSessionsDir = opts.cliSessionsDir ||
|
|
51
|
+
var cliSessionsDir = opts.cliSessionsDir || require("./yoke/legacy-sessions").directory(config.REAL_HOME, cwd);
|
|
52
52
|
var deletedCliSessionsPath = path.join(sessionsDir, "deleted-cli-sessions.json");
|
|
53
53
|
var deletedCliSessionIds = new Set();
|
|
54
54
|
try {
|
|
@@ -77,29 +77,6 @@ function createSessionManager(opts) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
function readCliTranscriptHead(filePath) {
|
|
81
|
-
var MAX_READ = 64 * 1024;
|
|
82
|
-
try {
|
|
83
|
-
var stat = fs.statSync(filePath);
|
|
84
|
-
var fd = fs.openSync(filePath, "r");
|
|
85
|
-
var bytesToRead = Math.min(stat.size, MAX_READ);
|
|
86
|
-
var buf = Buffer.alloc(bytesToRead);
|
|
87
|
-
fs.readSync(fd, buf, 0, bytesToRead, 0);
|
|
88
|
-
fs.closeSync(fd);
|
|
89
|
-
var lines = buf.toString("utf8").split("\n");
|
|
90
|
-
var events = [];
|
|
91
|
-
for (var i = 0; i < lines.length; i++) {
|
|
92
|
-
if (!lines[i]) continue;
|
|
93
|
-
try {
|
|
94
|
-
var event = JSON.parse(lines[i]);
|
|
95
|
-
if (event && typeof event === "object") events.push(event);
|
|
96
|
-
} catch (e) {}
|
|
97
|
-
}
|
|
98
|
-
return events;
|
|
99
|
-
} catch (e) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
80
|
|
|
104
81
|
// Auto-migrate sessions from legacy locations:
|
|
105
82
|
// v1: {cwd}/.claude-relay/sessions/
|
|
@@ -227,6 +204,11 @@ function createSessionManager(opts) {
|
|
|
227
204
|
if (session.homeDebatePlanning) metaObj.homeDebatePlanning = true;
|
|
228
205
|
if (session.homeDebatePhase) metaObj.homeDebatePhase = session.homeDebatePhase;
|
|
229
206
|
if (session.homeDebateInitialTopic) metaObj.homeDebateInitialTopic = session.homeDebateInitialTopic;
|
|
207
|
+
if (session.mateScheduleDraft) metaObj.mateScheduleDraft = session.mateScheduleDraft;
|
|
208
|
+
if (session.mateSchedules) metaObj.mateSchedules = session.mateSchedules;
|
|
209
|
+
if (session.clayWorkspaceReceipts) metaObj.clayWorkspaceReceipts = session.clayWorkspaceReceipts;
|
|
210
|
+
if (session.clayMateChatReceipts) metaObj.clayMateChatReceipts = session.clayMateChatReceipts;
|
|
211
|
+
if (session.claySchedulingReceipts) metaObj.claySchedulingReceipts = session.claySchedulingReceipts;
|
|
230
212
|
if (session.mateCreationMode) metaObj.mateCreationMode = true;
|
|
231
213
|
if (session.homeMateCreationPhase) metaObj.homeMateCreationPhase = session.homeMateCreationPhase;
|
|
232
214
|
if (session.homeClayEntryRequestId) metaObj.homeClayEntryRequestId = session.homeClayEntryRequestId;
|
|
@@ -386,6 +368,11 @@ function createSessionManager(opts) {
|
|
|
386
368
|
if (m.homeDebatePlanning) session.homeDebatePlanning = true;
|
|
387
369
|
if (m.homeDebatePhase) session.homeDebatePhase = m.homeDebatePhase;
|
|
388
370
|
if (m.homeDebateInitialTopic) session.homeDebateInitialTopic = m.homeDebateInitialTopic;
|
|
371
|
+
if (m.mateScheduleDraft) session.mateScheduleDraft = m.mateScheduleDraft;
|
|
372
|
+
if (m.mateSchedules) session.mateSchedules = m.mateSchedules;
|
|
373
|
+
if (Array.isArray(m.clayWorkspaceReceipts)) session.clayWorkspaceReceipts = m.clayWorkspaceReceipts;
|
|
374
|
+
if (Array.isArray(m.clayMateChatReceipts)) session.clayMateChatReceipts = m.clayMateChatReceipts;
|
|
375
|
+
if (Array.isArray(m.claySchedulingReceipts)) session.claySchedulingReceipts = m.claySchedulingReceipts;
|
|
389
376
|
if (m.mateCreationMode) session.mateCreationMode = true;
|
|
390
377
|
if (m.homeMateCreationPhase) session.homeMateCreationPhase = m.homeMateCreationPhase;
|
|
391
378
|
if (m.homeClayEntryRequestId) session.homeClayEntryRequestId = m.homeClayEntryRequestId;
|
|
@@ -460,9 +447,6 @@ function createSessionManager(opts) {
|
|
|
460
447
|
// - Warmup shape: 1 real "hi" prompt, optional automatic interruption,
|
|
461
448
|
// and 0 assistant messages (covered by daemon cleanup but defensive)
|
|
462
449
|
function adoptOrphanedCliSessions() {
|
|
463
|
-
var files;
|
|
464
|
-
try { files = fs.readdirSync(cliSessionsDir); } catch (e) { return; }
|
|
465
|
-
|
|
466
450
|
// Build set of cliSessionIds Clay already tracks
|
|
467
451
|
var knownCliIds = new Set();
|
|
468
452
|
sessions.forEach(function (s) {
|
|
@@ -471,56 +455,10 @@ function createSessionManager(opts) {
|
|
|
471
455
|
|
|
472
456
|
var adopted = 0;
|
|
473
457
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
var
|
|
477
|
-
|
|
478
|
-
if (deletedCliSessionIds.has(cliSid)) continue;
|
|
479
|
-
|
|
480
|
-
var fp = path.join(cliSessionsDir, files[i]);
|
|
481
|
-
var events = readCliTranscriptHead(fp);
|
|
482
|
-
if (!events) continue;
|
|
483
|
-
var userCount = 0;
|
|
484
|
-
var firstUserText = null;
|
|
485
|
-
var createdAtIso = null;
|
|
486
|
-
for (var li = 0; li < events.length; li++) {
|
|
487
|
-
var ev = events[li];
|
|
488
|
-
if (ev.type === "user" && ev.message && ev.message.role === "user") {
|
|
489
|
-
userCount++;
|
|
490
|
-
if (firstUserText == null) {
|
|
491
|
-
var c = ev.message.content;
|
|
492
|
-
if (typeof c === "string") {
|
|
493
|
-
firstUserText = c;
|
|
494
|
-
} else if (Array.isArray(c)) {
|
|
495
|
-
var parts = [];
|
|
496
|
-
for (var ci = 0; ci < c.length; ci++) {
|
|
497
|
-
if (c[ci] && c[ci].type === "text" && typeof c[ci].text === "string") parts.push(c[ci].text);
|
|
498
|
-
}
|
|
499
|
-
firstUserText = parts.join("");
|
|
500
|
-
}
|
|
501
|
-
if (ev.timestamp && !createdAtIso) createdAtIso = ev.timestamp;
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
if (userCount === 0) continue;
|
|
507
|
-
// Defensive warmup skip (daemon also cleans these)
|
|
508
|
-
if (hygiene.isClaudeWarmupTranscript(events)) continue;
|
|
509
|
-
|
|
510
|
-
// Title: first user message trimmed/truncated. Fall back to a
|
|
511
|
-
// neutral label so the sidebar entry is identifiable.
|
|
512
|
-
var title = (firstUserText || "").trim().replace(/\s+/g, " ");
|
|
513
|
-
if (title.length > 60) title = title.slice(0, 57) + "...";
|
|
514
|
-
if (!title) title = "Imported CLI session";
|
|
515
|
-
|
|
516
|
-
var createdAt = Date.now();
|
|
517
|
-
if (createdAtIso) {
|
|
518
|
-
var t = Date.parse(createdAtIso);
|
|
519
|
-
if (!isNaN(t)) createdAt = t;
|
|
520
|
-
}
|
|
521
|
-
var lastActivity = createdAt;
|
|
522
|
-
try { lastActivity = fs.statSync(fp).mtimeMs; } catch (e) {}
|
|
523
|
-
|
|
458
|
+
var candidates = require("./yoke/legacy-sessions").candidates(cliSessionsDir, knownCliIds, deletedCliSessionIds);
|
|
459
|
+
for (var i = 0; i < candidates.length; i++) {
|
|
460
|
+
var candidate = candidates[i], cliSid = candidate.id;
|
|
461
|
+
var title = candidate.title, createdAt = candidate.createdAt, lastActivity = candidate.lastActivity;
|
|
524
462
|
var localId = nextLocalId++;
|
|
525
463
|
var session = {
|
|
526
464
|
localId: localId,
|
|
@@ -538,7 +476,7 @@ function createSessionManager(opts) {
|
|
|
538
476
|
history: [],
|
|
539
477
|
messageUUIDs: [],
|
|
540
478
|
lastRewindUuid: null,
|
|
541
|
-
vendor:
|
|
479
|
+
vendor: candidate.vendor,
|
|
542
480
|
mode: "tui",
|
|
543
481
|
// Adopted from an external `claude` run in this cwd, not started by
|
|
544
482
|
// Clay. Notification emitters must stay silent for these until the
|
|
@@ -570,10 +508,7 @@ function createSessionManager(opts) {
|
|
|
570
508
|
var stale = [];
|
|
571
509
|
sessions.forEach(function (session) {
|
|
572
510
|
if (!session.adopted || !session.cliSessionId) return;
|
|
573
|
-
|
|
574
|
-
var events = readCliTranscriptHead(transcriptPath);
|
|
575
|
-
var missingEmptySource = !fs.existsSync(transcriptPath) && (!session.history || session.history.length === 0);
|
|
576
|
-
if (missingEmptySource || (events && hygiene.isClaudeWarmupTranscript(events))) stale.push(session.localId);
|
|
511
|
+
if (require("./yoke/legacy-sessions").obsolete(cliSessionsDir, session)) stale.push(session.localId);
|
|
577
512
|
});
|
|
578
513
|
for (var i = 0; i < stale.length; i++) deleteSessionQuiet(stale[i]);
|
|
579
514
|
if (stale.length > 0) {
|
|
@@ -867,7 +802,8 @@ function createSessionManager(opts) {
|
|
|
867
802
|
if (_item && (_item.type === "mention_user" || _item.type === "mention_response")) {
|
|
868
803
|
console.log("[DEBUG replayHistory] sending mention at index=" + i + " from=" + fromIndex + " total=" + total + " type=" + _item.type + " mate=" + (_item.mateName || ""));
|
|
869
804
|
}
|
|
870
|
-
var
|
|
805
|
+
var normalizedItem = require("./yoke/usage").clientEvent(_item, session.vendor || "claude");
|
|
806
|
+
var replayItem = transform ? transform(normalizedItem) : normalizedItem;
|
|
871
807
|
if (replayItem && typeof replayItem === "object") replayItem = Object.assign({}, replayItem, { _historyIndex: i });
|
|
872
808
|
_send(replayItem);
|
|
873
809
|
}
|
|
@@ -877,9 +813,11 @@ function createSessionManager(opts) {
|
|
|
877
813
|
var lastModelUsage = null;
|
|
878
814
|
var lastCost = null;
|
|
879
815
|
var lastStreamInputTokens = null;
|
|
816
|
+
var lastContext = null;
|
|
880
817
|
for (var j = total - 1; j >= 0; j--) {
|
|
881
818
|
if (session.history[j].type === "result") {
|
|
882
|
-
var r = session.history[j];
|
|
819
|
+
var r = require("./yoke/usage").clientEvent(session.history[j], session.vendor || "claude");
|
|
820
|
+
lastContext = r.context || null;
|
|
883
821
|
lastUsage = r.usage || null;
|
|
884
822
|
lastModelUsage = r.modelUsage || null;
|
|
885
823
|
lastCost = r.cost != null ? r.cost : null;
|
|
@@ -888,7 +826,7 @@ function createSessionManager(opts) {
|
|
|
888
826
|
}
|
|
889
827
|
}
|
|
890
828
|
|
|
891
|
-
_send({ type: "history_done", lastUsage: lastUsage, lastModelUsage: lastModelUsage, lastCost: lastCost, lastStreamInputTokens: lastStreamInputTokens, contextUsage: session.lastContextUsage ||
|
|
829
|
+
_send({ type: "history_done", lastUsage: lastUsage, lastModelUsage: lastModelUsage, lastCost: lastCost, lastStreamInputTokens: lastStreamInputTokens, context: lastContext, contextUsage: require("./yoke/usage").context(session.lastContextUsage, session.vendor || "claude") });
|
|
892
830
|
for (var vi = 0; vi < sessionViewedListeners.length; vi++) {
|
|
893
831
|
try { sessionViewedListeners[vi](session, targetWs, _send); } catch (e) {}
|
|
894
832
|
}
|
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/tool-llm.js
CHANGED
|
@@ -36,7 +36,7 @@ async function complete(opts) {
|
|
|
36
36
|
skipProjectInstructions: true,
|
|
37
37
|
skipSkills: true,
|
|
38
38
|
canUseTool: function () { return Promise.resolve({ behavior: "deny", message: "Capsule LLM calls cannot use tools." }); },
|
|
39
|
-
adapterOptions: {
|
|
39
|
+
adapterOptions: require("./yoke/query-options").map(adapter, { instructionSources: ["user"], readOnly: true, isolation: { user: opts.linuxUser || undefined } }),
|
|
40
40
|
},
|
|
41
41
|
});
|
|
42
42
|
return result.text;
|
|
@@ -1,132 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
// Build a per-session index of assistant text messages from a Claude Code
|
|
4
|
-
// TUI transcript (~/.claude/projects/{encoded-cwd}/{cliSessionId}.jsonl).
|
|
5
|
-
//
|
|
6
|
-
// The TUI message-grab feature uses this index on the client to map a
|
|
7
|
-
// hovered xterm region back to its original markdown source. We only
|
|
8
|
-
// extract assistant text blocks. Tool calls and tool results render in
|
|
9
|
-
// the terminal in a shape that's quite different from their JSONL form,
|
|
10
|
-
// so matching them would be noisy and not particularly useful.
|
|
11
|
-
//
|
|
12
|
-
// Codex sessions don't write transcripts at all; callers should skip
|
|
13
|
-
// indexing for non-claude vendors.
|
|
14
|
-
|
|
15
|
-
var fs = require("fs");
|
|
16
|
-
var path = require("path");
|
|
17
|
-
var utils = require("./utils");
|
|
18
|
-
var { REAL_HOME } = require("./config");
|
|
19
|
-
|
|
20
|
-
var encodeCwd = utils.encodeCwd;
|
|
21
|
-
|
|
22
|
-
// Min length of a normalized assistant message to bother indexing.
|
|
23
|
-
// Anything shorter ("ok", "sure", "yes") would generate too many false
|
|
24
|
-
// positives when matched against a hovered terminal block.
|
|
25
|
-
var MIN_MATCH_LEN = 20;
|
|
26
|
-
|
|
27
|
-
// Claude Code writes its JSONL under the *running user's* home, which
|
|
28
|
-
// is not the daemon's home in OS-isolation mode (where each Clay user
|
|
29
|
-
// gets a real Linux account like /home/clay-name). Callers from the
|
|
30
|
-
// project context resolve the session owner's home and pass it in;
|
|
31
|
-
// when no home is provided we fall back to REAL_HOME for single-user
|
|
32
|
-
// installs.
|
|
33
|
-
function transcriptFilePath(home, cwd, cliSessionId) {
|
|
34
|
-
if (!cwd || !cliSessionId) return null;
|
|
35
|
-
var base = home || REAL_HOME;
|
|
36
|
-
return path.join(base, ".claude", "projects", encodeCwd(cwd), cliSessionId + ".jsonl");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// matchKey is just whitespace-normalized raw markdown. We intentionally
|
|
40
|
-
// do NOT strip markdown decoration here.
|
|
41
|
-
//
|
|
42
|
-
// Reasoning: TUI rendering drops markdown markers (**bold** -> bold,
|
|
43
|
-
// `code` -> code, [text](url) -> text, etc.) and the visible text is
|
|
44
|
-
// therefore always a substring of the JSONL source's character stream.
|
|
45
|
-
// If we strip server-side we risk getting the rules wrong on corner
|
|
46
|
-
// cases (double-backtick code spans, list-bullet rendering quirks,
|
|
47
|
-
// nested formatting) and the resulting matchKey diverges from both
|
|
48
|
-
// sides at once. Leaving the source alone and letting the client do a
|
|
49
|
-
// multi-offset substring probe against block text is more robust and
|
|
50
|
-
// much less code.
|
|
51
|
-
function normalizeForMatch(s) {
|
|
52
|
-
if (!s) return "";
|
|
53
|
-
return s.replace(/\s+/g, " ").trim();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Stable per-message id. Claude's JSONL usually carries one of these but
|
|
57
|
-
// fall back to the parsed line index so the client always has a handle.
|
|
58
|
-
function messageId(obj, index) {
|
|
59
|
-
if (obj && obj.uuid) return String(obj.uuid);
|
|
60
|
-
if (obj && obj.message && obj.message.id) return String(obj.message.id);
|
|
61
|
-
return "msg-" + index;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Parse a single JSONL line into one assistant-text record, or null
|
|
65
|
-
// when the line isn't one we index (user prompts, tool_use blocks,
|
|
66
|
-
// tool_result records, etc.). Text-only assistant blocks get joined
|
|
67
|
-
// in order so a multi-block response surfaces as a single grabbable
|
|
68
|
-
// message.
|
|
69
|
-
function parseAssistantTextLine(line, index) {
|
|
70
|
-
var obj;
|
|
71
|
-
try { obj = JSON.parse(line); } catch (e) { return null; }
|
|
72
|
-
if (!obj || !obj.message) return null;
|
|
73
|
-
if (obj.message.role !== "assistant") return null;
|
|
74
|
-
if (!Array.isArray(obj.message.content)) return null;
|
|
75
|
-
|
|
76
|
-
var text = "";
|
|
77
|
-
for (var i = 0; i < obj.message.content.length; i++) {
|
|
78
|
-
var block = obj.message.content[i];
|
|
79
|
-
if (block && block.type === "text" && typeof block.text === "string") {
|
|
80
|
-
text += block.text;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
text = text.trim();
|
|
84
|
-
if (!text) return null;
|
|
85
|
-
|
|
86
|
-
var normalized = normalizeForMatch(text);
|
|
87
|
-
if (normalized.length < MIN_MATCH_LEN) return null;
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
id: messageId(obj, index),
|
|
91
|
-
text: text,
|
|
92
|
-
matchKey: normalized,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Read the whole transcript and return the assistant text index. The
|
|
97
|
-
// transcripts are small enough (KB to a few MB) that a sync read on
|
|
98
|
-
// session open or on a watcher-driven update is fine. We also return
|
|
99
|
-
// the mtime/size so callers can short-circuit re-reads when nothing
|
|
100
|
-
// changed.
|
|
101
|
-
function readAssistantIndex(home, cwd, cliSessionId) {
|
|
102
|
-
var file = transcriptFilePath(home, cwd, cliSessionId);
|
|
103
|
-
if (!file) return { messages: [], mtimeMs: 0, byteLength: 0 };
|
|
104
|
-
var raw;
|
|
105
|
-
var stat;
|
|
106
|
-
try {
|
|
107
|
-
raw = fs.readFileSync(file, "utf8");
|
|
108
|
-
stat = fs.statSync(file);
|
|
109
|
-
} catch (e) {
|
|
110
|
-
return { messages: [], mtimeMs: 0, byteLength: 0 };
|
|
111
|
-
}
|
|
112
|
-
var lines = raw.split("\n");
|
|
113
|
-
var messages = [];
|
|
114
|
-
for (var i = 0; i < lines.length; i++) {
|
|
115
|
-
if (!lines[i]) continue;
|
|
116
|
-
var entry = parseAssistantTextLine(lines[i], i);
|
|
117
|
-
if (entry) messages.push(entry);
|
|
118
|
-
}
|
|
119
|
-
return {
|
|
120
|
-
messages: messages,
|
|
121
|
-
mtimeMs: stat.mtimeMs || 0,
|
|
122
|
-
byteLength: stat.size || raw.length,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
module.exports = {
|
|
127
|
-
MIN_MATCH_LEN: MIN_MATCH_LEN,
|
|
128
|
-
transcriptFilePath: transcriptFilePath,
|
|
129
|
-
readAssistantIndex: readAssistantIndex,
|
|
130
|
-
parseAssistantTextLine: parseAssistantTextLine,
|
|
131
|
-
normalizeForMatch: normalizeForMatch,
|
|
132
|
-
};
|
|
1
|
+
module.exports = require("./yoke/tui-transcript-index");
|
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; });
|
|
@@ -7,17 +7,7 @@ var spawn = require("child_process").spawn;
|
|
|
7
7
|
var buildUserEnv = require("./build-user-env").buildUserEnv;
|
|
8
8
|
var wrapSpawnAsUser = require("./os-users").wrapSpawnAsUser;
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
var url = new URL(value);
|
|
13
|
-
var hosts = vendor === "codex" ? ["auth.openai.com"] : ["claude.ai", "claude.com", "console.anthropic.com", "platform.claude.com"];
|
|
14
|
-
if (url.protocol !== "https:" || url.username || url.password || hosts.indexOf(url.hostname) < 0) return null;
|
|
15
|
-
if (!url.searchParams.get("state") || !url.searchParams.get("code_challenge")) return null;
|
|
16
|
-
var callback = new URL(url.searchParams.get("redirect_uri"));
|
|
17
|
-
if (callback.protocol !== "http:" || ["localhost", "127.0.0.1", "[::1]"].indexOf(callback.hostname) < 0) return null;
|
|
18
|
-
return url.href;
|
|
19
|
-
} catch (e) { return null; }
|
|
20
|
-
}
|
|
10
|
+
var loginUrl = require("./yoke/login-protocol").loginUrl;
|
|
21
11
|
|
|
22
12
|
function createLoginBrowser(options) {
|
|
23
13
|
var initial = null;
|
|
@@ -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" },
|
|
@@ -9,8 +9,9 @@ var execFile = require("child_process").execFile;
|
|
|
9
9
|
var execFileSync = require("child_process").execFileSync;
|
|
10
10
|
|
|
11
11
|
function findOnPath(binaryName, overrideName) {
|
|
12
|
-
var
|
|
13
|
-
|
|
12
|
+
var discovery = require("./discovery");
|
|
13
|
+
var overridePath = overrideName && discovery.explicitEntry(process.env, overrideName, false);
|
|
14
|
+
if (overridePath !== undefined && overrideName) return overridePath;
|
|
14
15
|
try {
|
|
15
16
|
var command = process.platform === "win32" ? "where" : "which";
|
|
16
17
|
var out = execFileSync(command, [binaryName], {
|
|
@@ -18,7 +19,8 @@ function findOnPath(binaryName, overrideName) {
|
|
|
18
19
|
encoding: "utf8",
|
|
19
20
|
stdio: ["pipe", "pipe", "pipe"],
|
|
20
21
|
});
|
|
21
|
-
|
|
22
|
+
var resolved = out.trim().split(/\r?\n/)[0] || null;
|
|
23
|
+
return discovery.validEntry(resolved, false) ? resolved : null;
|
|
22
24
|
} catch (e) {
|
|
23
25
|
return null;
|
|
24
26
|
}
|
|
@@ -3,19 +3,7 @@ var childProcess = require("child_process");
|
|
|
3
3
|
var readline = require("readline");
|
|
4
4
|
var skillDiscovery = require("../skill-discovery");
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
if (process.env.ANTIGRAVITY_CLI_PATH) return process.env.ANTIGRAVITY_CLI_PATH;
|
|
8
|
-
try {
|
|
9
|
-
var command = process.platform === "win32" ? "where" : "which";
|
|
10
|
-
return childProcess.execFileSync(command, ["agy"], {
|
|
11
|
-
encoding: "utf8",
|
|
12
|
-
timeout: 3000,
|
|
13
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
14
|
-
}).trim().split(/\r?\n/)[0] || null;
|
|
15
|
-
} catch (e) {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
6
|
+
var findBinary = require("../providers/antigravity-executable").resolve;
|
|
19
7
|
|
|
20
8
|
function modelValue(model) {
|
|
21
9
|
if (typeof model === "string") return model;
|
|
@@ -427,7 +415,8 @@ function createAntigravityAdapter(opts) {
|
|
|
427
415
|
var adapter = {
|
|
428
416
|
vendor: "antigravity",
|
|
429
417
|
init: async function(initOpts) {
|
|
430
|
-
if (
|
|
418
|
+
if (opts.linuxUser || initOpts && initOpts.linuxUser) throw new Error("Antigravity does not support mapped OS-user execution.");
|
|
419
|
+
if (!binaryPath) binaryPath = findBinary({ env: initOpts && initOpts.env || opts.env || process.env });
|
|
431
420
|
if (!binaryPath) throw new Error("Antigravity CLI binary not found: agy");
|
|
432
421
|
var fetched = opts._fetchModels ? await opts._fetchModels(binaryPath, cwd) : await fetchModels(binaryPath, cwd);
|
|
433
422
|
if (fetched && fetched.length) cachedModels = fetched;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Init-free provider transport obligations, shared by the registry and adapter.
|
|
2
|
+
module.exports = {
|
|
3
|
+
questionInput: function(name, input) { return name === "AskUserQuestion" ? input : null; },
|
|
4
|
+
toolTransport: "sdk-mcp",
|
|
5
|
+
catalogLifetime: "query",
|
|
6
|
+
permissionModes: ["auto"],
|
|
7
|
+
mcpPermissionOverrides: true,
|
|
8
|
+
interruptionMessage: "Interrupted · What should Claude do instead?",
|
|
9
|
+
};
|