clay-server 5.2.0-beta.5 → 5.2.0-beta.7
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/claude-hook-installer.js +1 -267
- package/lib/claude-jsonl-watcher.js +1 -204
- package/lib/clay-control-presentation-binding.js +96 -0
- package/lib/clay-control-presentation.js +128 -0
- package/lib/clay-control-target-projection.js +26 -0
- package/lib/clay-mate-chat.js +1 -0
- package/lib/clay-mate-knowledge.js +1 -1
- package/lib/clay-product-control-tools.js +1 -1
- package/lib/clay-product-control.js +22 -12
- package/lib/clay-project-records.js +2 -1
- package/lib/clay-scheduling.js +1 -1
- package/lib/clay-screen-controls.js +13 -5
- package/lib/clay-skill-install.js +1 -33
- package/lib/clay-workspace-controls.js +2 -1
- package/lib/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- package/lib/contextual-screen-snapshot.js +38 -0
- package/lib/daemon.js +5 -55
- package/lib/default-ai-runtime.js +4 -8
- package/lib/email-mcp-server.js +1 -1
- package/lib/kiro-defaults.js +1 -22
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- 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/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +4 -65
- package/lib/project-connection.js +14 -10
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-filesystem.js +5 -1
- package/lib/project-http.js +7 -4
- package/lib/project-mcp.js +2 -2
- package/lib/project-notifications.js +5 -4
- package/lib/project-pair-result-delivery.js +2 -2
- package/lib/project-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +3 -1
- package/lib/project-product-control.js +3 -1
- package/lib/project-scheduled-messages.js +4 -4
- package/lib/project-scheduled-task-control.js +1 -1
- package/lib/project-session-document.js +20 -5
- package/lib/project-session-history-actions.js +5 -3
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +2 -1
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +2 -1
- package/lib/project-sessions.js +18 -26
- package/lib/project-shared-browser.js +22 -5
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +37 -0
- package/lib/project-vendor-login.js +6 -36
- package/lib/project-workspace-query.js +11 -1
- package/lib/project.js +24 -7
- package/lib/public/app.js +25 -0
- package/lib/public/appearance-bootstrap.js +2 -0
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/css/messages.css +6 -2
- package/lib/public/modules/app-favicon.js +18 -9
- 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 +5 -1
- package/lib/public/modules/app-messages.js +50 -6
- package/lib/public/modules/app-notifications.js +11 -5
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-projects.js +3 -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-control-activity.js +214 -0
- package/lib/public/modules/clay-control-copy.js +36 -0
- package/lib/public/modules/clay-control-detail-targets.js +44 -0
- package/lib/public/modules/clay-control-object-targets.js +52 -0
- package/lib/public/modules/clay-control-target-visibility.js +12 -0
- package/lib/public/modules/clay-control-targets.js +44 -0
- package/lib/public/modules/clay-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +11 -2
- package/lib/public/modules/clay-session-links.js +31 -0
- package/lib/public/modules/clay-studio-bridge.js +20 -0
- package/lib/public/modules/clay-studio-document.js +67 -0
- package/lib/public/modules/clay-studio-render.js +144 -0
- package/lib/public/modules/clay-tool-presentation.js +4 -0
- package/lib/public/modules/command-palette.js +26 -31
- package/lib/public/modules/contextual-ask-session.js +26 -0
- package/lib/public/modules/contextual-clay-geometry.js +155 -0
- package/lib/public/modules/contextual-clay-session.js +130 -0
- package/lib/public/modules/contextual-clay-workspace.js +157 -0
- package/lib/public/modules/contextual-clay.js +237 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +115 -0
- package/lib/public/modules/contextual-mate-hint.js +40 -0
- package/lib/public/modules/contextual-mate-identity.js +23 -0
- package/lib/public/modules/contextual-mate-sessions.js +134 -0
- package/lib/public/modules/contextual-search.js +137 -0
- package/lib/public/modules/contextual-session-citations.js +58 -0
- package/lib/public/modules/filebrowser.js +20 -1
- package/lib/public/modules/generation-stop.js +8 -5
- package/lib/public/modules/git-panel.js +3 -1
- package/lib/public/modules/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +35 -1
- package/lib/public/modules/issues-render.js +3 -2
- package/lib/public/modules/knowledge-db-workbench.js +4 -4
- package/lib/public/modules/markdown.js +2 -34
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/mcp-connection-view.js +1 -1
- package/lib/public/modules/message-delivery.js +10 -0
- package/lib/public/modules/pane-bridge.js +2 -2
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/product-review.js +26 -0
- package/lib/public/modules/project-chat-identity.js +13 -4
- package/lib/public/modules/project-logs-render.js +3 -0
- package/lib/public/modules/project-mate-navigation.js +58 -21
- package/lib/public/modules/scheduled-tasks.js +2 -0
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/search-clay-chat.js +5 -454
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/shared-browser.js +2 -0
- package/lib/public/modules/sidebar-mobile.js +4 -3
- package/lib/public/modules/sidebar-projects.js +1 -0
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-view.js +7 -16
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/tools.js +6 -2
- package/lib/public/modules/tui-grab.js +1 -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/modules/wireframe-workbench.js +5 -2
- 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/sdk-bridge.js +131 -395
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +50 -17
- package/lib/sdk-quota-snapshot.js +1 -1
- package/lib/sdk-response-recovery.js +1 -155
- package/lib/sdk-worker.js +2 -677
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-home-chat.js +7 -1
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +12 -0
- package/lib/server-owner-ui.js +49 -8
- package/lib/server-settings.js +2 -0
- package/lib/server.js +18 -1
- package/lib/session-fork-history.js +21 -0
- 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/sessions.js +24 -89
- package/lib/terminal-manager.js +18 -11
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users.js +3 -0
- package/lib/vendor-login-browser.js +1 -11
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +10 -0
- 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 +7 -42
- package/lib/yoke/adapters/codex-query-contract.js +24 -0
- package/lib/yoke/adapters/codex.js +1 -0
- 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 +271 -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/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/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 +31 -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
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
var fs = require("fs");
|
|
2
|
+
var path = require("path");
|
|
3
|
+
var readline = require("readline");
|
|
4
|
+
var utils = require("../utils");
|
|
5
|
+
var { REAL_HOME } = require("../config");
|
|
6
|
+
|
|
7
|
+
var encodeCwd = utils.encodeCwd;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Parse the first ~20 lines of a CLI session JSONL file to extract metadata.
|
|
11
|
+
* Returns null if the file can't be parsed or has no user messages.
|
|
12
|
+
*/
|
|
13
|
+
function parseSessionFile(filePath, maxLines) {
|
|
14
|
+
if (maxLines == null) maxLines = 20;
|
|
15
|
+
return new Promise(function (resolve) {
|
|
16
|
+
var sessionId = path.basename(filePath, ".jsonl");
|
|
17
|
+
var result = {
|
|
18
|
+
sessionId: sessionId,
|
|
19
|
+
firstPrompt: "",
|
|
20
|
+
model: null,
|
|
21
|
+
gitBranch: null,
|
|
22
|
+
startTime: null,
|
|
23
|
+
lastActivity: null,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
var lineCount = 0;
|
|
27
|
+
var foundUser = false;
|
|
28
|
+
var stream;
|
|
29
|
+
try {
|
|
30
|
+
stream = fs.createReadStream(filePath, { encoding: "utf8" });
|
|
31
|
+
} catch (e) {
|
|
32
|
+
return resolve(null);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
var rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
36
|
+
|
|
37
|
+
rl.on("line", function (line) {
|
|
38
|
+
lineCount++;
|
|
39
|
+
if (lineCount > maxLines) {
|
|
40
|
+
rl.close();
|
|
41
|
+
stream.destroy();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
var obj;
|
|
46
|
+
try { obj = JSON.parse(line); } catch (e) { return; }
|
|
47
|
+
|
|
48
|
+
// Skip file-history-snapshot, queue-operation, and other non-message records
|
|
49
|
+
if (obj.type === "user" && obj.message && obj.message.role === "user") {
|
|
50
|
+
if (!foundUser) {
|
|
51
|
+
foundUser = true;
|
|
52
|
+
result.sessionId = obj.sessionId || sessionId;
|
|
53
|
+
result.gitBranch = obj.gitBranch || null;
|
|
54
|
+
if (obj.timestamp) result.startTime = obj.timestamp;
|
|
55
|
+
var content = obj.message.content || "";
|
|
56
|
+
if (typeof content === "string") {
|
|
57
|
+
result.firstPrompt = content.substring(0, 100);
|
|
58
|
+
} else if (Array.isArray(content)) {
|
|
59
|
+
for (var i = 0; i < content.length; i++) {
|
|
60
|
+
if (content[i].type === "text" && content[i].text) {
|
|
61
|
+
result.firstPrompt = content[i].text.substring(0, 100);
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Track latest user timestamp for lastActivity
|
|
68
|
+
if (obj.timestamp) result.lastActivity = obj.timestamp;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Extract model from first assistant message
|
|
72
|
+
if (!result.model && obj.message && obj.message.role === "assistant" && obj.message.model) {
|
|
73
|
+
result.model = obj.message.model;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
rl.on("close", function () {
|
|
78
|
+
if (!foundUser) return resolve(null);
|
|
79
|
+
|
|
80
|
+
// Use file mtime as fallback for lastActivity, or as a better proxy
|
|
81
|
+
// since we only read the first ~20 lines
|
|
82
|
+
try {
|
|
83
|
+
var stat = fs.statSync(filePath);
|
|
84
|
+
var mtime = stat.mtime.toISOString();
|
|
85
|
+
// File mtime is always more accurate for "last activity" since we
|
|
86
|
+
// don't read the entire file
|
|
87
|
+
result.lastActivity = mtime;
|
|
88
|
+
} catch (e) {}
|
|
89
|
+
|
|
90
|
+
resolve(result);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
rl.on("error", function () {
|
|
94
|
+
resolve(null);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
stream.on("error", function () {
|
|
98
|
+
rl.close();
|
|
99
|
+
resolve(null);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* List CLI sessions for a given project directory.
|
|
106
|
+
* Reads ~/.claude/projects/{encoded-cwd}/ and parses JSONL metadata.
|
|
107
|
+
* Returns array sorted by lastActivity descending (most recent first).
|
|
108
|
+
*/
|
|
109
|
+
function listCliSessions(cwd) {
|
|
110
|
+
var encoded = encodeCwd(cwd);
|
|
111
|
+
var projectDir = path.join(REAL_HOME, ".claude", "projects", encoded);
|
|
112
|
+
|
|
113
|
+
return new Promise(function (resolve) {
|
|
114
|
+
fs.readdir(projectDir, { withFileTypes: true }, function (err, entries) {
|
|
115
|
+
if (err) return resolve([]);
|
|
116
|
+
|
|
117
|
+
var jsonlFiles = [];
|
|
118
|
+
for (var i = 0; i < entries.length; i++) {
|
|
119
|
+
if (entries[i].isFile() && entries[i].name.endsWith(".jsonl")) {
|
|
120
|
+
jsonlFiles.push(path.join(projectDir, entries[i].name));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (jsonlFiles.length === 0) return resolve([]);
|
|
125
|
+
|
|
126
|
+
var pending = jsonlFiles.length;
|
|
127
|
+
var results = [];
|
|
128
|
+
|
|
129
|
+
for (var j = 0; j < jsonlFiles.length; j++) {
|
|
130
|
+
parseSessionFile(jsonlFiles[j]).then(function (session) {
|
|
131
|
+
if (session) results.push(session);
|
|
132
|
+
pending--;
|
|
133
|
+
if (pending === 0) {
|
|
134
|
+
results.sort(function (a, b) {
|
|
135
|
+
var ta = a.lastActivity || "";
|
|
136
|
+
var tb = b.lastActivity || "";
|
|
137
|
+
return ta < tb ? 1 : ta > tb ? -1 : 0;
|
|
138
|
+
});
|
|
139
|
+
resolve(results);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get the most recent CLI session for a given project directory.
|
|
149
|
+
* Returns the session object or null if none found.
|
|
150
|
+
*/
|
|
151
|
+
function getMostRecentCliSession(cwd) {
|
|
152
|
+
return listCliSessions(cwd).then(function (sessions) {
|
|
153
|
+
return sessions.length > 0 ? sessions[0] : null;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Extract user message text from a CLI JSONL content field.
|
|
159
|
+
* Content can be a string or an array of content blocks.
|
|
160
|
+
*/
|
|
161
|
+
function extractText(content) {
|
|
162
|
+
if (typeof content === "string") return content;
|
|
163
|
+
if (!Array.isArray(content)) return "";
|
|
164
|
+
var parts = [];
|
|
165
|
+
for (var i = 0; i < content.length; i++) {
|
|
166
|
+
if (content[i].type === "text" && content[i].text) {
|
|
167
|
+
parts.push(content[i].text);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return parts.join("");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Read a full CLI session JSONL file and convert it to relay-compatible
|
|
175
|
+
* history entries (user_message, delta, tool_start, tool_executing, tool_result).
|
|
176
|
+
* Returns a Promise that resolves to an array of history entries.
|
|
177
|
+
*/
|
|
178
|
+
// Convert one parsed CLI jsonl record into client history entries. Shared by
|
|
179
|
+
// the streaming (async) and synchronous readers so the format stays in lockstep.
|
|
180
|
+
// `state.toolCounter` carries across lines to mint unique tool ids.
|
|
181
|
+
function appendCliRecord(obj, state, history) {
|
|
182
|
+
if (!obj || !obj.message) return;
|
|
183
|
+
|
|
184
|
+
// User prompt
|
|
185
|
+
if (obj.type === "user" && obj.message.role === "user") {
|
|
186
|
+
// Skip tool_result records (they have type "user" but content is tool results)
|
|
187
|
+
var content = obj.message.content;
|
|
188
|
+
if (Array.isArray(content) && content.length > 0 && content[0].type === "tool_result") {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
var text = extractText(content);
|
|
192
|
+
if (text) history.push({ type: "user_message", text: text });
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Assistant message
|
|
197
|
+
if (obj.message.role === "assistant" && Array.isArray(obj.message.content)) {
|
|
198
|
+
for (var i = 0; i < obj.message.content.length; i++) {
|
|
199
|
+
var block = obj.message.content[i];
|
|
200
|
+
|
|
201
|
+
if (block.type === "text" && block.text) {
|
|
202
|
+
history.push({ type: "delta", text: block.text });
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (block.type === "tool_use") {
|
|
206
|
+
var toolId = "cli-tool-" + (++state.toolCounter);
|
|
207
|
+
var toolName = block.name || "Tool";
|
|
208
|
+
history.push({ type: "tool_start", id: toolId, name: toolName });
|
|
209
|
+
history.push({
|
|
210
|
+
type: "tool_executing",
|
|
211
|
+
id: toolId,
|
|
212
|
+
name: toolName,
|
|
213
|
+
input: block.input || {},
|
|
214
|
+
});
|
|
215
|
+
// Emit ask_user_answered so the client re-enables input after replaying AskUserQuestion
|
|
216
|
+
if (toolName === "AskUserQuestion") {
|
|
217
|
+
history.push({ type: "ask_user_answered", toolId: toolId });
|
|
218
|
+
}
|
|
219
|
+
history.push({ type: "tool_result", id: toolId, content: "" });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function readCliSessionHistory(home, cwd, sessionId) {
|
|
226
|
+
var encoded = encodeCwd(cwd);
|
|
227
|
+
var filePath = path.join(home || REAL_HOME, ".claude", "projects", encoded, sessionId + ".jsonl");
|
|
228
|
+
|
|
229
|
+
return new Promise(function (resolve) {
|
|
230
|
+
var history = [];
|
|
231
|
+
var stream;
|
|
232
|
+
try {
|
|
233
|
+
stream = fs.createReadStream(filePath, { encoding: "utf8" });
|
|
234
|
+
} catch (e) {
|
|
235
|
+
return resolve([]);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
var rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
239
|
+
var state = { toolCounter: 0 };
|
|
240
|
+
|
|
241
|
+
rl.on("line", function (line) {
|
|
242
|
+
var obj;
|
|
243
|
+
try { obj = JSON.parse(line); } catch (e) { return; }
|
|
244
|
+
appendCliRecord(obj, state, history);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
rl.on("close", function () {
|
|
248
|
+
resolve(history);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
rl.on("error", function () {
|
|
252
|
+
resolve([]);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
stream.on("error", function () {
|
|
256
|
+
rl.close();
|
|
257
|
+
resolve([]);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Synchronous variant for callers that run inside a synchronous request
|
|
263
|
+
// handler (e.g. switch_session, which must populate session.history before
|
|
264
|
+
// the session_switched broadcast). Reads the whole jsonl - these transcripts
|
|
265
|
+
// are small enough that blocking on a local read is fine.
|
|
266
|
+
// Modified-time (ms) of a CLI session's jsonl, or 0 if missing. Lets callers
|
|
267
|
+
// cheaply detect that the transcript grew (e.g. after a TUI turn) and re-read.
|
|
268
|
+
function cliSessionFileMtime(home, cwd, sessionId) {
|
|
269
|
+
var encoded = encodeCwd(cwd);
|
|
270
|
+
var filePath = path.join(home || REAL_HOME, ".claude", "projects", encoded, sessionId + ".jsonl");
|
|
271
|
+
try { return fs.statSync(filePath).mtimeMs; } catch (e) { return 0; }
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function readCliSessionHistorySync(home, cwd, sessionId) {
|
|
275
|
+
var encoded = encodeCwd(cwd);
|
|
276
|
+
var filePath = path.join(home || REAL_HOME, ".claude", "projects", encoded, sessionId + ".jsonl");
|
|
277
|
+
var raw;
|
|
278
|
+
try { raw = fs.readFileSync(filePath, "utf8"); } catch (e) { return []; }
|
|
279
|
+
var history = [];
|
|
280
|
+
var state = { toolCounter: 0 };
|
|
281
|
+
var lines = raw.split("\n");
|
|
282
|
+
for (var i = 0; i < lines.length; i++) {
|
|
283
|
+
if (!lines[i]) continue;
|
|
284
|
+
var obj;
|
|
285
|
+
try { obj = JSON.parse(lines[i]); } catch (e) { continue; }
|
|
286
|
+
appendCliRecord(obj, state, history);
|
|
287
|
+
}
|
|
288
|
+
return history;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
module.exports = {
|
|
292
|
+
listCliSessions: listCliSessions,
|
|
293
|
+
getMostRecentCliSession: getMostRecentCliSession,
|
|
294
|
+
readCliSessionHistory: readCliSessionHistory,
|
|
295
|
+
readCliSessionHistorySync: readCliSessionHistorySync,
|
|
296
|
+
cliSessionFileMtime: cliSessionFileMtime,
|
|
297
|
+
parseSessionFile: parseSessionFile,
|
|
298
|
+
encodeCwd: encodeCwd,
|
|
299
|
+
extractText: extractText,
|
|
300
|
+
};
|
|
@@ -17,9 +17,9 @@ var { wrapSpawnAsUser } = require("../os-users");
|
|
|
17
17
|
//
|
|
18
18
|
// The bundled @openai/codex platform package is the default. Set the
|
|
19
19
|
// CLAY_CODEX_PATH env var to an existing executable to run a different codex
|
|
20
|
-
// build (local dev build, system install, pinned older release)
|
|
21
|
-
//
|
|
22
|
-
//
|
|
20
|
+
// build (local dev build, system install, pinned older release). An unset
|
|
21
|
+
// override uses bundled resolution; an explicitly invalid override fails
|
|
22
|
+
// closed without selecting a different installation.
|
|
23
23
|
|
|
24
24
|
var PLATFORM_PACKAGE_BY_TARGET = {
|
|
25
25
|
"aarch64-apple-darwin": "@openai/codex-darwin-arm64",
|
|
@@ -45,14 +45,9 @@ function getTargetTriple() {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function findCodexPath() {
|
|
48
|
-
var
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
console.log("[codex-app-server] Using CLAY_CODEX_PATH binary:", override);
|
|
52
|
-
return override;
|
|
53
|
-
}
|
|
54
|
-
console.warn("[codex-app-server] CLAY_CODEX_PATH does not exist, falling back to bundled codex:", override);
|
|
55
|
-
}
|
|
48
|
+
var discovery = require("./discovery");
|
|
49
|
+
var override = discovery.explicitEntry(process.env, "CLAY_CODEX_PATH", false);
|
|
50
|
+
if (override !== undefined) return override;
|
|
56
51
|
|
|
57
52
|
var triple = getTargetTriple();
|
|
58
53
|
if (!triple) throw new Error("Unsupported platform: " + process.platform + "/" + process.arch);
|
|
@@ -74,7 +69,7 @@ function findCodexPath() {
|
|
|
74
69
|
path.join(vendorRoot, triple, "codex", binaryName),
|
|
75
70
|
];
|
|
76
71
|
for (var i = 0; i < candidates.length; i++) {
|
|
77
|
-
if (
|
|
72
|
+
if (discovery.validEntry(candidates[i], false)) {
|
|
78
73
|
console.log("[codex-app-server] Using bundled codex binary:", candidates[i]);
|
|
79
74
|
return candidates[i];
|
|
80
75
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Serializable descriptions of implemented provider controls. Legacy setting
|
|
2
|
+
// keys and message names describe persistence compatibility, never authority.
|
|
3
|
+
var claude = {
|
|
4
|
+
auto: true,
|
|
5
|
+
permissionModes: [{ value: 'default', label: 'Ask' }, { value: 'plan', label: 'Plan' }, { value: 'acceptEdits', label: 'Auto-accept edits' }],
|
|
6
|
+
thinking: { options: ['disabled', 'adaptive', 'budget'], budget: true },
|
|
7
|
+
};
|
|
8
|
+
var codex = {
|
|
9
|
+
approval: { options: [{ value: 'never', label: 'Auto' }, { value: 'untrusted', label: 'Untrusted' }, { value: 'on-request', label: 'Ask' }], state: 'codexApproval', message: 'set_codex_approval', key: 'approval' },
|
|
10
|
+
sandbox: { options: [{ value: 'read-only', label: 'Read Only' }, { value: 'workspace-write', label: 'Workspace' }, { value: 'danger-full-access', label: 'Full Access' }], state: 'codexSandbox', message: 'set_codex_sandbox', key: 'sandbox' },
|
|
11
|
+
webSearch: { options: [{ value: 'disabled', label: 'Off' }, { value: 'cached', label: 'Cached' }, { value: 'live', label: 'Live' }], state: 'codexWebSearch', message: 'set_codex_websearch', key: 'webSearch' },
|
|
12
|
+
};
|
|
13
|
+
module.exports = { claude: claude, codex: codex };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Installation resolution shared by adapter creation, startup and product UI.
|
|
2
|
+
// This never starts a provider; callers may replace resolvers for isolated tests.
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var cp = require('child_process');
|
|
5
|
+
function onPath(binary, user) {
|
|
6
|
+
try {
|
|
7
|
+
if (user && !/^[a-z_][a-z0-9_-]*\$?$/i.test(user)) return null;
|
|
8
|
+
var command = user ? 'su' : process.platform === 'win32' ? 'where' : 'which';
|
|
9
|
+
var args = user ? ['-', user, '-c', 'which ' + binary] : [binary];
|
|
10
|
+
if (!/^[a-zA-Z0-9_.-]+$/.test(binary)) return null;
|
|
11
|
+
var result = cp.execFileSync(command, args, { encoding: 'utf8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
12
|
+
return String(result || '').trim().split(/\r?\n/)[0] || null;
|
|
13
|
+
} catch (error) { return null; }
|
|
14
|
+
}
|
|
15
|
+
// Native commands require an executable regular file. SDK-owned JavaScript
|
|
16
|
+
// entries are readable files launched through Node, not native executables.
|
|
17
|
+
function validEntry(file, script) {
|
|
18
|
+
try {
|
|
19
|
+
if (typeof file !== 'string' || !file || !fs.statSync(file).isFile()) return false;
|
|
20
|
+
fs.accessSync(file, script && /\.(?:c|m)?js$/i.test(file) ? fs.constants.R_OK : fs.constants.X_OK);
|
|
21
|
+
return true;
|
|
22
|
+
} catch (error) { return false; }
|
|
23
|
+
}
|
|
24
|
+
function explicitEntry(env, name, script) {
|
|
25
|
+
if (!Object.prototype.hasOwnProperty.call(env, name)) return undefined;
|
|
26
|
+
if (!validEntry(env[name], script)) throw new Error('Invalid explicit provider executable: ' + name);
|
|
27
|
+
return env[name];
|
|
28
|
+
}
|
|
29
|
+
function pathResolver(binary, override) {
|
|
30
|
+
return function(options) {
|
|
31
|
+
options = options || {};
|
|
32
|
+
var env = options.env || process.env;
|
|
33
|
+
if (!options.user && override) {
|
|
34
|
+
var explicit = explicitEntry(env, override, false);
|
|
35
|
+
if (explicit !== undefined) return explicit;
|
|
36
|
+
}
|
|
37
|
+
var resolved = onPath(binary, options.user);
|
|
38
|
+
return options.user || validEntry(resolved, false) ? resolved : null;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function bundledResolver(find, binary) {
|
|
42
|
+
return function(options) {
|
|
43
|
+
options = options || {};
|
|
44
|
+
// The mapped account cannot inherit the daemon account's installation.
|
|
45
|
+
if (options.user) return onPath(binary, options.user);
|
|
46
|
+
// The runtime resolver owns all fallback policy. Adding a discovery-only
|
|
47
|
+
// PATH fallback would advertise a runtime that its adapter cannot start.
|
|
48
|
+
return find();
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function acpResolver(vendor) {
|
|
52
|
+
return function(options) {
|
|
53
|
+
if (options && options.user) return null;
|
|
54
|
+
var profiles = require('./acp-agent-profiles');
|
|
55
|
+
return profiles.findAcpAgentPath(profiles.getAcpAgentProfile(vendor));
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function installed(options) {
|
|
59
|
+
var registry = options && options.registry || require('./vendor-registry').VENDOR_REGISTRY;
|
|
60
|
+
var result = {};
|
|
61
|
+
Object.keys(registry).forEach(function(vendor) {
|
|
62
|
+
var info = registry[vendor];
|
|
63
|
+
result[vendor] = false;
|
|
64
|
+
if (options && options.user && info.osUserIsolation !== true) return;
|
|
65
|
+
if (typeof info.resolveExecutable !== 'function') return;
|
|
66
|
+
try { result[vendor] = !!info.resolveExecutable(options || {}); } catch (error) {}
|
|
67
|
+
});
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
module.exports = { installed: installed, pathResolver: pathResolver, bundledResolver: bundledResolver, acpResolver: acpResolver, validEntry: validEntry, explicitEntry: explicitEntry };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
function classify(provider, text) {
|
|
2
|
+
var service = require('./provider-contract').resolve(provider).classifyError;
|
|
3
|
+
return typeof service === 'function' ? service(text) : null;
|
|
4
|
+
}
|
|
5
|
+
function contextOverflow(error) {
|
|
6
|
+
return /prompt is too long|context_length|maximum context length/i.test(String(error || ""));
|
|
7
|
+
}
|
|
8
|
+
module.exports = { contextOverflow: contextOverflow, classify: classify };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Provider compatibility at the host boundary. No effects occur on import.
|
|
2
|
+
function prepare(env) { delete env.CLAUDECODE; }
|
|
3
|
+
function reaper(env) {
|
|
4
|
+
return { idleMs: Number(env.CLAY_ADAPTER_IDLE_MS) || Number(env.CLAY_CODEX_IDLE_MS) || 5 * 60 * 1000,
|
|
5
|
+
reapMs: Number(env.CLAY_ADAPTER_REAPER_MS) || Number(env.CLAY_CODEX_REAPER_MS) || 60 * 1000 };
|
|
6
|
+
}
|
|
7
|
+
module.exports = { prepare: prepare, reaper: reaper };
|
package/lib/yoke/index.js
CHANGED
|
@@ -16,11 +16,12 @@ var createGrokAdapter = require("./adapters/grok").createGrokAdapter;
|
|
|
16
16
|
var createCopilotAdapter = require("./adapters/copilot").createCopilotAdapter;
|
|
17
17
|
var createQwenAdapter = require("./adapters/qwen").createQwenAdapter;
|
|
18
18
|
var createJunieAdapter = require("./adapters/junie").createJunieAdapter;
|
|
19
|
+
var createMuseAdapter = require("./adapters/muse").createMuseAdapter;
|
|
19
20
|
var createKiroAdapter = require("./adapters/kiro").createKiroAdapter;
|
|
20
21
|
|
|
21
22
|
// Keep the first session in a new project predictable. This order is also
|
|
22
23
|
// used by the UI when a project has no remembered vendor yet.
|
|
23
|
-
var DEFAULT_VENDOR_ORDER = ["claude", "codex", "grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode", "kiro"];
|
|
24
|
+
var DEFAULT_VENDOR_ORDER = ["claude", "codex", "muse", "grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode", "kiro"];
|
|
24
25
|
|
|
25
26
|
function resolveDefaultVendor(availableVendors) {
|
|
26
27
|
availableVendors = availableVendors || {};
|
|
@@ -97,6 +98,8 @@ function createAdapter(opts) {
|
|
|
97
98
|
adapter = createJunieAdapter(opts);
|
|
98
99
|
} else if (vendor === "kiro") {
|
|
99
100
|
adapter = createKiroAdapter(opts);
|
|
101
|
+
} else if (vendor === "muse") {
|
|
102
|
+
adapter = createMuseAdapter(opts);
|
|
100
103
|
} else {
|
|
101
104
|
throw new Error("[YOKE] Unknown adapter vendor: " + vendor);
|
|
102
105
|
}
|
|
@@ -262,6 +265,7 @@ function checkAuth() {
|
|
|
262
265
|
qwen: !!lookupBinary("qwen"),
|
|
263
266
|
junie: !!lookupBinary("junie"),
|
|
264
267
|
kiro: checkKiro(),
|
|
268
|
+
muse: null,
|
|
265
269
|
};
|
|
266
270
|
logAuthCheck(_authCache);
|
|
267
271
|
return _authCache;
|
|
@@ -280,54 +284,8 @@ function checkAuth() {
|
|
|
280
284
|
var _installedCache = null;
|
|
281
285
|
|
|
282
286
|
function checkInstalled() {
|
|
283
|
-
if (_installedCache)
|
|
284
|
-
|
|
285
|
-
var fs = require("fs");
|
|
286
|
-
var execFileSync = require("child_process").execFileSync;
|
|
287
|
-
var result = { claude: false, codex: false, antigravity: false, opencode: false, kimi: false, grok: false, copilot: false, qwen: false, junie: false, kiro: false };
|
|
288
|
-
try {
|
|
289
|
-
if (process.platform === "win32") execFileSync("where", ["claude"], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
|
|
290
|
-
else execFileSync("which", ["claude"], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
|
|
291
|
-
result.claude = true;
|
|
292
|
-
} catch (e) {}
|
|
293
|
-
try {
|
|
294
|
-
var findKiroPath = require("./kiro-acp-server").findKiroPath;
|
|
295
|
-
var kiroBin = findKiroPath();
|
|
296
|
-
if (kiroBin && fs.existsSync(kiroBin)) result.kiro = true;
|
|
297
|
-
} catch (e) {}
|
|
298
|
-
try {
|
|
299
|
-
var codexBin = null;
|
|
300
|
-
try {
|
|
301
|
-
var findCodexPath = require("./codex-app-server").findCodexPath;
|
|
302
|
-
codexBin = findCodexPath();
|
|
303
|
-
if (codexBin && fs.existsSync(codexBin)) {
|
|
304
|
-
result.codex = true;
|
|
305
|
-
}
|
|
306
|
-
} catch (e) {}
|
|
307
|
-
|
|
308
|
-
if (!result.codex) {
|
|
309
|
-
var whichOut = process.platform === "win32"
|
|
310
|
-
? execFileSync("where", ["codex"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] })
|
|
311
|
-
: execFileSync("which", ["codex"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
|
|
312
|
-
if (whichOut.trim()) result.codex = true;
|
|
313
|
-
}
|
|
314
|
-
} catch (e) {}
|
|
315
|
-
try {
|
|
316
|
-
var antigravityBinary = process.platform === "win32"
|
|
317
|
-
? execFileSync("where", ["agy"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] })
|
|
318
|
-
: execFileSync("which", ["agy"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
|
|
319
|
-
result.antigravity = !!antigravityBinary.trim();
|
|
320
|
-
} catch (e) {}
|
|
321
|
-
var acpVendorKeys = ["opencode", "kimi", "grok", "copilot", "qwen", "junie"];
|
|
322
|
-
for (var acpIndex = 0; acpIndex < acpVendorKeys.length; acpIndex++) {
|
|
323
|
-
try {
|
|
324
|
-
var acpProfiles = require("./acp-agent-profiles");
|
|
325
|
-
var acpVendor = acpVendorKeys[acpIndex];
|
|
326
|
-
result[acpVendor] = !!acpProfiles.findAcpAgentPath(acpProfiles.getAcpAgentProfile(acpVendor));
|
|
327
|
-
} catch (e) {}
|
|
328
|
-
}
|
|
329
|
-
_installedCache = result;
|
|
330
|
-
return result;
|
|
287
|
+
if (!_installedCache) _installedCache = require("./discovery").installed();
|
|
288
|
+
return _installedCache;
|
|
331
289
|
}
|
|
332
290
|
|
|
333
291
|
function invalidateAuthCache() {
|
|
@@ -352,7 +310,7 @@ function createAdapters(opts) {
|
|
|
352
310
|
// Tests can supply a fixed installation snapshot without probing or spawning
|
|
353
311
|
// vendor binaries; production callers always use the cached host scan.
|
|
354
312
|
var installed = opts._installed || checkInstalled();
|
|
355
|
-
var auth = { claude: false, codex: false, antigravity: false, opencode: false, kimi: false, grok: false, copilot: false, qwen: false, junie: false, kiro: false };
|
|
313
|
+
var auth = { claude: false, codex: false, antigravity: false, opencode: false, kimi: false, grok: false, copilot: false, qwen: false, junie: false, kiro: false, muse: false };
|
|
356
314
|
var adapters = {};
|
|
357
315
|
|
|
358
316
|
function supportsConfiguredIsolation(vendor) {
|
|
@@ -390,7 +348,7 @@ function createAdapters(opts) {
|
|
|
390
348
|
}
|
|
391
349
|
}
|
|
392
350
|
|
|
393
|
-
var subprocessVendors = ["antigravity", "opencode", "kimi", "grok", "copilot", "qwen", "junie"];
|
|
351
|
+
var subprocessVendors = ["antigravity", "opencode", "kimi", "grok", "copilot", "qwen", "junie", "muse"];
|
|
394
352
|
for (var subprocessIndex = 0; subprocessIndex < subprocessVendors.length; subprocessIndex++) {
|
|
395
353
|
var subprocessVendor = subprocessVendors[subprocessIndex];
|
|
396
354
|
var subprocessInfo = vendorRegistry.getVendorInfo(subprocessVendor);
|