clay-server 5.2.0-beta.5 → 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/claude-hook-installer.js +1 -267
- package/lib/claude-jsonl-watcher.js +1 -204
- package/lib/clay-skill-install.js +1 -33
- package/lib/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- 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/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 +8 -7
- package/lib/project-http.js +4 -4
- package/lib/project-mcp.js +2 -2
- 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-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-user-message.js +1 -0
- package/lib/project-vendor-login.js +6 -36
- package/lib/public/app.js +1 -0
- package/lib/public/css/messages.css +6 -2
- 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-messages.js +36 -5
- package/lib/public/modules/app-notifications.js +1 -2
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-rate-limit.js +7 -27
- package/lib/public/modules/chat-render-runtime.js +3 -0
- package/lib/public/modules/mcp-connection-view.js +1 -1
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/tools.js +2 -1
- 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/muse-avatar.svg +4 -0
- package/lib/safe-bash-commands.js +3 -45
- package/lib/sdk-bridge.js +127 -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.js +1 -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 +17 -89
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/vendor-login-browser.js +1 -11
- 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 +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/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
|
@@ -16,16 +16,14 @@ function contextStatus(session) {
|
|
|
16
16
|
var used = null;
|
|
17
17
|
var window = null;
|
|
18
18
|
var source = "unavailable";
|
|
19
|
+
var measurement = "unavailable";
|
|
19
20
|
if (snapshot && typeof snapshot === "object") {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
window = firstNumber(snapshot.contextWindow);
|
|
27
|
-
if (used !== null || window !== null) source = "adapter_context_usage";
|
|
28
|
-
}
|
|
21
|
+
var current = require("./yoke/usage").context(snapshot, session.vendor || "claude").context;
|
|
22
|
+
measurement = current.measurement;
|
|
23
|
+
used = firstNumber(current.usedTokens);
|
|
24
|
+
window = firstNumber(current.windowTokens);
|
|
25
|
+
if (used !== null || window !== null) source = current.source;
|
|
26
|
+
|
|
29
27
|
}
|
|
30
28
|
var history = session.history || [];
|
|
31
29
|
var cumulativeInput = 0;
|
|
@@ -46,9 +44,9 @@ function contextStatus(session) {
|
|
|
46
44
|
if (typeof item._ts === "number") lastCompactionAt = item._ts;
|
|
47
45
|
}
|
|
48
46
|
if (item.type !== "result") continue;
|
|
49
|
-
var usage = item.usage || {};
|
|
50
|
-
var input = firstNumber(usage.
|
|
51
|
-
var output = firstNumber(usage.
|
|
47
|
+
var usage = require("./yoke/usage").accounting(item.usage) || {};
|
|
48
|
+
var input = firstNumber(usage.inputTokens);
|
|
49
|
+
var output = firstNumber(usage.outputTokens);
|
|
52
50
|
if (input !== null) { cumulativeInput += input; observedInput = true; }
|
|
53
51
|
if (output !== null) { cumulativeOutput += output; observedOutput = true; }
|
|
54
52
|
results++;
|
|
@@ -59,13 +57,14 @@ function contextStatus(session) {
|
|
|
59
57
|
if (used !== null && window !== null && used > window) {
|
|
60
58
|
used = null;
|
|
61
59
|
source = "unavailable";
|
|
60
|
+
measurement = "unavailable";
|
|
62
61
|
}
|
|
63
62
|
// Older result records contain lastStreamInputTokens, but that field was
|
|
64
63
|
// populated from adapter snapshots that could be cumulative or inflated by
|
|
65
64
|
// cache accounting. It is not safe evidence of current context occupancy.
|
|
66
65
|
var ratio = used !== null && window !== null && window > 0 ? Math.min(1, Math.round((used / window) * 1000) / 1000) : null;
|
|
67
66
|
return {
|
|
68
|
-
current: { source: source, usedTokens: used, windowTokens: window, usedRatio: ratio,
|
|
67
|
+
current: { source: source, measurement: measurement, usedTokens: used, windowTokens: window, usedRatio: ratio,
|
|
69
68
|
scope: used === null && window === null ? "unknown" : (used !== null && window !== null ? "current_context" : "partial_current_context") },
|
|
70
69
|
cumulative: { inputTokens: observedInput ? cumulativeInput : null, outputTokens: observedOutput ? cumulativeOutput : null, tasksObserved: results, scope: "loaded_session_history", complete: false },
|
|
71
70
|
lastTask: lastTask,
|
|
@@ -249,7 +249,8 @@ function createPendingMessageQueue(opts) {
|
|
|
249
249
|
return true;
|
|
250
250
|
}
|
|
251
251
|
function consumeOne(session, dispatch) {
|
|
252
|
-
|
|
252
|
+
var foreground = require('./sdk-foreground-admission');
|
|
253
|
+
if (loadError || !session || session._pendingMessageClaimId || isPaused(session) || session._pendingMessageDrainPaused || session.taskStopRequested || session._queryStarting || (session._awaitingTurnResult || session.isProcessing) && !foreground.available(session)) return null;
|
|
253
254
|
if (session.rateLimitResetsAt && session.rateLimitResetsAt > Date.now()) return null;
|
|
254
255
|
for (var i = 0; i < data.items.length; i++) {
|
|
255
256
|
var item = data.items[i];
|
|
@@ -262,6 +263,7 @@ function createPendingMessageQueue(opts) {
|
|
|
262
263
|
data.revision++;
|
|
263
264
|
try { persist(); } catch (e) { restore(before); return null; }
|
|
264
265
|
session._pendingMessageClaimId = item.id;
|
|
266
|
+
foreground.take(session);
|
|
265
267
|
broadcast(session, { type: "pending_message_claimed", sessionId: session.localId, projectSlug: opts.slug, paused: isPaused(session), id: item.id, revision: data.revision });
|
|
266
268
|
var completed = false;
|
|
267
269
|
function complete(ok, error) { if (completed) return false; completed = true; return finishClaim(session, item.id, ok, error); }
|
|
@@ -105,7 +105,10 @@ function attachSessionHistoryActions(ctx) {
|
|
|
105
105
|
if (session.messageUUIDs[fi].uuid === uuid) { targetIdx = fi; break; }
|
|
106
106
|
}
|
|
107
107
|
var forkHistory = [];
|
|
108
|
-
if (
|
|
108
|
+
if (result.localHistoryEndIndex !== undefined) {
|
|
109
|
+
if (!Number.isInteger(result.localHistoryEndIndex) || result.localHistoryEndIndex < 0 || result.localHistoryEndIndex > session.history.length) throw new Error("The provider fork exists but its local history boundary is unavailable; inspect before retrying");
|
|
110
|
+
forkHistory = session.history.slice(0, result.localHistoryEndIndex);
|
|
111
|
+
} else if (targetIdx >= 0) {
|
|
109
112
|
var trimTo = session.messageUUIDs[targetIdx].historyIndex;
|
|
110
113
|
forkHistory = session.history.slice(0, trimTo);
|
|
111
114
|
} else {
|
|
@@ -133,8 +136,7 @@ function attachSessionHistoryActions(ctx) {
|
|
|
133
136
|
return forked;
|
|
134
137
|
} else {
|
|
135
138
|
// Read history from CLI session files
|
|
136
|
-
var
|
|
137
|
-
var history = await cliSess.readCliSessionHistory(resolveSessionHome(session), cwd, result.sessionId);
|
|
139
|
+
var history = await require("./yoke/session-history").read(session.vendor || "claude", resolveSessionHome(session), cwd, result.sessionId);
|
|
138
140
|
revalidate();
|
|
139
141
|
var options = {
|
|
140
142
|
history: history,
|
|
@@ -350,7 +350,7 @@ function attachSessionPair(ctx) {
|
|
|
350
350
|
if (boundRoles && boundRoles.workers.indexOf(boundSession) !== -1) return taskControl.workerToolDefs(boundSession);
|
|
351
351
|
var adHocSplit = !!(group && !group.pair);
|
|
352
352
|
if (!driverEligibility.isEligibleDriverSession(boundSession, sm)) return [];
|
|
353
|
-
var persistentCatalog = boundSession.vendor === "
|
|
353
|
+
var persistentCatalog = require("./yoke/session-tool-transport").contract(boundSession.vendor || "claude").catalogLifetime === "conversation" && (!group || !!group.pair);
|
|
354
354
|
if (!group && !persistentCatalog) {
|
|
355
355
|
return workerProposal.getToolDefs(boundSession)
|
|
356
356
|
.concat(workerPermission.getToolDefs(boundSession, { dormantDriver: true }));
|
|
@@ -11,7 +11,8 @@ function attachSessionRuntimeActions(ctx) {
|
|
|
11
11
|
var vendor = session.vendor || ctx.sm.defaultVendor || "claude";
|
|
12
12
|
var ids = Array.from(new Set([session.terminalId, session.runtimeTerminalId].filter(function (id) { return typeof id === "number"; })));
|
|
13
13
|
if (!ids.length && (session.runtimeMode || session.mode || "gui") === "gui") return { status: "completed", runtimeMode: "gui", runtimeEffect: "none", threadPreserved: true };
|
|
14
|
-
|
|
14
|
+
var lifecycle = require("./yoke/provider-contract").resolve(vendor);
|
|
15
|
+
if (typeof lifecycle.supportsLegacyGuiResume !== "function" || !lifecycle.supportsLegacyGuiResume(session)) throw new Error("This provider cannot return a legacy terminal thread to GUI chat.");
|
|
15
16
|
var closed = 0, persisted = false;
|
|
16
17
|
var fields = ['terminalId', 'runtimeTerminalId'];
|
|
17
18
|
var originalFields = fields.map(function (field) { return session[field]; });
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
var yoke = require("./yoke");
|
|
2
2
|
var sessionSpawnMcp = require("./session-spawn-mcp-server");
|
|
3
|
-
var cliSessions = require("./cli-sessions");
|
|
4
3
|
var os = require("os");
|
|
5
4
|
var osUsers = require("./os-users");
|
|
6
5
|
|
|
@@ -161,7 +160,7 @@ function attachSessionSpawn(ctx) {
|
|
|
161
160
|
var sm = ctx.sm;
|
|
162
161
|
var queue = createSpawnQueue(SPAWN_CONCURRENCY);
|
|
163
162
|
var adapters = ctx.adapters || {};
|
|
164
|
-
var readCliSessionHistory = ctx.readCliSessionHistory ||
|
|
163
|
+
var readCliSessionHistory = ctx.readCliSessionHistory || function(home, project, sessionId, provider) { return require("./yoke/session-history").read(provider || "claude", home, project, sessionId); };
|
|
165
164
|
|
|
166
165
|
function resolveSessionHome(session) {
|
|
167
166
|
var linuxUser = ctx.getLinuxUserForSession(session);
|
|
@@ -283,7 +282,7 @@ function attachSessionSpawn(ctx) {
|
|
|
283
282
|
forkHistory = parent.history.slice();
|
|
284
283
|
} else {
|
|
285
284
|
forkHistory = await readCliSessionHistory(
|
|
286
|
-
resolveSessionHome(parent), ctx.cwd, forkResult.sessionId
|
|
285
|
+
resolveSessionHome(parent), ctx.cwd, forkResult.sessionId, parent.vendor
|
|
287
286
|
);
|
|
288
287
|
}
|
|
289
288
|
} catch (e) {
|
|
@@ -18,7 +18,8 @@ function attachSessionVendor(ctx) {
|
|
|
18
18
|
session.vendor = vendor;
|
|
19
19
|
session.model = null;
|
|
20
20
|
session.effort = yoke.clampEffort(vendor, session.effort) || null;
|
|
21
|
-
|
|
21
|
+
var modes = yoke.sessionTools.contract(ctx.adapters[vendor]).permissionModes;
|
|
22
|
+
if (session.permissionMode === 'auto' && (!Array.isArray(modes) || modes.indexOf('auto') < 0)) session.permissionMode = 'default';
|
|
22
23
|
session.effectivePermissionMode = null;
|
|
23
24
|
try { if (ctx.sm.saveSessionFile(session) !== true) throw new Error('Could not persist the provider selection.'); }
|
|
24
25
|
catch (error) { Object.assign(session, previous); throw error; }
|
package/lib/project-sessions.js
CHANGED
|
@@ -2,7 +2,7 @@ var serverSettingsMessages = require("./project-server-settings");
|
|
|
2
2
|
var fs = require("fs");
|
|
3
3
|
var path = require("path");
|
|
4
4
|
var { execFileSync } = require("child_process");
|
|
5
|
-
var
|
|
5
|
+
var providerSettings = require("./yoke/settings");
|
|
6
6
|
var updateSnooze = require("./update-snooze");
|
|
7
7
|
var yoke = require("./yoke");
|
|
8
8
|
var sessionVisibility = require("./session-visibility");
|
|
@@ -258,7 +258,7 @@ function attachSessions(ctx) {
|
|
|
258
258
|
if (!session || !session.cliSessionId) return;
|
|
259
259
|
if (session._titleWatcherStop) return; // already watching
|
|
260
260
|
var watcher;
|
|
261
|
-
try { watcher = require("./claude-jsonl-watcher"); } catch (e) { return; }
|
|
261
|
+
try { watcher = require("./yoke/claude-jsonl-watcher"); } catch (e) { return; }
|
|
262
262
|
var home = resolveSessionHome(session);
|
|
263
263
|
var jsonlPath = watcher.jsonlPathFor(home, cwd, session.cliSessionId);
|
|
264
264
|
if (!jsonlPath) return;
|
|
@@ -326,7 +326,7 @@ function attachSessions(ctx) {
|
|
|
326
326
|
// message right away. The transcript is small enough that a full
|
|
327
327
|
// re-send beats maintaining a delta protocol.
|
|
328
328
|
try {
|
|
329
|
-
var newIndex = require("./tui-transcript-index").readAssistantIndex(resolveSessionHome(s), cwd, s.cliSessionId);
|
|
329
|
+
var newIndex = require("./yoke/tui-transcript-index").readAssistantIndex(resolveSessionHome(s), cwd, s.cliSessionId);
|
|
330
330
|
send({
|
|
331
331
|
type: "tui_transcript_state",
|
|
332
332
|
id: s.localId,
|
|
@@ -453,7 +453,7 @@ function attachSessions(ctx) {
|
|
|
453
453
|
function prepareTuiSessionForGuiView(session, options) {
|
|
454
454
|
if (!session || session.cliSessionId == null) return;
|
|
455
455
|
var cliSess;
|
|
456
|
-
try { cliSess = require("./cli-sessions"); } catch (e) { return; }
|
|
456
|
+
try { cliSess = require("./yoke/cli-sessions"); } catch (e) { return; }
|
|
457
457
|
// Re-read whenever the jsonl has changed since the last hydrate (a TUI
|
|
458
458
|
// turn appended messages), not just when history is empty. The earlier
|
|
459
459
|
// "already hydrated" short-circuit kept stale history after a
|
|
@@ -603,7 +603,7 @@ function attachSessions(ctx) {
|
|
|
603
603
|
var from = sm.findTurnBoundary(session.history, Math.max(0, targetFrom));
|
|
604
604
|
var to = before;
|
|
605
605
|
var items = session.history.slice(from, to).map(function (item, index) {
|
|
606
|
-
return Object.assign({}, hydrateImageRefs(item), { _historyIndex: from + index });
|
|
606
|
+
return Object.assign({}, hydrateImageRefs(require("./yoke/usage").clientEvent(item, session.vendor || "claude")), { _historyIndex: from + index });
|
|
607
607
|
});
|
|
608
608
|
sendTo(ws, {
|
|
609
609
|
type: "history_prepend",
|
|
@@ -918,7 +918,7 @@ function attachSessions(ctx) {
|
|
|
918
918
|
return true;
|
|
919
919
|
}
|
|
920
920
|
try {
|
|
921
|
-
var tprIndex = require("./tui-transcript-index").readAssistantIndex(resolveSessionHome(tprSess), cwd, tprSess.cliSessionId);
|
|
921
|
+
var tprIndex = require("./yoke/tui-transcript-index").readAssistantIndex(resolveSessionHome(tprSess), cwd, tprSess.cliSessionId);
|
|
922
922
|
sendTo(ws, {
|
|
923
923
|
type: "tui_transcript_state",
|
|
924
924
|
id: tprId,
|
|
@@ -1099,14 +1099,14 @@ function attachSessions(ctx) {
|
|
|
1099
1099
|
var pid = msg.pid;
|
|
1100
1100
|
if (!pid || typeof pid !== "number") return true;
|
|
1101
1101
|
// Verify target is actually a claude process before killing
|
|
1102
|
-
if (!sdk.
|
|
1103
|
-
console.error("[project] Refused to kill PID " + pid + ": not a
|
|
1104
|
-
sendTo(ws, { type: "error", text: "Process " + pid + " is not a
|
|
1102
|
+
if (!sdk.isProviderProcess(pid, getSessionForWs(ws))) {
|
|
1103
|
+
console.error("[project] Refused to kill PID " + pid + ": not a verified provider process");
|
|
1104
|
+
sendTo(ws, { type: "error", text: "Process " + pid + " is not a verified provider process." });
|
|
1105
1105
|
return true;
|
|
1106
1106
|
}
|
|
1107
1107
|
try {
|
|
1108
1108
|
process.kill(pid, "SIGTERM");
|
|
1109
|
-
console.log("[project] Sent SIGTERM to conflicting
|
|
1109
|
+
console.log("[project] Sent SIGTERM to conflicting provider process PID " + pid);
|
|
1110
1110
|
sendTo(ws, { type: "process_killed", pid: pid });
|
|
1111
1111
|
} catch (e) {
|
|
1112
1112
|
console.error("[project] Failed to kill PID " + pid + ":", e.message);
|
|
@@ -1367,20 +1367,12 @@ function attachSessions(ctx) {
|
|
|
1367
1367
|
return true;
|
|
1368
1368
|
}
|
|
1369
1369
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
if (msg.type === "set_codex_sandbox") {
|
|
1377
|
-
sm.codexSandbox = msg.sandbox || CODEX_DEFAULTS.sandbox;
|
|
1378
|
-
send(Object.assign({ type: "codex_config" }, getCodexConfig(sm)));
|
|
1379
|
-
return true;
|
|
1380
|
-
}
|
|
1381
|
-
if (msg.type === "set_codex_websearch") {
|
|
1382
|
-
sm.codexWebSearch = msg.webSearch || CODEX_DEFAULTS.webSearch;
|
|
1383
|
-
send(Object.assign({ type: "codex_config" }, getCodexConfig(sm)));
|
|
1370
|
+
var providerChange;
|
|
1371
|
+
try { providerChange = providerSettings.change(msg, sm); }
|
|
1372
|
+
catch (error) { sendTo(ws, { type: "error", text: error.message }); return true; }
|
|
1373
|
+
if (providerChange) {
|
|
1374
|
+
Object.keys(providerChange.patch).forEach(function(key) { sm[key] = providerChange.patch[key]; });
|
|
1375
|
+
providerChange.messages.forEach(function(message) { send(message); });
|
|
1384
1376
|
return true;
|
|
1385
1377
|
}
|
|
1386
1378
|
|
|
@@ -1924,7 +1916,7 @@ function attachSessions(ctx) {
|
|
|
1924
1916
|
var galManaged = [];
|
|
1925
1917
|
var galUser = [];
|
|
1926
1918
|
try {
|
|
1927
|
-
var galInstaller = require("./claude-hook-installer");
|
|
1919
|
+
var galInstaller = require("./yoke/claude-hook-installer");
|
|
1928
1920
|
galManaged = galInstaller.CLAY_MANAGED_ALLOW || [];
|
|
1929
1921
|
} catch (e) {}
|
|
1930
1922
|
if (galUid) {
|
|
@@ -1950,7 +1942,7 @@ function attachSessions(ctx) {
|
|
|
1950
1942
|
// home (OS-mode: getent passwd; single-user: os.homedir()).
|
|
1951
1943
|
var salEffective = false;
|
|
1952
1944
|
try {
|
|
1953
|
-
var salInstaller = require("./claude-hook-installer");
|
|
1945
|
+
var salInstaller = require("./yoke/claude-hook-installer");
|
|
1954
1946
|
var salHome = null;
|
|
1955
1947
|
if (osUsers && ws._clayUser && ws._clayUser.linuxUser) {
|
|
1956
1948
|
try {
|
|
@@ -488,6 +488,7 @@ function attachUserMessage(ctx) {
|
|
|
488
488
|
if (queuedResult.ok) {
|
|
489
489
|
messageDelivery.acknowledge(ws, deliveryReceipt, null, session);
|
|
490
490
|
sendTo(ws, { type: "message_queued", clientMessageId: msg.clientMessageId || null, sessionId: session.localId, projectSlug: slug, state: "pending", paused: pendingMessageQueue.isPaused(session), revision: pendingMessageQueue.getRevision() });
|
|
491
|
+
if (require('./sdk-foreground-admission').available(session)) setImmediate(function () { consumePendingMessage(session); });
|
|
491
492
|
} else {
|
|
492
493
|
sendTo(ws, { type: "error", text: queuedResult.error || "Unable to queue message" });
|
|
493
494
|
}
|
|
@@ -25,37 +25,11 @@ var yoke = require("./yoke");
|
|
|
25
25
|
// Login CLIs print a success line and then hand the shell back, so the PTY
|
|
26
26
|
// itself does not exit. Watch the output stream instead. Deliberately narrow:
|
|
27
27
|
// "Successfully logged out" and MCP-server logins must not match.
|
|
28
|
-
var LOGIN_SUCCESS_PATTERNS = [
|
|
29
|
-
/successfully logged in(?![ \t]+to[ \t]+mcp)/i,
|
|
30
|
-
/logged in successfully/i,
|
|
31
|
-
/login successful/i,
|
|
32
|
-
/successfully authenticated/i,
|
|
33
|
-
/authentication successful/i,
|
|
34
|
-
/signed in successfully/i,
|
|
35
|
-
/signed in with your [a-z ]+ account/i,
|
|
36
|
-
/you(?:'re| are) (?:now )?(?:logged|signed) in/i,
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
// Rolling window kept per flow so a success line split across PTY chunks is
|
|
40
|
-
// still matched, without buffering the whole login transcript.
|
|
41
28
|
var OUTPUT_TAIL_MAX = 4096;
|
|
42
|
-
|
|
43
|
-
// Grace period between detecting success and killing the terminal, so the user
|
|
44
|
-
// actually sees the confirmation line before the modal closes.
|
|
45
29
|
var CLOSE_AFTER_SUCCESS_MS = 2000;
|
|
46
|
-
|
|
47
|
-
var
|
|
48
|
-
|
|
49
|
-
function stripAnsi(text) {
|
|
50
|
-
return String(text).replace(ANSI_PATTERN, "");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function looksLikeLoginSuccess(text) {
|
|
54
|
-
for (var i = 0; i < LOGIN_SUCCESS_PATTERNS.length; i++) {
|
|
55
|
-
if (LOGIN_SUCCESS_PATTERNS[i].test(text)) return true;
|
|
56
|
-
}
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
30
|
+
var loginProtocol = require("./yoke/login-protocol");
|
|
31
|
+
var stripAnsi = loginProtocol.stripAnsi;
|
|
32
|
+
var looksLikeLoginSuccess = loginProtocol.successful;
|
|
59
33
|
|
|
60
34
|
/**
|
|
61
35
|
* ctx fields:
|
|
@@ -96,11 +70,7 @@ function attachVendorLogin(ctx) {
|
|
|
96
70
|
cancel: function (vendor) { closeFlowTerminal(discardFlow(vendor)); broadcastState(); },
|
|
97
71
|
});
|
|
98
72
|
|
|
99
|
-
function loginCommandFor(vendor) {
|
|
100
|
-
if (vendor === "claude") return "claude auth login";
|
|
101
|
-
var info = vendorRegistry.getVendorInfo(vendor);
|
|
102
|
-
return (info && info.loginCommand) || "claude login";
|
|
103
|
-
}
|
|
73
|
+
function loginCommandFor(vendor) { return loginProtocol.command(vendor, false); }
|
|
104
74
|
|
|
105
75
|
function vendorDisplayName(vendor) {
|
|
106
76
|
var info = vendorRegistry.getVendorInfo(vendor);
|
|
@@ -284,8 +254,8 @@ function attachVendorLogin(ctx) {
|
|
|
284
254
|
var key = flowKey(ws, vendor);
|
|
285
255
|
var identity = resolveLoginIdentity(ws, msg);
|
|
286
256
|
var command = loginCommandFor(vendor);
|
|
287
|
-
var browserMode = msg.mode === "browser" && (vendor
|
|
288
|
-
if (browserMode) command = vendor
|
|
257
|
+
var browserMode = msg.mode === "browser" && !!(vendorRegistry.getVendorInfo(vendor) || {}).browserLoginCommand;
|
|
258
|
+
if (browserMode) command = loginProtocol.command(vendor, true);
|
|
289
259
|
var flow = {
|
|
290
260
|
vendor: vendor,
|
|
291
261
|
key: key,
|
package/lib/public/app.js
CHANGED
|
@@ -583,6 +583,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
583
583
|
// rendering
|
|
584
584
|
currentMsgTs: null,
|
|
585
585
|
richContextUsage: null,
|
|
586
|
+
contextMeasurement: "unavailable",
|
|
586
587
|
currentMsgEl: null,
|
|
587
588
|
currentFullText: "",
|
|
588
589
|
matePreThinkingEl: null,
|
|
@@ -675,7 +675,8 @@ pre.mermaid-error {
|
|
|
675
675
|
|
|
676
676
|
.thinking-live .thinking-chevron { display: none; }
|
|
677
677
|
|
|
678
|
-
.thinking-live .thinking-label
|
|
678
|
+
.thinking-live .thinking-label,
|
|
679
|
+
.activity-inline .activity-text.activity-state-label {
|
|
679
680
|
background: linear-gradient(100deg, var(--text-muted) 40%, var(--text-dimmer) 50%, var(--text-muted) 60%);
|
|
680
681
|
background-size: 300% 100%;
|
|
681
682
|
background-clip: text;
|
|
@@ -690,7 +691,10 @@ pre.mermaid-error {
|
|
|
690
691
|
}
|
|
691
692
|
|
|
692
693
|
@media (prefers-reduced-motion: reduce) {
|
|
693
|
-
.thinking-live .thinking-label
|
|
694
|
+
.thinking-live .thinking-label,
|
|
695
|
+
.activity-inline .activity-text.activity-state-label {
|
|
696
|
+
animation: none; background: none; color: var(--text-muted); -webkit-text-fill-color: currentColor;
|
|
697
|
+
}
|
|
694
698
|
}
|
|
695
699
|
|
|
696
700
|
.thinking-header[aria-disabled="true"] { cursor: default; }
|
|
@@ -197,7 +197,7 @@ export function stopUrgentBlink() {
|
|
|
197
197
|
|
|
198
198
|
export function setActivity(text) {
|
|
199
199
|
var thinkingState = store.get('thinkingState');
|
|
200
|
-
if (text === "thinking" && thinkingState && thinkingState.active) {
|
|
200
|
+
if ((text === "thinking" || text === "running") && thinkingState && thinkingState.active) {
|
|
201
201
|
// Live Thinking already owns the tail progress UI. Compaction and tool
|
|
202
202
|
// activity intentionally continue through so their distinct states show.
|
|
203
203
|
if (getActivityEl()) {
|
|
@@ -225,9 +225,18 @@ export function setActivity(text) {
|
|
|
225
225
|
_actEl.innerHTML =
|
|
226
226
|
'<div class="mate-thinking-dots"><span></span><span></span><span></span></div>';
|
|
227
227
|
}
|
|
228
|
+
_actEl.setAttribute("role", "status");
|
|
229
|
+
_actEl.setAttribute("aria-live", "polite");
|
|
228
230
|
setActivityEl(_actEl);
|
|
229
|
-
addToMessages(_actEl);
|
|
230
231
|
}
|
|
232
|
+
var activity = getActivityEl();
|
|
233
|
+
var labels = { waiting: "Waiting for provider", running: "Working", background: "Background work pending" };
|
|
234
|
+
var label = activity.querySelector(".activity-state-label");
|
|
235
|
+
if (labels[text]) {
|
|
236
|
+
if (!label) { label = document.createElement("span"); label.className = "activity-state-label activity-text"; activity.appendChild(label); }
|
|
237
|
+
label.textContent = labels[text];
|
|
238
|
+
} else if (label) label.remove();
|
|
239
|
+
addToMessages(activity);
|
|
231
240
|
scrollToBottom();
|
|
232
241
|
} else {
|
|
233
242
|
if (getActivityEl()) {
|
|
@@ -267,14 +267,16 @@ export function initHeader() {
|
|
|
267
267
|
addRow("Local ID", split.panes[pi].sessionId);
|
|
268
268
|
if (member && member.cliSessionId) {
|
|
269
269
|
addRow("Session ID", member.cliSessionId);
|
|
270
|
-
|
|
270
|
+
var memberResume = ((store.get("vendorInfo") || {})[member.vendor || "claude"] || {}).terminalResumeCommand;
|
|
271
|
+
if (memberResume) addRow("Resume", memberResume + " " + member.cliSessionId);
|
|
271
272
|
}
|
|
272
273
|
}
|
|
273
274
|
} else {
|
|
274
275
|
var s = store.snap();
|
|
275
276
|
if (s.cliSessionId) addRow("Session ID", s.cliSessionId);
|
|
276
277
|
if (s.activeSessionId) addRow("Local ID", s.activeSessionId);
|
|
277
|
-
|
|
278
|
+
var resume = ((s.vendorInfo || {})[s.currentVendor] || {}).terminalResumeCommand;
|
|
279
|
+
if (s.cliSessionId && resume) addRow("Resume", resume + " " + s.cliSessionId);
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
document.body.appendChild(pop);
|
|
@@ -657,6 +657,8 @@ function renderPreviewModelTab(bodyEl) {
|
|
|
657
657
|
}
|
|
658
658
|
|
|
659
659
|
var opts = {
|
|
660
|
+
effortLevels: ((store.get("vendorInfo") || {})[store.get("currentVendor")] || {}).effortLevels || [],
|
|
661
|
+
configuration: ((store.get("vendorInfo") || {})[store.get("currentVendor")] || {}).configuration || {},
|
|
660
662
|
models: s.currentModels || [],
|
|
661
663
|
currentModel: _previewLoopSettings.model || "",
|
|
662
664
|
currentMode: _previewLoopSettings.permissionMode || "default",
|
|
@@ -282,7 +282,7 @@ export function processMessage(msg) {
|
|
|
282
282
|
|
|
283
283
|
// Restore accurate context data from the last result in full history
|
|
284
284
|
if (msg.lastUsage || msg.lastModelUsage) {
|
|
285
|
-
accumulateContext(msg.lastCost, msg.lastUsage, msg.lastModelUsage, msg.lastStreamInputTokens);
|
|
285
|
+
accumulateContext(msg.lastCost, msg.lastUsage, msg.lastModelUsage, msg.lastStreamInputTokens, msg.context);
|
|
286
286
|
}
|
|
287
287
|
updateContextPanel();
|
|
288
288
|
updateUsagePanel();
|
|
@@ -290,6 +290,7 @@ export function processMessage(msg) {
|
|
|
290
290
|
// the restored turn instead of starting a second answer bubble.
|
|
291
291
|
if (store.get('sessionIsProcessing')) {
|
|
292
292
|
flushStreamBuffer();
|
|
293
|
+
if (store.get('turnActivity')) setActivity(store.get('turnActivity').phase);
|
|
293
294
|
} else {
|
|
294
295
|
markAllToolsDone();
|
|
295
296
|
finalizeAssistantBlock();
|
|
@@ -912,7 +913,7 @@ export function processMessage(msg) {
|
|
|
912
913
|
? msg.runtimeTerminalId
|
|
913
914
|
: (typeof msg.terminalId === "number" ? msg.terminalId : null);
|
|
914
915
|
var _sessionRole = msg.sessionRole === "worker" ? "worker" : "driver";
|
|
915
|
-
store.set({ activeSessionId: msg.id, sessionOriginId: msg.sessionOriginId || null, cliSessionId: msg.cliSessionId || null, currentModel: msg.model || "", currentEffort: msg.effort || store.get('currentEffort'), vendorCapabilities: msg.capabilities || {}, sessionIsProcessing: !!msg.isProcessing, activeSessionMode: _effectiveMode, activeTerminalId: _effectiveTerminalId, sessionHasHistory: !!msg.hasHistory, sessionVendorBound: !!msg.vendor || !!msg.hasHistory, sessionFullAccess: msg.permissionMode === "bypassPermissions", currentMode: msg.permissionMode || store.get('currentMode'), effectivePermissionMode: msg.effectivePermissionMode || null, permissionCapabilities: msg.permissionCapabilities || { auto: false, mcpOverride: false }, mcpPermissionModeOverrides: msg.mcpPermissionModeOverrides || {}, activeSessionMateId: _sessionRole === "worker" ? null : (store.get('activeProjectMateId') || null), activeSessionMateName: _sessionRole === "worker" ? "" : (store.get('activeProjectMateName') || "") });
|
|
916
|
+
store.set({ activeSessionId: msg.id, sessionOriginId: msg.sessionOriginId || null, cliSessionId: msg.cliSessionId || null, currentModel: msg.model || "", currentEffort: msg.effort || store.get('currentEffort'), vendorCapabilities: msg.capabilities || {}, sessionIsProcessing: !!msg.isProcessing, turnActivity: null, activeSessionMode: _effectiveMode, activeTerminalId: _effectiveTerminalId, sessionHasHistory: !!msg.hasHistory, sessionVendorBound: !!msg.vendor || !!msg.hasHistory, sessionFullAccess: msg.permissionMode === "bypassPermissions", currentMode: msg.permissionMode || store.get('currentMode'), effectivePermissionMode: msg.effectivePermissionMode || null, permissionCapabilities: msg.permissionCapabilities || { auto: false, mcpOverride: false }, mcpPermissionModeOverrides: msg.mcpPermissionModeOverrides || {}, activeSessionMateId: _sessionRole === "worker" ? null : (store.get('activeProjectMateId') || null), activeSessionMateName: _sessionRole === "worker" ? "" : (store.get('activeProjectMateName') || "") });
|
|
916
917
|
handleScheduledTaskSessionSwitched(msg);
|
|
917
918
|
requestLoopInterviewState();
|
|
918
919
|
activateDeliverySession(msg.id, msg.cliSessionId || null, msg.sessionOriginId || null);
|
|
@@ -1039,7 +1040,11 @@ export function processMessage(msg) {
|
|
|
1039
1040
|
// running session, where history_done keeps current tools active.
|
|
1040
1041
|
// Question answers, plan feedback and Driver delegations are injected
|
|
1041
1042
|
// mid-turn, so tools before them may still be running.
|
|
1042
|
-
else if (!msg.askUserAnswer && !msg.planFeedback && !msg.delegated)
|
|
1043
|
+
else if (!msg.askUserAnswer && !msg.planFeedback && !msg.delegated) {
|
|
1044
|
+
markAllToolsDone();
|
|
1045
|
+
// Older histories predate explicit foreground presentation boundaries.
|
|
1046
|
+
finalizeAssistantBlock();
|
|
1047
|
+
}
|
|
1043
1048
|
resetThinkingGroup();
|
|
1044
1049
|
if (msg.planContent) {
|
|
1045
1050
|
setPlanContent(msg.planContent);
|
|
@@ -1136,7 +1141,7 @@ export function processMessage(msg) {
|
|
|
1136
1141
|
// events make it through.
|
|
1137
1142
|
removeMatePreThinking();
|
|
1138
1143
|
if (!(store.get('dmMode') && store.get('dmTargetUser') && store.get('dmTargetUser').isMate) && !store.get('matePreThinkingEl')) {
|
|
1139
|
-
setActivity("thinking");
|
|
1144
|
+
setActivity((store.get("turnActivity") || {}).phase || "thinking");
|
|
1140
1145
|
}
|
|
1141
1146
|
}
|
|
1142
1147
|
break;
|
|
@@ -1172,8 +1177,24 @@ export function processMessage(msg) {
|
|
|
1172
1177
|
}
|
|
1173
1178
|
break;
|
|
1174
1179
|
|
|
1180
|
+
case "turn_activity":
|
|
1181
|
+
if (["waiting", "running", "background"].indexOf(msg.phase) === -1) break;
|
|
1182
|
+
store.set({ turnActivity: { phase: msg.phase, turnId: msg.turnId || null, disposition: msg.disposition || null } });
|
|
1183
|
+
if (!store.get('replayingHistory') && store.get('sessionIsProcessing')) {
|
|
1184
|
+
removeMatePreThinking();
|
|
1185
|
+
setActivity(msg.phase);
|
|
1186
|
+
}
|
|
1187
|
+
break;
|
|
1188
|
+
|
|
1189
|
+
case "assistant_boundary":
|
|
1190
|
+
// Foreground presentation ended; background work still owns its real
|
|
1191
|
+
// terminal. Flush pending animation text without finishing tools/Stop.
|
|
1192
|
+
finalizeAssistantBlock();
|
|
1193
|
+
break;
|
|
1194
|
+
|
|
1175
1195
|
case "delta":
|
|
1176
1196
|
if (typeof msg.text !== "string") break;
|
|
1197
|
+
store.set({ turnActivity: null });
|
|
1177
1198
|
removeMatePreThinking();
|
|
1178
1199
|
stopThinking();
|
|
1179
1200
|
setActivity(null);
|
|
@@ -1221,6 +1242,8 @@ export function processMessage(msg) {
|
|
|
1221
1242
|
renderMcpDebateProposal(msg.id, msg.input);
|
|
1222
1243
|
startUrgentBlink();
|
|
1223
1244
|
} else if (msg.name === "AskUserQuestion" && msg.input && msg.input.questions) {
|
|
1245
|
+
store.set({ turnActivity: null });
|
|
1246
|
+
setActivity(null);
|
|
1224
1247
|
var askTool = getTools()[msg.id];
|
|
1225
1248
|
if (askTool) {
|
|
1226
1249
|
if (askTool.el) askTool.el.style.display = "none";
|
|
@@ -1301,6 +1324,7 @@ export function processMessage(msg) {
|
|
|
1301
1324
|
break;
|
|
1302
1325
|
|
|
1303
1326
|
case "permission_request":
|
|
1327
|
+
store.set({ turnActivity: null });
|
|
1304
1328
|
setActivity(null);
|
|
1305
1329
|
renderPermissionRequest(msg.requestId, msg.toolName, msg.toolInput, msg.decisionReason, msg.mateId, msg.vendor, msg);
|
|
1306
1330
|
startUrgentBlink();
|
|
@@ -1317,12 +1341,15 @@ export function processMessage(msg) {
|
|
|
1317
1341
|
break;
|
|
1318
1342
|
|
|
1319
1343
|
case "permission_request_pending":
|
|
1344
|
+
store.set({ turnActivity: null });
|
|
1320
1345
|
setActivity(null);
|
|
1321
1346
|
renderPermissionRequest(msg.requestId, msg.toolName, msg.toolInput, msg.decisionReason, msg.mateId, msg.vendor, msg);
|
|
1322
1347
|
startUrgentBlink();
|
|
1323
1348
|
break;
|
|
1324
1349
|
|
|
1325
1350
|
case "elicitation_request":
|
|
1351
|
+
store.set({ turnActivity: null });
|
|
1352
|
+
setActivity(null);
|
|
1326
1353
|
renderElicitationRequest(msg);
|
|
1327
1354
|
startUrgentBlink();
|
|
1328
1355
|
break;
|
|
@@ -1337,6 +1364,8 @@ export function processMessage(msg) {
|
|
|
1337
1364
|
break;
|
|
1338
1365
|
|
|
1339
1366
|
case "user_dialog_request":
|
|
1367
|
+
store.set({ turnActivity: null });
|
|
1368
|
+
setActivity(null);
|
|
1340
1369
|
renderUserDialogRequest(msg);
|
|
1341
1370
|
startUrgentBlink();
|
|
1342
1371
|
break;
|
|
@@ -1402,7 +1431,7 @@ export function processMessage(msg) {
|
|
|
1402
1431
|
finalizeAssistantBlock();
|
|
1403
1432
|
addTurnMeta(msg.cost, msg.duration);
|
|
1404
1433
|
accumulateUsage(msg.cost, msg.usage);
|
|
1405
|
-
accumulateContext(msg.cost, msg.usage, msg.modelUsage, msg.lastStreamInputTokens);
|
|
1434
|
+
accumulateContext(msg.cost, msg.usage, msg.modelUsage, msg.lastStreamInputTokens, msg.context);
|
|
1406
1435
|
break;
|
|
1407
1436
|
|
|
1408
1437
|
case "context_usage":
|
|
@@ -1415,6 +1444,7 @@ export function processMessage(msg) {
|
|
|
1415
1444
|
break;
|
|
1416
1445
|
|
|
1417
1446
|
case "done":
|
|
1447
|
+
store.set({ turnActivity: null });
|
|
1418
1448
|
removeMatePreThinking();
|
|
1419
1449
|
setActivity(null);
|
|
1420
1450
|
finishThinkingTurn();
|
|
@@ -1438,6 +1468,7 @@ export function processMessage(msg) {
|
|
|
1438
1468
|
break;
|
|
1439
1469
|
|
|
1440
1470
|
case "error":
|
|
1471
|
+
store.set({ turnActivity: null });
|
|
1441
1472
|
removeMatePreThinking();
|
|
1442
1473
|
setActivity(null);
|
|
1443
1474
|
finishThinkingTurn();
|
|
@@ -26,8 +26,7 @@ function getVendorLoginCommand(vendor) {
|
|
|
26
26
|
var vendors = store.get('vendorInfo') || {};
|
|
27
27
|
var info = vendors[vendor];
|
|
28
28
|
if (info && info.loginCommand) return info.loginCommand;
|
|
29
|
-
|
|
30
|
-
return fallbacks[vendor] || fallbacks.claude;
|
|
29
|
+
return "";
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
// --- Pending TUI attention tracking ---
|