clay-server 3.4.0-beta.11 → 3.4.0-beta.13
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/project-models.js +216 -0
- package/lib/project-session-handoff.js +162 -0
- package/lib/project-sessions.js +0 -8
- package/lib/project.js +30 -73
- package/lib/public/app.js +8 -0
- package/lib/public/css/menus.css +35 -56
- package/lib/public/css/pane.css +7 -1
- package/lib/public/css/session-actions.css +98 -0
- package/lib/public/index.html +4 -8
- package/lib/public/modules/agent-config-selects.js +69 -0
- package/lib/public/modules/app-header.js +0 -22
- package/lib/public/modules/app-messages.js +17 -5
- package/lib/public/modules/app-panels.js +13 -80
- package/lib/public/modules/app-projects.js +2 -0
- package/lib/public/modules/model-picker.js +262 -0
- package/lib/public/modules/session-actions.js +294 -0
- package/lib/public/modules/split-pair-ui.js +16 -78
- package/lib/public/modules/split-view.js +3 -0
- package/lib/public/style.css +1 -0
- package/lib/sdk-bridge.js +7 -3
- package/lib/session-handoff-context.js +110 -0
- package/lib/sessions.js +2 -0
- package/lib/ws-schema.js +8 -1
- package/lib/yoke/adapters/codex.js +3 -2
- package/lib/yoke/adapters/kiro.js +2 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { store } from './store.js';
|
|
2
2
|
import { getWs } from './ws-ref.js';
|
|
3
|
-
import { VENDOR_AVATARS
|
|
4
|
-
import {
|
|
3
|
+
import { VENDOR_AVATARS } from './app-rendering.js';
|
|
4
|
+
import { buildAgentVendorSelect, fillAgentModels, buildAgentEffortSelect, fillAgentEffort } from './agent-config-selects.js';
|
|
5
5
|
import { showToast } from './utils.js';
|
|
6
6
|
|
|
7
7
|
var pairDialog = null;
|
|
@@ -9,78 +9,14 @@ var pairDialog = null;
|
|
|
9
9
|
// that session becomes the Driver and the dialog only configures the Worker.
|
|
10
10
|
var pendingDriver = null;
|
|
11
11
|
|
|
12
|
-
function optionValue(entry) {
|
|
13
|
-
if (typeof entry === "string") return entry;
|
|
14
|
-
return entry && (entry.value || entry.id) || "";
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function optionLabel(entry) {
|
|
18
|
-
if (typeof entry === "string") return entry;
|
|
19
|
-
return entry && (entry.displayName || entry.name || entry.value || entry.id) || "";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function fillModels(select, vendor, options) {
|
|
23
|
-
var models = (options.modelsByVendor && options.modelsByVendor[vendor]) || [];
|
|
24
|
-
select.innerHTML = "";
|
|
25
|
-
var automatic = document.createElement("option");
|
|
26
|
-
automatic.value = "";
|
|
27
|
-
automatic.textContent = "Automatic";
|
|
28
|
-
select.appendChild(automatic);
|
|
29
|
-
for (var i = 0; i < models.length; i++) {
|
|
30
|
-
var option = document.createElement("option");
|
|
31
|
-
option.value = optionValue(models[i]);
|
|
32
|
-
option.textContent = optionLabel(models[i]);
|
|
33
|
-
select.appendChild(option);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
12
|
function closePairDialog() {
|
|
38
13
|
if (pairDialog) pairDialog.remove();
|
|
39
14
|
pairDialog = null;
|
|
40
15
|
}
|
|
41
16
|
|
|
42
|
-
function buildVendorSelect(installed, preferred) {
|
|
43
|
-
var select = document.createElement("select");
|
|
44
|
-
select.className = "wt-modal-input";
|
|
45
|
-
for (var i = 0; i < VENDOR_ORDER.length; i++) {
|
|
46
|
-
if (installed.indexOf(VENDOR_ORDER[i]) === -1) continue;
|
|
47
|
-
var option = document.createElement("option");
|
|
48
|
-
option.value = VENDOR_ORDER[i];
|
|
49
|
-
option.textContent = (isExperimentalVendor(VENDOR_ORDER[i]) ? "🧪 " : "") + (VENDOR_NAMES[VENDOR_ORDER[i]] || VENDOR_ORDER[i]);
|
|
50
|
-
if (isExperimentalVendor(VENDOR_ORDER[i])) option.title = "Experimental integration; not yet validated through direct use testing";
|
|
51
|
-
select.appendChild(option);
|
|
52
|
-
}
|
|
53
|
-
if (preferred && installed.indexOf(preferred) !== -1) select.value = preferred;
|
|
54
|
-
return select;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
17
|
// Effort levels are vendor- and model-specific (codex: minimal..xhigh,
|
|
58
18
|
// claude/kiro: low..max, plus per-model supportedEffortLevels overrides), so
|
|
59
19
|
// options are rebuilt whenever the role's vendor or model changes.
|
|
60
|
-
function fillEffortOptions(select, vendor, options, modelValue) {
|
|
61
|
-
var previous = select.value;
|
|
62
|
-
var models = (options.modelsByVendor && options.modelsByVendor[vendor]) || [];
|
|
63
|
-
var levels = effortLevelsFor(vendor, models, modelValue);
|
|
64
|
-
select.innerHTML = "";
|
|
65
|
-
var automatic = document.createElement("option");
|
|
66
|
-
automatic.value = "";
|
|
67
|
-
automatic.textContent = "Default";
|
|
68
|
-
select.appendChild(automatic);
|
|
69
|
-
for (var i = 0; i < levels.length; i++) {
|
|
70
|
-
var option = document.createElement("option");
|
|
71
|
-
option.value = levels[i];
|
|
72
|
-
option.textContent = effortDisplayName(levels[i]);
|
|
73
|
-
select.appendChild(option);
|
|
74
|
-
}
|
|
75
|
-
select.value = levels.indexOf(previous) !== -1 ? previous : "";
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function buildEffortSelect() {
|
|
79
|
-
var select = document.createElement("select");
|
|
80
|
-
select.className = "wt-modal-input";
|
|
81
|
-
return select;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
20
|
function fieldLabel(text, control) {
|
|
85
21
|
var label = document.createElement("label");
|
|
86
22
|
label.className = "wt-modal-label";
|
|
@@ -155,25 +91,25 @@ export function showPairDialog(options) {
|
|
|
155
91
|
: "One Driver plans and directs a visible Worker session.";
|
|
156
92
|
modal.appendChild(desc);
|
|
157
93
|
|
|
158
|
-
var driverVendor =
|
|
94
|
+
var driverVendor = buildAgentVendorSelect(installed, installed.indexOf("claude") !== -1 ? "claude" : installed[0]);
|
|
159
95
|
var workerDefault = options.lastVendor && options.lastVendor !== driverVendor.value ? options.lastVendor : (installed.indexOf("codex") !== -1 ? "codex" : installed[0]);
|
|
160
|
-
var workerVendor =
|
|
96
|
+
var workerVendor = buildAgentVendorSelect(installed, workerDefault);
|
|
161
97
|
var driverModel = document.createElement("select");
|
|
162
98
|
driverModel.className = "wt-modal-input";
|
|
163
99
|
var workerModel = document.createElement("select");
|
|
164
100
|
workerModel.className = "wt-modal-input";
|
|
165
|
-
var driverEffort =
|
|
166
|
-
var workerEffort =
|
|
167
|
-
function refreshDriverEffort() {
|
|
168
|
-
function refreshWorkerEffort() {
|
|
169
|
-
|
|
170
|
-
|
|
101
|
+
var driverEffort = buildAgentEffortSelect();
|
|
102
|
+
var workerEffort = buildAgentEffortSelect();
|
|
103
|
+
function refreshDriverEffort() { fillAgentEffort(driverEffort, driverVendor.value, options, driverModel.value); }
|
|
104
|
+
function refreshWorkerEffort() { fillAgentEffort(workerEffort, workerVendor.value, options, workerModel.value); }
|
|
105
|
+
fillAgentModels(driverModel, driverVendor.value, options);
|
|
106
|
+
fillAgentModels(workerModel, workerVendor.value, options);
|
|
171
107
|
refreshDriverEffort();
|
|
172
108
|
refreshWorkerEffort();
|
|
173
109
|
workerEffort.value = "medium";
|
|
174
110
|
if (workerEffort.value !== "medium") workerEffort.value = "";
|
|
175
|
-
driverVendor.addEventListener("change", function () {
|
|
176
|
-
workerVendor.addEventListener("change", function () {
|
|
111
|
+
driverVendor.addEventListener("change", function () { fillAgentModels(driverModel, driverVendor.value, options); refreshDriverEffort(); });
|
|
112
|
+
workerVendor.addEventListener("change", function () { fillAgentModels(workerModel, workerVendor.value, options); refreshWorkerEffort(); });
|
|
177
113
|
driverModel.addEventListener("change", refreshDriverEffort);
|
|
178
114
|
workerModel.addEventListener("change", refreshWorkerEffort);
|
|
179
115
|
|
|
@@ -319,7 +255,8 @@ export function syncPairChrome(host, split) {
|
|
|
319
255
|
setBtn.title = "Make this session the Driver; the other pane becomes its Worker";
|
|
320
256
|
setBtn.addEventListener("click", function () { sendSetPair(group.id, paneSessionId); });
|
|
321
257
|
var titleEl = header.querySelector(".split-pane-title");
|
|
322
|
-
|
|
258
|
+
var accessEl = header.querySelector(".split-pane-full-access");
|
|
259
|
+
header.insertBefore(setBtn, accessEl ? accessEl.nextSibling : (titleEl ? titleEl.nextSibling : null));
|
|
323
260
|
})(split.panes[ai].sessionId, headers[ai]);
|
|
324
261
|
}
|
|
325
262
|
return;
|
|
@@ -339,7 +276,8 @@ export function syncPairChrome(host, split) {
|
|
|
339
276
|
sendSetPair(group.id, isDriver ? null : sessionId);
|
|
340
277
|
});
|
|
341
278
|
var title = header.querySelector(".split-pane-title");
|
|
342
|
-
|
|
279
|
+
var access = header.querySelector(".split-pane-full-access");
|
|
280
|
+
header.insertBefore(badge, access ? access.nextSibling : (title ? title.nextSibling : null));
|
|
343
281
|
})(split.panes[pi].sessionId, headers[pi]);
|
|
344
282
|
}
|
|
345
283
|
var active = (store.get('splitDelegations') || {})[group.id];
|
|
@@ -231,6 +231,9 @@ function createPane(pane, index) {
|
|
|
231
231
|
}, "Skip Permissions", true);
|
|
232
232
|
});
|
|
233
233
|
header.appendChild(fullAccess);
|
|
234
|
+
// Permission state belongs to the session identity on the left. Keep it
|
|
235
|
+
// immediately after the title instead of grouping it with usage and close.
|
|
236
|
+
header.insertBefore(fullAccess, ctxChip);
|
|
234
237
|
|
|
235
238
|
var close = document.createElement("button");
|
|
236
239
|
close.type = "button";
|
package/lib/public/style.css
CHANGED
package/lib/sdk-bridge.js
CHANGED
|
@@ -1931,10 +1931,12 @@ function createSDKBridge(opts) {
|
|
|
1931
1931
|
session.model = model;
|
|
1932
1932
|
sm.saveSessionFile(session);
|
|
1933
1933
|
sm.currentModel = model;
|
|
1934
|
-
//
|
|
1935
|
-
|
|
1934
|
+
// Confirm against the session vendor so a non-default vendor does not
|
|
1935
|
+
// receive model metadata labeled as the project's default adapter.
|
|
1936
|
+
var pendingVendor = session.vendor || (adapter && adapter.vendor) || "claude";
|
|
1937
|
+
sendModelInfoForVendor(pendingVendor, model);
|
|
1936
1938
|
sendToSession(session, { type: "config_state", model: sm.currentModel, mode: session.permissionMode || sm.currentPermissionMode || "default", effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1937
|
-
return;
|
|
1939
|
+
return { ok: true, model: model };
|
|
1938
1940
|
}
|
|
1939
1941
|
try {
|
|
1940
1942
|
await session.queryInstance.setModel(model);
|
|
@@ -1944,8 +1946,10 @@ function createSDKBridge(opts) {
|
|
|
1944
1946
|
var sessionVendor = session.vendor || (adapter && adapter.vendor) || "claude";
|
|
1945
1947
|
sendModelInfoForVendor(sessionVendor, model);
|
|
1946
1948
|
sendToSession(session, { type: "config_state", model: sm.currentModel, mode: session.permissionMode || sm.currentPermissionMode || "default", effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1949
|
+
return { ok: true, model: model };
|
|
1947
1950
|
} catch (e) {
|
|
1948
1951
|
send({ type: "error", text: "Failed to switch model: " + (e.message || e) });
|
|
1952
|
+
return { ok: false, model: session.model || "", error: e.message || String(e) };
|
|
1949
1953
|
}
|
|
1950
1954
|
}
|
|
1951
1955
|
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
var spawnSync = require("child_process").spawnSync;
|
|
2
|
+
var yoke = require("./yoke");
|
|
3
|
+
|
|
4
|
+
var MAX_CONTEXT_CHARS = 36000;
|
|
5
|
+
var MAX_TURNS = 12;
|
|
6
|
+
var MAX_USER_CHARS = 5000;
|
|
7
|
+
var MAX_ASSISTANT_CHARS = 9000;
|
|
8
|
+
var MAX_GIT_CHARS = 5000;
|
|
9
|
+
var MAX_TRANSCRIPT_CHARS = 24000;
|
|
10
|
+
|
|
11
|
+
function trimText(value, limit) {
|
|
12
|
+
var text = typeof value === "string" ? value.trim() : "";
|
|
13
|
+
if (text.length <= limit) return text;
|
|
14
|
+
return text.slice(0, limit) + "\n[truncated]";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function recentTurns(history) {
|
|
18
|
+
var turns = [];
|
|
19
|
+
var current = null;
|
|
20
|
+
history = Array.isArray(history) ? history : [];
|
|
21
|
+
for (var i = 0; i < history.length; i++) {
|
|
22
|
+
var entry = history[i];
|
|
23
|
+
if (!entry) continue;
|
|
24
|
+
if (entry.type === "user_message" || (entry.type === "handoff_context" && entry.request)) {
|
|
25
|
+
current = { user: trimText(entry.text || entry.request, MAX_USER_CHARS), assistant: "" };
|
|
26
|
+
turns.push(current);
|
|
27
|
+
} else if (entry.type === "delta" && entry.text) {
|
|
28
|
+
if (!current) {
|
|
29
|
+
current = { user: "", assistant: "" };
|
|
30
|
+
turns.push(current);
|
|
31
|
+
}
|
|
32
|
+
current.assistant += entry.text;
|
|
33
|
+
if (current.assistant.length > MAX_ASSISTANT_CHARS) {
|
|
34
|
+
current.assistant = current.assistant.slice(-MAX_ASSISTANT_CHARS);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return turns.slice(-MAX_TURNS);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function latestUserRequest(history) {
|
|
42
|
+
var turns = recentTurns(history);
|
|
43
|
+
for (var i = turns.length - 1; i >= 0; i--) {
|
|
44
|
+
if (turns[i].user) return turns[i].user;
|
|
45
|
+
}
|
|
46
|
+
return "";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function gitCommand(cwd, args) {
|
|
50
|
+
var result = spawnSync("git", args, {
|
|
51
|
+
cwd: cwd,
|
|
52
|
+
encoding: "utf8",
|
|
53
|
+
timeout: 5000,
|
|
54
|
+
maxBuffer: 1024 * 1024,
|
|
55
|
+
});
|
|
56
|
+
if (result.error || result.status !== 0) return "";
|
|
57
|
+
return trimText(result.stdout, MAX_GIT_CHARS);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function repositoryState(cwd) {
|
|
61
|
+
var status = gitCommand(cwd, ["status", "--short", "--branch"]);
|
|
62
|
+
var lines = [];
|
|
63
|
+
lines.push("Working tree:\n" + (status || "clean"));
|
|
64
|
+
return lines.join("\n\n");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function transcriptText(turns) {
|
|
68
|
+
var sections = [];
|
|
69
|
+
for (var i = 0; i < turns.length; i++) {
|
|
70
|
+
var turn = turns[i];
|
|
71
|
+
var parts = ["Turn " + (i + 1)];
|
|
72
|
+
if (turn.user) parts.push("USER:\n" + turn.user);
|
|
73
|
+
if (turn.assistant) parts.push("ASSISTANT:\n" + trimText(turn.assistant, MAX_ASSISTANT_CHARS));
|
|
74
|
+
sections.push(parts.join("\n\n"));
|
|
75
|
+
}
|
|
76
|
+
while (sections.length > 1 && sections.join("\n\n---\n\n").length > MAX_TRANSCRIPT_CHARS) {
|
|
77
|
+
sections.shift();
|
|
78
|
+
}
|
|
79
|
+
return sections.join("\n\n---\n\n");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function buildHandoffContext(options) {
|
|
83
|
+
var source = options.source;
|
|
84
|
+
var targetVendor = options.targetVendor;
|
|
85
|
+
var sourceVendor = source.vendor || "claude";
|
|
86
|
+
var sourceName = (yoke.getVendorInfo(sourceVendor) || {}).displayName || sourceVendor;
|
|
87
|
+
var targetName = (yoke.getVendorInfo(targetVendor) || {}).displayName || targetVendor;
|
|
88
|
+
var turns = recentTurns(source.history);
|
|
89
|
+
var latestUser = latestUserRequest(source.history);
|
|
90
|
+
var parts = [
|
|
91
|
+
"[Clay session handoff]",
|
|
92
|
+
"You are continuing work from another Clay coding-agent session. This is a snapshot, not a native conversation resume. Verify the current filesystem state before acting.",
|
|
93
|
+
"Source agent: " + sourceName,
|
|
94
|
+
"Target agent: " + targetName,
|
|
95
|
+
"Source session: " + (source.title || "Untitled session") + " (#" + source.localId + ")",
|
|
96
|
+
];
|
|
97
|
+
if (latestUser) parts.push("Current user request, verbatim:\n" + latestUser);
|
|
98
|
+
parts.push("Repository state at handoff:\n" + repositoryState(options.cwd));
|
|
99
|
+
parts.push("Recent conversation:\n" + transcriptText(turns));
|
|
100
|
+
parts.push("Continue from the unresolved work above. Preserve the user's decisions and constraints, inspect the actual files before making assumptions, and proceed without asking the user to repeat context.");
|
|
101
|
+
return trimText(parts.join("\n\n"), MAX_CONTEXT_CHARS);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
MAX_CONTEXT_CHARS: MAX_CONTEXT_CHARS,
|
|
106
|
+
buildHandoffContext: buildHandoffContext,
|
|
107
|
+
latestUserRequest: latestUserRequest,
|
|
108
|
+
recentTurns: recentTurns,
|
|
109
|
+
repositoryState: repositoryState,
|
|
110
|
+
};
|
package/lib/sessions.js
CHANGED
|
@@ -169,6 +169,7 @@ function createSessionManager(opts) {
|
|
|
169
169
|
if (session.lastRewindUuid) metaObj.lastRewindUuid = session.lastRewindUuid;
|
|
170
170
|
if (session.loop) metaObj.loop = session.loop;
|
|
171
171
|
if (session.spawn) metaObj.spawn = session.spawn;
|
|
172
|
+
if (session.handoff) metaObj.handoff = session.handoff;
|
|
172
173
|
if (session.debateState) metaObj.debateState = session.debateState;
|
|
173
174
|
if (session.debateSetupMode) metaObj.debateSetupMode = true;
|
|
174
175
|
var meta = JSON.stringify(metaObj);
|
|
@@ -281,6 +282,7 @@ function createSessionManager(opts) {
|
|
|
281
282
|
session.effort = m.effort || null;
|
|
282
283
|
if (m.loop) session.loop = m.loop;
|
|
283
284
|
if (m.spawn) session.spawn = m.spawn;
|
|
285
|
+
if (m.handoff) session.handoff = m.handoff;
|
|
284
286
|
if (m.debateState) session.debateState = m.debateState;
|
|
285
287
|
if (m.debateSetupMode) session.debateSetupMode = true;
|
|
286
288
|
if (m.ownerId) session.ownerId = m.ownerId;
|
package/lib/ws-schema.js
CHANGED
|
@@ -30,6 +30,8 @@ var schema = {
|
|
|
30
30
|
"search_session_content": { direction: "c2s", handler: "lib/project-sessions.js", description: "Full-text search within a session" },
|
|
31
31
|
"load_more_history": { direction: "c2s", handler: "lib/project-sessions.js", description: "Request older history entries for the current session" },
|
|
32
32
|
"fork_session": { direction: "c2s", handler: "lib/project-sessions.js", description: "Fork a session from a given message UUID" },
|
|
33
|
+
"handoff_session": { direction: "c2s", handler: "lib/project-session-handoff.js", description: "Continue the active session in a newly created agent session" },
|
|
34
|
+
"handoff_session_options": { direction: "c2s", handler: "lib/project-session-handoff.js", description: "Request vendors, models, and effort capabilities for the handoff dialog (response reuses the same type)" },
|
|
33
35
|
"input_sync": { direction: "c2s", handler: "lib/project-sessions.js", description: "Sync the current input field text to other clients" },
|
|
34
36
|
"tui_transcript_request": { direction: "c2s", handler: "lib/project-sessions.js", description: "Ask for the assistant text index of a Claude TUI session (for hover-to-grab)" },
|
|
35
37
|
"split_group_create": { direction: "c2s", handler: "lib/session-split-groups.js", description: "Create a persistent two-session split group" },
|
|
@@ -49,6 +51,9 @@ var schema = {
|
|
|
49
51
|
"search_results": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Session title search results" },
|
|
50
52
|
"search_content_results": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Full-text content search results" },
|
|
51
53
|
"fork_complete": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Fork succeeded, includes new session ID" },
|
|
54
|
+
"session_handoff_result": { direction: "s2c", handler: "lib/public/modules/session-actions.js", description: "Session handoff result and new target session ID" },
|
|
55
|
+
"handoff_context": { direction: "s2c", handler: "lib/public/modules/session-actions.js", description: "Timeline marker identifying the source of a handoff session" },
|
|
56
|
+
"handoff_created": { direction: "s2c", handler: "lib/public/modules/session-actions.js", description: "Timeline marker linking a source session to its handoff target" },
|
|
52
57
|
"input_sync_broadcast": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Broadcast input text from another client" },
|
|
53
58
|
"tui_transcript_state": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Assistant text index for a Claude TUI session (full replace; sent on request and after each new assistant message)" },
|
|
54
59
|
"split_groups": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Full persistent split-group list for the current user" },
|
|
@@ -175,7 +180,8 @@ var schema = {
|
|
|
175
180
|
// -----------------------------------------------------------------------
|
|
176
181
|
// Model / config
|
|
177
182
|
// -----------------------------------------------------------------------
|
|
178
|
-
"set_model": { direction: "c2s", handler: "lib/project-
|
|
183
|
+
"set_model": { direction: "c2s", handler: "lib/project-models.js", description: "Set the model for the current session" },
|
|
184
|
+
"get_vendor_models": { direction: "c2s", handler: "lib/project-models.js", description: "Load a vendor model catalog" },
|
|
179
185
|
"set_server_default_model": { direction: "c2s", handler: "lib/project-sessions.js", description: "Set the server-wide default model" },
|
|
180
186
|
"set_project_default_model": { direction: "c2s", handler: "lib/project-sessions.js", description: "Set the project default model" },
|
|
181
187
|
"set_permission_mode": { direction: "c2s", handler: "lib/project-sessions.js", description: "Set permission mode for the current session" },
|
|
@@ -192,6 +198,7 @@ var schema = {
|
|
|
192
198
|
"set_betas": { direction: "c2s", handler: "lib/project-sessions.js", description: "Set beta feature flags" },
|
|
193
199
|
"set_thinking": { direction: "c2s", handler: "lib/project-sessions.js", description: "Set thinking mode and budget" },
|
|
194
200
|
"model_info": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Current model and available models list" },
|
|
201
|
+
"model_selection_result": { direction: "s2c", handler: "lib/public/modules/model-picker.js", description: "Acknowledgement or error for a model selection" },
|
|
195
202
|
"config_state": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Full config state: model, mode, effort, betas, thinking" },
|
|
196
203
|
"slash_commands": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Available slash commands list" },
|
|
197
204
|
"fast_mode_state": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Fast mode toggle state" },
|
|
@@ -1072,6 +1072,7 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
1072
1072
|
await appServer.send("turn/start", {
|
|
1073
1073
|
threadId: state.threadId,
|
|
1074
1074
|
input: input,
|
|
1075
|
+
model: state.model,
|
|
1075
1076
|
}, 60000);
|
|
1076
1077
|
|
|
1077
1078
|
// Wait for turn to complete
|
|
@@ -1144,7 +1145,7 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
1144
1145
|
},
|
|
1145
1146
|
|
|
1146
1147
|
setModel: function(model) {
|
|
1147
|
-
|
|
1148
|
+
state.model = model || "gpt-5.6-terra";
|
|
1148
1149
|
return Promise.resolve();
|
|
1149
1150
|
},
|
|
1150
1151
|
|
|
@@ -1326,7 +1327,7 @@ function createCodexAdapter(opts) {
|
|
|
1326
1327
|
fastModeState: null,
|
|
1327
1328
|
capabilities: {
|
|
1328
1329
|
effort: true,
|
|
1329
|
-
midSessionModelSwitch:
|
|
1330
|
+
midSessionModelSwitch: true,
|
|
1330
1331
|
fork: true,
|
|
1331
1332
|
rollback: true,
|
|
1332
1333
|
sessionListing: false,
|
|
@@ -762,7 +762,7 @@ function createKiroQueryHandle(acp, queryOpts) {
|
|
|
762
762
|
|
|
763
763
|
setModel: function(model) {
|
|
764
764
|
state.model = model;
|
|
765
|
-
return setSessionModel(model)
|
|
765
|
+
return setSessionModel(model);
|
|
766
766
|
},
|
|
767
767
|
|
|
768
768
|
setEffort: function() { return Promise.resolve(); },
|
|
@@ -867,7 +867,7 @@ function createKiroAdapter(opts) {
|
|
|
867
867
|
fastModeState: null,
|
|
868
868
|
capabilities: {
|
|
869
869
|
effort: false,
|
|
870
|
-
midSessionModelSwitch:
|
|
870
|
+
midSessionModelSwitch: true,
|
|
871
871
|
fork: false,
|
|
872
872
|
rollback: false,
|
|
873
873
|
sessionListing: false,
|
package/package.json
CHANGED