clay-server 3.4.0-beta.17 → 3.4.0-beta.19
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-connection.js +18 -6
- package/lib/project-models.js +6 -2
- package/lib/project-sessions.js +13 -37
- package/lib/project-worker-proposal.js +49 -14
- package/lib/project.js +3 -4
- package/lib/public/modules/app-messages.js +23 -4
- package/lib/public/modules/model-picker.js +1 -0
- package/lib/public/modules/worker-proposal.js +5 -1
- package/lib/sdk-bridge.js +36 -31
- package/lib/sdk-message-processor.js +11 -4
- package/package.json +1 -1
|
@@ -22,12 +22,23 @@ function dispatchMessageSafely(handleMessage, sendTo, slug, ws, msg) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function buildInitialModelInfo(sm, initialVendor, initialModel, initialModels) {
|
|
25
|
+
function buildInitialModelInfo(sm, initialVendor, initialModel, initialModels, sessionId) {
|
|
26
|
+
var model = initialModel || "";
|
|
27
|
+
var models = initialModels || [];
|
|
28
|
+
if (model && models.length > 0) {
|
|
29
|
+
var found = false;
|
|
30
|
+
for (var i = 0; i < models.length; i++) {
|
|
31
|
+
var entry = models[i];
|
|
32
|
+
if (typeof entry === "string" ? entry === model : (entry.value === model || entry.id === model || entry.resolvedModel === model)) found = true;
|
|
33
|
+
}
|
|
34
|
+
if (!found) model = typeof models[0] === "string" ? models[0] : (models[0].value || models[0].id || "");
|
|
35
|
+
}
|
|
26
36
|
return {
|
|
27
37
|
type: "model_info",
|
|
28
|
-
model:
|
|
29
|
-
models:
|
|
38
|
+
model: model,
|
|
39
|
+
models: models,
|
|
30
40
|
vendor: initialVendor,
|
|
41
|
+
sessionId: sessionId || null,
|
|
31
42
|
availableVendors: sm.availableVendors || [],
|
|
32
43
|
installedVendors: sm.installedVendors || [],
|
|
33
44
|
};
|
|
@@ -177,11 +188,12 @@ function attachConnection(ctx) {
|
|
|
177
188
|
if (sm.slashCommands) {
|
|
178
189
|
sendTo(ws, { type: "slash_commands", commands: sm.slashCommands });
|
|
179
190
|
}
|
|
180
|
-
var initialModel = (restoredActive && restoredActive.model) || sm.
|
|
191
|
+
var initialModel = (restoredActive && restoredActive.model) || ((sm.defaultModelByVendor || {})[initialVendor]) || "";
|
|
181
192
|
// Vendor installation state is needed even before a new project has a
|
|
182
193
|
// model. Always send it so reconnects cannot fall back to "Not installed."
|
|
183
|
-
|
|
184
|
-
sendTo(ws,
|
|
194
|
+
var initialModelInfo = buildInitialModelInfo(sm, initialVendor, initialModel, initialModels, restoredActive ? restoredActive.localId : null);
|
|
195
|
+
sendTo(ws, initialModelInfo);
|
|
196
|
+
sendTo(ws, { type: "config_state", model: initialModelInfo.model, vendor: initialVendor, sessionId: restoredActive ? restoredActive.localId : null, mode: sm.currentPermissionMode || "default", effort: initialEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
185
197
|
sendTo(ws, { type: "last_vendor", vendor: sm.lastVendor || "" });
|
|
186
198
|
sendTo(ws, Object.assign({ type: "codex_config" }, getCodexConfig(sm)));
|
|
187
199
|
sendTo(ws, { type: "term_list", terminals: tm.list() });
|
package/lib/project-models.js
CHANGED
|
@@ -30,6 +30,7 @@ function attachModels(ctx) {
|
|
|
30
30
|
var requestId = msg.requestId || null;
|
|
31
31
|
var loadError = null;
|
|
32
32
|
var vendorAdapter = null;
|
|
33
|
+
var session = getSessionForWs(ws);
|
|
33
34
|
|
|
34
35
|
if (!vendor) {
|
|
35
36
|
sendTo(ws, {
|
|
@@ -40,6 +41,7 @@ function attachModels(ctx) {
|
|
|
40
41
|
error: "No vendor was selected.",
|
|
41
42
|
model: "",
|
|
42
43
|
models: [],
|
|
44
|
+
sessionId: session ? session.localId : null,
|
|
43
45
|
});
|
|
44
46
|
return;
|
|
45
47
|
}
|
|
@@ -109,9 +111,10 @@ function attachModels(ctx) {
|
|
|
109
111
|
|
|
110
112
|
var vendorModels = (sm.modelsByVendor && sm.modelsByVendor[vendor]) || [];
|
|
111
113
|
var modelToSend = modelEntryValue(vendorModels[0]);
|
|
112
|
-
|
|
114
|
+
var preferredModel = (session && session.vendor === vendor && session.model) || (sm.defaultModelByVendor && sm.defaultModelByVendor[vendor]) || "";
|
|
115
|
+
if (preferredModel) {
|
|
113
116
|
for (var i = 0; i < vendorModels.length; i++) {
|
|
114
|
-
if (modelEntryMatches(vendorModels[i],
|
|
117
|
+
if (modelEntryMatches(vendorModels[i], preferredModel)) {
|
|
115
118
|
modelToSend = modelEntryValue(vendorModels[i]);
|
|
116
119
|
break;
|
|
117
120
|
}
|
|
@@ -131,6 +134,7 @@ function attachModels(ctx) {
|
|
|
131
134
|
model: modelToSend,
|
|
132
135
|
models: vendorModels,
|
|
133
136
|
vendor: vendor,
|
|
137
|
+
sessionId: session ? session.localId : null,
|
|
134
138
|
capabilities: (sm.capabilitiesByVendor && sm.capabilitiesByVendor[vendor]) || {},
|
|
135
139
|
availableVendors: sm.availableVendors || [],
|
|
136
140
|
installedVendors: sm.installedVendors || [],
|
package/lib/project-sessions.js
CHANGED
|
@@ -658,10 +658,6 @@ function attachSessions(ctx) {
|
|
|
658
658
|
// (resume_tui_session), and born-GUI never auto-converts to a terminal.
|
|
659
659
|
resolveSessionForView(xmTarget, ws);
|
|
660
660
|
}
|
|
661
|
-
// If the target session's vendor doesn't own the currently cached
|
|
662
|
-
// model, clear sm.currentModel so the UI and next query don't leak
|
|
663
|
-
// the previous session's vendor-specific model into this one. A
|
|
664
|
-
// session-specific model always wins and survives daemon restarts.
|
|
665
661
|
var switchTargetSess = sm.sessions.get(msg.id);
|
|
666
662
|
var switchTargetVendor = switchTargetSess && (switchTargetSess.vendor || sm.defaultVendor || "claude");
|
|
667
663
|
if (switchTargetSess && !switchTargetSess.effort) {
|
|
@@ -671,22 +667,6 @@ function attachSessions(ctx) {
|
|
|
671
667
|
) || null;
|
|
672
668
|
sm.saveSessionFile(switchTargetSess);
|
|
673
669
|
}
|
|
674
|
-
if (switchTargetSess && switchTargetSess.model) {
|
|
675
|
-
sm.currentModel = switchTargetSess.model;
|
|
676
|
-
} else if (switchTargetSess && sm.currentModel) {
|
|
677
|
-
var targetVendor = switchTargetSess.vendor || sm.defaultVendor || null;
|
|
678
|
-
var tvModels = (targetVendor && sm.modelsByVendor && sm.modelsByVendor[targetVendor]) || [];
|
|
679
|
-
var found = false;
|
|
680
|
-
var _curLc = sm.currentModel.toLowerCase();
|
|
681
|
-
for (var tvi = 0; tvi < tvModels.length; tvi++) {
|
|
682
|
-
var tvEntry = tvModels[tvi];
|
|
683
|
-
var tvVal = typeof tvEntry === "string" ? tvEntry : (tvEntry && (tvEntry.value || tvEntry.id)) || "";
|
|
684
|
-
if (tvVal === sm.currentModel || (tvVal && (tvVal.toLowerCase().indexOf(_curLc) !== -1 || _curLc.indexOf(tvVal.toLowerCase()) !== -1))) { found = true; break; }
|
|
685
|
-
}
|
|
686
|
-
if (tvModels.length > 0 && !found) {
|
|
687
|
-
sm.currentModel = "";
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
670
|
// Check access in multi-user mode
|
|
691
671
|
if (usersModule.isMultiUser() && ws._clayUser) {
|
|
692
672
|
var switchTarget = sm.sessions.get(msg.id);
|
|
@@ -989,11 +969,7 @@ function attachSessions(ctx) {
|
|
|
989
969
|
" is bound to '" + vendorSession.vendor + "', refused rebind to '" + msg.vendor + "'");
|
|
990
970
|
} else {
|
|
991
971
|
vendorSession.vendor = msg.vendor;
|
|
992
|
-
|
|
993
|
-
// instead of leaking the previous vendor's model into a fresh session.
|
|
994
|
-
if (sm.currentModel) {
|
|
995
|
-
sm.currentModel = "";
|
|
996
|
-
}
|
|
972
|
+
if (vendorSession.vendor !== msg.vendor) vendorSession.model = "";
|
|
997
973
|
sm.saveSessionFile(vendorSession);
|
|
998
974
|
sm.broadcastSessionList();
|
|
999
975
|
}
|
|
@@ -1004,11 +980,11 @@ function attachSessions(ctx) {
|
|
|
1004
980
|
type: "model_info",
|
|
1005
981
|
model: "",
|
|
1006
982
|
models: vendorModels,
|
|
1007
|
-
vendor: msg.vendor,
|
|
983
|
+
vendor: msg.vendor, sessionId: vendorSession ? vendorSession.localId : null,
|
|
1008
984
|
availableVendors: sm.availableVendors || [],
|
|
1009
985
|
installedVendors: sm.installedVendors || [],
|
|
1010
986
|
});
|
|
1011
|
-
send({ type: "config_state",
|
|
987
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1012
988
|
}
|
|
1013
989
|
return true;
|
|
1014
990
|
}
|
|
@@ -1044,7 +1020,7 @@ function attachSessions(ctx) {
|
|
|
1044
1020
|
sm.broadcastSessionList();
|
|
1045
1021
|
sdk.setPermissionMode(session, msg.mode);
|
|
1046
1022
|
}
|
|
1047
|
-
send({ type: "config_state",
|
|
1023
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1048
1024
|
return true;
|
|
1049
1025
|
}
|
|
1050
1026
|
|
|
@@ -1105,7 +1081,7 @@ function attachSessions(ctx) {
|
|
|
1105
1081
|
if (session) {
|
|
1106
1082
|
sdk.setPermissionMode(session, msg.mode);
|
|
1107
1083
|
}
|
|
1108
|
-
send({ type: "config_state",
|
|
1084
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1109
1085
|
return true;
|
|
1110
1086
|
}
|
|
1111
1087
|
|
|
@@ -1118,7 +1094,7 @@ function attachSessions(ctx) {
|
|
|
1118
1094
|
if (session) {
|
|
1119
1095
|
sdk.setPermissionMode(session, msg.mode);
|
|
1120
1096
|
}
|
|
1121
|
-
send({ type: "config_state",
|
|
1097
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1122
1098
|
return true;
|
|
1123
1099
|
}
|
|
1124
1100
|
|
|
@@ -1134,7 +1110,7 @@ function attachSessions(ctx) {
|
|
|
1134
1110
|
sdk.setEffort(session, sessionEffort).catch(function (e) {
|
|
1135
1111
|
sendTo(ws, { type: "error", text: "Failed to change reasoning effort: " + (e.message || e) });
|
|
1136
1112
|
});
|
|
1137
|
-
sm.sendToSession(session, { type: "config_state", model: session.model || sm.
|
|
1113
|
+
sm.sendToSession(session, { type: "config_state", model: session.model || ((sm.defaultModelByVendor || {})[effortVendor]) || "", vendor: effortVendor, sessionId: session.localId, mode: session.permissionMode || sm.currentPermissionMode || "default", effort: sessionEffort, betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1138
1114
|
}
|
|
1139
1115
|
return true;
|
|
1140
1116
|
}
|
|
@@ -1144,7 +1120,7 @@ function attachSessions(ctx) {
|
|
|
1144
1120
|
opts.onSetServerDefaultEffort(msg.effort);
|
|
1145
1121
|
}
|
|
1146
1122
|
sm.currentEffort = msg.effort;
|
|
1147
|
-
send({ type: "config_state",
|
|
1123
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode || "default", effort: sm.currentEffort, betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1148
1124
|
return true;
|
|
1149
1125
|
}
|
|
1150
1126
|
|
|
@@ -1153,20 +1129,20 @@ function attachSessions(ctx) {
|
|
|
1153
1129
|
opts.onSetProjectDefaultEffort(slug, msg.effort);
|
|
1154
1130
|
}
|
|
1155
1131
|
sm.currentEffort = msg.effort;
|
|
1156
|
-
send({ type: "config_state",
|
|
1132
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode || "default", effort: sm.currentEffort, betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1157
1133
|
return true;
|
|
1158
1134
|
}
|
|
1159
1135
|
|
|
1160
1136
|
if (msg.type === "set_betas") {
|
|
1161
1137
|
sm.currentBetas = msg.betas || [];
|
|
1162
|
-
send({ type: "config_state",
|
|
1138
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas, thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1163
1139
|
return true;
|
|
1164
1140
|
}
|
|
1165
1141
|
|
|
1166
1142
|
if (msg.type === "set_thinking") {
|
|
1167
1143
|
sm.currentThinking = msg.thinking || "adaptive";
|
|
1168
1144
|
if (msg.budgetTokens) sm.currentThinkingBudget = msg.budgetTokens;
|
|
1169
|
-
send({ type: "config_state",
|
|
1145
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1170
1146
|
return true;
|
|
1171
1147
|
}
|
|
1172
1148
|
|
|
@@ -1448,7 +1424,7 @@ function attachSessions(ctx) {
|
|
|
1448
1424
|
if (decision === "allow_accept_edits") {
|
|
1449
1425
|
sdk.setPermissionMode(session, "acceptEdits");
|
|
1450
1426
|
sm.currentPermissionMode = "acceptEdits";
|
|
1451
|
-
send({ type: "config_state",
|
|
1427
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1452
1428
|
pending.resolve({ behavior: "allow", updatedInput: pending.toolInput });
|
|
1453
1429
|
sm.sendAndRecord(session, { type: "permission_resolved", requestId: requestId, decision: decision });
|
|
1454
1430
|
return true;
|
|
@@ -1477,7 +1453,7 @@ function attachSessions(ctx) {
|
|
|
1477
1453
|
|
|
1478
1454
|
// Update permission mode for the new session
|
|
1479
1455
|
sm.currentPermissionMode = "acceptEdits";
|
|
1480
|
-
send({ type: "config_state",
|
|
1456
|
+
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode, effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1481
1457
|
|
|
1482
1458
|
// Build prompt from plan content (sent from client) or plan file path
|
|
1483
1459
|
var clientPlanContent = msg.planContent || "";
|
|
@@ -40,7 +40,7 @@ function attachWorkerProposal(ctx) {
|
|
|
40
40
|
function isEligible(session) {
|
|
41
41
|
if (ctx.isMate || !session || session.mode === "tui") return false;
|
|
42
42
|
if (store.groupForMember(session.localId)) return false;
|
|
43
|
-
return isFableSession(session, sm.modelsByVendor, sm.
|
|
43
|
+
return isFableSession(session, sm.modelsByVendor, (sm.defaultModelByVendor || {})[session.vendor || "claude"]);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function safeModelsByVendor(installed) {
|
|
@@ -112,7 +112,7 @@ function attachWorkerProposal(ctx) {
|
|
|
112
112
|
}
|
|
113
113
|
var models = options.modelsByVendor[vendor] || [];
|
|
114
114
|
var model = modelIsAvailable(options, vendor, args.recommendedModel) ? (args.recommendedModel || "") : "";
|
|
115
|
-
var currentModel = session.model || sm.
|
|
115
|
+
var currentModel = session.model || (sm.defaultModelByVendor || {})[session.vendor || "claude"] || "";
|
|
116
116
|
if (vendor === session.vendor && model === currentModel) model = "";
|
|
117
117
|
if (!model && models.length > 0) {
|
|
118
118
|
for (var j = 0; j < models.length; j++) {
|
|
@@ -154,6 +154,18 @@ function attachWorkerProposal(ctx) {
|
|
|
154
154
|
}, patch));
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
function skipPermissionsEnabled(session) {
|
|
158
|
+
return !!session && (session.permissionMode === "bypassPermissions" || session.dangerouslySkipPermissions === true);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function autoApprovalWs(session) {
|
|
162
|
+
return {
|
|
163
|
+
_clayActiveSession: session.localId,
|
|
164
|
+
_clayUser: session.ownerId ? { id: session.ownerId } : null,
|
|
165
|
+
_autoApproval: true,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
157
169
|
async function propose(args, session) {
|
|
158
170
|
if (!isEligible(session)) return toolResult({ error: "Worker suggestions are only available in an unpaired Fable session." });
|
|
159
171
|
if (hasPendingProposal(session)) return toolResult({ error: "A Worker suggestion is already awaiting a decision." });
|
|
@@ -166,6 +178,7 @@ function attachWorkerProposal(ctx) {
|
|
|
166
178
|
var options = proposalOptions();
|
|
167
179
|
if (options.installedVendors.length === 0) return toolResult({ error: "No coding agent is installed for a Worker session." });
|
|
168
180
|
var recommendation = chooseRecommendation(args, session, options);
|
|
181
|
+
var autoApprove = skipPermissionsEnabled(session);
|
|
169
182
|
var proposal = {
|
|
170
183
|
type: "worker_proposal",
|
|
171
184
|
proposalId: "worker_" + crypto.randomUUID(),
|
|
@@ -178,7 +191,22 @@ function attachWorkerProposal(ctx) {
|
|
|
178
191
|
recommendedEffort: recommendation.effort,
|
|
179
192
|
options: options,
|
|
180
193
|
};
|
|
194
|
+
if (autoApprove) proposal.autoApproved = true;
|
|
181
195
|
sm.sendAndRecord(session, proposal);
|
|
196
|
+
if (autoApprove) {
|
|
197
|
+
var accepted = await acceptProposal(session, proposal, {
|
|
198
|
+
vendor: recommendation.vendor,
|
|
199
|
+
model: recommendation.model,
|
|
200
|
+
effort: recommendation.effort,
|
|
201
|
+
autoApproved: true,
|
|
202
|
+
}, autoApprovalWs(session));
|
|
203
|
+
if (!accepted.ok) return toolResult({ error: accepted.error || "Could not start the Worker." });
|
|
204
|
+
return toolResult({
|
|
205
|
+
status: "running",
|
|
206
|
+
proposalId: proposal.proposalId,
|
|
207
|
+
instruction: "The Worker was auto-approved and started because skip permissions is enabled. Its result will return for review.",
|
|
208
|
+
});
|
|
209
|
+
}
|
|
182
210
|
return toolResult({
|
|
183
211
|
status: "posted",
|
|
184
212
|
proposalId: proposal.proposalId,
|
|
@@ -238,30 +266,24 @@ function attachWorkerProposal(ctx) {
|
|
|
238
266
|
return session;
|
|
239
267
|
}
|
|
240
268
|
|
|
241
|
-
async function
|
|
242
|
-
var session = sessionForResponse(ws);
|
|
243
|
-
var proposal = findProposal(session, msg.proposalId);
|
|
244
|
-
if (!proposal) throw new Error("Worker suggestion not found");
|
|
245
|
-
if (proposal.status !== "pending") throw new Error("Worker suggestion has already been resolved");
|
|
246
|
-
if (!msg.accepted) {
|
|
247
|
-
updateProposal(session, proposal, { status: "declined" });
|
|
248
|
-
await resumeDriver(session, "[Worker suggestion declined]\nContinue this task in the current session using the plan you already prepared.");
|
|
249
|
-
return { ok: true, status: "declined" };
|
|
250
|
-
}
|
|
269
|
+
async function acceptProposal(session, proposal, msg, ws) {
|
|
251
270
|
var options = proposal.options || proposalOptions();
|
|
252
271
|
var vendor = msg.vendor || proposal.recommendedVendor;
|
|
253
272
|
var model = msg.model || "";
|
|
254
273
|
if (options.installedVendors.indexOf(vendor) === -1) throw new Error("Selected Worker vendor is not installed");
|
|
255
274
|
if (!modelIsAvailable(options, vendor, model)) throw new Error("Selected Worker model is unavailable");
|
|
256
275
|
var effort = yoke.clampEffort(vendor, msg.effort || proposal.recommendedEffort || "medium") || "";
|
|
257
|
-
|
|
276
|
+
var startingPatch = { status: "starting", selectedVendor: vendor, selectedModel: model, selectedEffort: effort };
|
|
277
|
+
if (msg.autoApproved) startingPatch.autoApproved = true;
|
|
278
|
+
updateProposal(session, proposal, startingPatch);
|
|
258
279
|
try {
|
|
259
280
|
var created = ctx.createPairRecord(ws, {
|
|
260
281
|
driver: { sessionId: session.localId },
|
|
261
282
|
worker: { vendor: vendor, model: model, effort: effort },
|
|
262
283
|
});
|
|
263
284
|
updateProposal(session, proposal, { status: "running", groupId: created.group.id, workerId: created.worker.localId });
|
|
264
|
-
|
|
285
|
+
if (ws._autoApproval) sm.sendToSession(session, { type: "pair_session_created", ok: true, group: created.group });
|
|
286
|
+
else ctx.sendTo(ws, { type: "pair_session_created", ok: true, group: created.group });
|
|
265
287
|
runWorker(session, proposal).catch(function (err) {
|
|
266
288
|
updateProposal(session, proposal, { status: "error", error: err.message || String(err) });
|
|
267
289
|
resumeDriver(session, "[Worker execution failed]\n" + (err.message || String(err))).catch(function () {});
|
|
@@ -273,6 +295,19 @@ function attachWorkerProposal(ctx) {
|
|
|
273
295
|
}
|
|
274
296
|
}
|
|
275
297
|
|
|
298
|
+
async function respondToProposal(ws, msg) {
|
|
299
|
+
var session = sessionForResponse(ws);
|
|
300
|
+
var proposal = findProposal(session, msg.proposalId);
|
|
301
|
+
if (!proposal) throw new Error("Worker suggestion not found");
|
|
302
|
+
if (proposal.status !== "pending") throw new Error("Worker suggestion has already been resolved");
|
|
303
|
+
if (!msg.accepted) {
|
|
304
|
+
updateProposal(session, proposal, { status: "declined" });
|
|
305
|
+
await resumeDriver(session, "[Worker suggestion declined]\nContinue this task in the current session using the plan you already prepared.");
|
|
306
|
+
return { ok: true, status: "declined" };
|
|
307
|
+
}
|
|
308
|
+
return acceptProposal(session, proposal, msg, ws);
|
|
309
|
+
}
|
|
310
|
+
|
|
276
311
|
function handleMessage(ws, msg) {
|
|
277
312
|
if (msg.type !== "worker_proposal_response") return false;
|
|
278
313
|
respondToProposal(ws, msg).catch(function (err) {
|
package/lib/project.js
CHANGED
|
@@ -472,10 +472,9 @@ function createProjectContext(opts) {
|
|
|
472
472
|
|
|
473
473
|
var _projModel = typeof opts.onGetProjectDefaultModel === "function" ? opts.onGetProjectDefaultModel(slug) : null;
|
|
474
474
|
var _srvModel = typeof opts.onGetServerDefaultModel === "function" ? opts.onGetServerDefaultModel() : null;
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (sm._savedDefaultModel) sm.currentModel = sm._savedDefaultModel;
|
|
475
|
+
var savedDefaultModel = (_projModel && _projModel.model) || (_srvModel && _srvModel.model) || null;
|
|
476
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
477
|
+
if (savedDefaultModel) sm.defaultModelByVendor[sm.defaultVendor || "claude"] = savedDefaultModel;
|
|
479
478
|
|
|
480
479
|
// --- Local MCP (direct process management for localhost clients) ---
|
|
481
480
|
var _localMcp = createLocalMcp();
|
|
@@ -54,7 +54,7 @@ import { handleWhatsNewState, handleWhatsNewSeenResult, setKnownEntries as setWh
|
|
|
54
54
|
import { closeArticle as closeWhatsNewArticle } from './whats-new-article.js';
|
|
55
55
|
import { resolvePaneSession, resolveSwitchedVendor } from './pane-session.js';
|
|
56
56
|
import { selectDefaultVendorForBlankSession } from './vendor-selection.js';
|
|
57
|
-
import { getModelInfoUpdate, modelEntryMatches, handleModelSelectionResult } from './model-picker.js';
|
|
57
|
+
import { getModelInfoUpdate, modelEntryValue, modelEntryMatches, handleModelSelectionResult, requestVendorModels } from './model-picker.js';
|
|
58
58
|
import { getModelEffortLevels, accumulateUsage, updateUsagePanel, accumulateContext, updateContextPanel, renderCtxPopover, updateStatusPanel } from './app-panels.js';
|
|
59
59
|
import { updateProjectList, resetClientState, showUpdateAvailable, handleRemoveProjectCheckResult, handleRemoveProjectResult, handleBrowseDirResult, handleAddProjectResult, handleCloneProgress } from './app-projects.js';
|
|
60
60
|
import { updateHistorySentinel, prependOlderHistory } from './app-header.js';
|
|
@@ -449,7 +449,13 @@ export function processMessage(msg) {
|
|
|
449
449
|
var _curInList = !!_curModel && (msg.models || []).some(function (m) {
|
|
450
450
|
return modelEntryMatches(m, _curModel);
|
|
451
451
|
});
|
|
452
|
-
|
|
452
|
+
var _incomingInList = !_modelVal || (msg.models || []).length === 0 || (msg.models || []).some(function (m) {
|
|
453
|
+
return modelEntryMatches(m, _modelVal);
|
|
454
|
+
});
|
|
455
|
+
if (!_incomingInList) {
|
|
456
|
+
console.warn("[model-state] Ignoring model not listed for vendor " + (msg.vendor || store.get('currentVendor')) + ": " + _modelVal);
|
|
457
|
+
_miUpdate.currentModel = _curInList ? _curModel : modelEntryValue((msg.models || [])[0]);
|
|
458
|
+
} else if (store.get('vendorSelectionLocked') && _curInList) {
|
|
453
459
|
// Keep the user's existing (valid) selection; only update models list
|
|
454
460
|
} else {
|
|
455
461
|
_miUpdate.currentModel = _modelVal || "";
|
|
@@ -469,8 +475,20 @@ export function processMessage(msg) {
|
|
|
469
475
|
break;
|
|
470
476
|
|
|
471
477
|
case "config_state": {
|
|
478
|
+
if ((msg.sessionId != null && msg.sessionId !== store.get('activeSessionId')) || (msg.vendor && msg.vendor !== store.get('currentVendor'))) break;
|
|
472
479
|
var _cs = {};
|
|
473
|
-
if (msg.model)
|
|
480
|
+
if (msg.model) {
|
|
481
|
+
var _knownModels = store.get('currentModels') || [];
|
|
482
|
+
var _modelKnown = _knownModels.length === 0 || _knownModels.some(function(model) { return modelEntryMatches(model, msg.model); });
|
|
483
|
+
if (_modelKnown) {
|
|
484
|
+
_cs.currentModel = msg.model;
|
|
485
|
+
} else {
|
|
486
|
+
console.warn("[model-state] Ignoring model not listed for current vendor: " + msg.model);
|
|
487
|
+
var _existingModel = store.get('currentModel');
|
|
488
|
+
var _existingKnown = _knownModels.some(function(model) { return modelEntryMatches(model, _existingModel); });
|
|
489
|
+
_cs.currentModel = _existingKnown ? _existingModel : modelEntryValue(_knownModels[0]);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
474
492
|
if (msg.mode) _cs.currentMode = msg.mode;
|
|
475
493
|
if (msg.effort) _cs.currentEffort = msg.effort;
|
|
476
494
|
if (msg.betas) _cs.currentBetas = msg.betas;
|
|
@@ -681,7 +699,7 @@ export function processMessage(msg) {
|
|
|
681
699
|
var _effectiveTerminalId = (typeof msg.runtimeTerminalId === "number")
|
|
682
700
|
? msg.runtimeTerminalId
|
|
683
701
|
: (typeof msg.terminalId === "number" ? msg.terminalId : null);
|
|
684
|
-
store.set({ activeSessionId: msg.id, cliSessionId: msg.cliSessionId || null, currentModel: msg.model ||
|
|
702
|
+
store.set({ activeSessionId: msg.id, 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') });
|
|
685
703
|
// TUI sessions swap the chat UI for an embedded xterm running
|
|
686
704
|
// `claude` inside a real PTY. Mount or tear down before the rest of
|
|
687
705
|
// the chat-side bookkeeping runs so we don't waste work on hidden DOM.
|
|
@@ -728,6 +746,7 @@ export function processMessage(msg) {
|
|
|
728
746
|
if (!msg.hasHistory && !msg.vendor) {
|
|
729
747
|
selectDefaultVendorForBlankSession();
|
|
730
748
|
}
|
|
749
|
+
if (!msg.model) requestVendorModels(store.get('currentVendor') || "claude", true);
|
|
731
750
|
// Vendor toggle visibility + active-vendor indicator next to the
|
|
732
751
|
// model chip.
|
|
733
752
|
// - Session has an explicit vendor: hide the toggle (it's
|
|
@@ -112,6 +112,7 @@ export function getModelInfoUpdate(msg) {
|
|
|
112
112
|
var vendor = msg.vendor || store.get('currentVendor') || "claude";
|
|
113
113
|
var currentVendor = store.get('currentVendor');
|
|
114
114
|
if (currentVendor && vendor !== currentVendor) return null;
|
|
115
|
+
if (msg.sessionId != null && msg.sessionId !== store.get('activeSessionId')) return null;
|
|
115
116
|
|
|
116
117
|
var s = store.snap();
|
|
117
118
|
if (msg.requestId && s.modelRequestId && msg.requestId !== s.modelRequestId) return null;
|
|
@@ -103,8 +103,10 @@ function statusLabel(status) {
|
|
|
103
103
|
function applyState(card, msg) {
|
|
104
104
|
var status = msg.status || "pending";
|
|
105
105
|
card.dataset.status = status;
|
|
106
|
+
if (msg.autoApproved) card.dataset.autoApproved = "true";
|
|
107
|
+
var autoApproved = card.dataset.autoApproved === "true";
|
|
106
108
|
var badge = card.querySelector(".worker-proposal-status");
|
|
107
|
-
if (badge) badge.textContent = statusLabel(status);
|
|
109
|
+
if (badge) badge.textContent = statusLabel(status) + (autoApproved ? " · auto-approved" : "");
|
|
108
110
|
var error = card.querySelector(".worker-proposal-error");
|
|
109
111
|
if (error) {
|
|
110
112
|
error.textContent = msg.error || "";
|
|
@@ -116,6 +118,8 @@ function applyState(card, msg) {
|
|
|
116
118
|
preview.classList.remove("hidden");
|
|
117
119
|
}
|
|
118
120
|
setControlsDisabled(card, status !== "pending");
|
|
121
|
+
var actions = card.querySelector(".worker-proposal-actions");
|
|
122
|
+
if (actions) actions.classList.toggle("hidden", autoApproved);
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
function sendDecision(card, accepted) {
|
package/lib/sdk-bridge.js
CHANGED
|
@@ -245,17 +245,24 @@ function createSDKBridge(opts) {
|
|
|
245
245
|
return null;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
function
|
|
248
|
+
function defaultModelForVendor(vendor) {
|
|
249
|
+
return (sm.defaultModelByVendor && sm.defaultModelByVendor[vendor]) || "";
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function sendModelInfoForVendor(session, vendor, model) {
|
|
249
253
|
var resolvedVendor = vendor || (adapter && adapter.vendor) || "claude";
|
|
250
|
-
|
|
254
|
+
var message = {
|
|
251
255
|
type: "model_info",
|
|
252
256
|
model: model || "",
|
|
253
257
|
models: getModelsForVendor(resolvedVendor),
|
|
254
258
|
vendor: resolvedVendor,
|
|
259
|
+
sessionId: session ? session.localId : null,
|
|
255
260
|
capabilities: (sm.capabilitiesByVendor && sm.capabilitiesByVendor[resolvedVendor]) || {},
|
|
256
261
|
availableVendors: sm.availableVendors || [],
|
|
257
262
|
installedVendors: sm.installedVendors || [],
|
|
258
|
-
}
|
|
263
|
+
};
|
|
264
|
+
if (session) sendToSession(session, message);
|
|
265
|
+
else send(message);
|
|
259
266
|
}
|
|
260
267
|
|
|
261
268
|
function rememberAdapterReady(vendor, result) {
|
|
@@ -849,19 +856,20 @@ function createSDKBridge(opts) {
|
|
|
849
856
|
case "model_changed":
|
|
850
857
|
session.model = metaData.model;
|
|
851
858
|
sm.saveSessionFile(session);
|
|
852
|
-
sm.
|
|
853
|
-
|
|
854
|
-
|
|
859
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
860
|
+
sm.defaultModelByVendor[session.vendor || "claude"] = metaData.model;
|
|
861
|
+
sendModelInfoForVendor(session, session.vendor || (adapter && adapter.vendor) || "claude", metaData.model);
|
|
862
|
+
sendToSession(session, { type: "config_state", model: session.model || defaultModelForVendor(session.vendor || "claude"), vendor: session.vendor || "claude", sessionId: session.localId, mode: session.permissionMode || sm.currentPermissionMode || "default", effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
855
863
|
break;
|
|
856
864
|
case "effort_changed":
|
|
857
865
|
session.effort = metaData.effort;
|
|
858
866
|
sm.saveSessionFile(session);
|
|
859
867
|
sm.currentEffort = metaData.effort;
|
|
860
|
-
sendToSession(session, { type: "config_state", model: session.model ||
|
|
868
|
+
sendToSession(session, { type: "config_state", model: session.model || defaultModelForVendor(session.vendor || "claude"), vendor: session.vendor || "claude", sessionId: session.localId, mode: session.permissionMode || sm.currentPermissionMode || "default", effort: session.effort, betas: sm.currentBetas || [] });
|
|
861
869
|
break;
|
|
862
870
|
case "permission_mode_changed":
|
|
863
871
|
sm.currentPermissionMode = metaData.mode;
|
|
864
|
-
sendToSession(session, { type: "config_state", model: session.model ||
|
|
872
|
+
sendToSession(session, { type: "config_state", model: session.model || defaultModelForVendor(session.vendor || "claude"), vendor: session.vendor || "claude", sessionId: session.localId, mode: session.permissionMode || sm.currentPermissionMode, effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
865
873
|
break;
|
|
866
874
|
case "worker_error":
|
|
867
875
|
send({ type: "error", text: metaData.error });
|
|
@@ -1232,10 +1240,10 @@ function createSDKBridge(opts) {
|
|
|
1232
1240
|
sm.modelsByVendor[vendor] = await vendorAdapter.supportedModels();
|
|
1233
1241
|
}
|
|
1234
1242
|
var vendorModels = getModelsForVendor(vendor);
|
|
1235
|
-
var modelForVendor = resolveModelInList(vendorModels,
|
|
1243
|
+
var modelForVendor = resolveModelInList(vendorModels, defaultModelForVendor(vendor))
|
|
1236
1244
|
|| modelEntryValue(vendorModels[0])
|
|
1237
1245
|
|| "";
|
|
1238
|
-
sendModelInfoForVendor(vendor, modelForVendor);
|
|
1246
|
+
sendModelInfoForVendor(session, vendor, modelForVendor);
|
|
1239
1247
|
}
|
|
1240
1248
|
return vendorAdapter;
|
|
1241
1249
|
}
|
|
@@ -1438,14 +1446,9 @@ function createSDKBridge(opts) {
|
|
|
1438
1446
|
}
|
|
1439
1447
|
}
|
|
1440
1448
|
|
|
1441
|
-
// Pick a model
|
|
1442
|
-
//
|
|
1443
|
-
|
|
1444
|
-
// project (or in another session that switches vendor to claude) and
|
|
1445
|
-
// Claude would reject the unknown model. We validate against the
|
|
1446
|
-
// session vendor's model list regardless of which vendor happens to be
|
|
1447
|
-
// the project's default adapter.
|
|
1448
|
-
var queryModel = (ls.model && ls.model !== "default" ? ls.model : null) || session.model || sm.currentModel || undefined;
|
|
1449
|
+
// Pick a model from the session or its vendor-specific default, then
|
|
1450
|
+
// validate it against the session vendor's known model list.
|
|
1451
|
+
var queryModel = (ls.model && ls.model !== "default" ? ls.model : null) || session.model || defaultModelForVendor(session.vendor || "claude") || undefined;
|
|
1449
1452
|
var sessionVendor = session.vendor || (adapter && adapter.vendor) || null;
|
|
1450
1453
|
if (sessionVendor) {
|
|
1451
1454
|
var vendorModels = (sm.modelsByVendor && sm.modelsByVendor[sessionVendor]) || [];
|
|
@@ -1461,8 +1464,7 @@ function createSDKBridge(opts) {
|
|
|
1461
1464
|
}
|
|
1462
1465
|
|
|
1463
1466
|
// Bind the resolved model to the session so it survives a daemon
|
|
1464
|
-
// restart.
|
|
1465
|
-
// in-memory value) came back after restart on the adapter default.
|
|
1467
|
+
// restart. This preserves a session-specific selection across restarts.
|
|
1466
1468
|
if (queryModel && session.model !== queryModel) {
|
|
1467
1469
|
session.model = queryModel;
|
|
1468
1470
|
sm.saveSessionFile(session);
|
|
@@ -1874,7 +1876,7 @@ function createSDKBridge(opts) {
|
|
|
1874
1876
|
// as if every CLI were missing while the default adapter starts up.
|
|
1875
1877
|
sm.installedVendors = detectInstalledVendors(linuxUser);
|
|
1876
1878
|
sm.availableVendors = getAvailableVendors(linuxUser);
|
|
1877
|
-
sendModelInfoForVendor(defaultVendor,
|
|
1879
|
+
sendModelInfoForVendor(null, defaultVendor, defaultModelForVendor(defaultVendor));
|
|
1878
1880
|
|
|
1879
1881
|
// Initialize default adapter first (provides skills, slash commands, etc.)
|
|
1880
1882
|
if (adapter) {
|
|
@@ -1906,7 +1908,8 @@ function createSDKBridge(opts) {
|
|
|
1906
1908
|
send({ type: "slash_commands", commands: combined, vendor: defaultVendor });
|
|
1907
1909
|
}
|
|
1908
1910
|
if (result.defaultModel) {
|
|
1909
|
-
sm.
|
|
1911
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
1912
|
+
sm.defaultModelByVendor[defaultVendor] = sm.defaultModelByVendor[defaultVendor] || result.defaultModel;
|
|
1910
1913
|
}
|
|
1911
1914
|
sm.availableModels = result.models || [];
|
|
1912
1915
|
// Store per-vendor models and capabilities
|
|
@@ -1928,7 +1931,7 @@ function createSDKBridge(opts) {
|
|
|
1928
1931
|
sm.modelsByVendor = sm.modelsByVendor || {};
|
|
1929
1932
|
|
|
1930
1933
|
// Send the fully initialized state to the client.
|
|
1931
|
-
sendModelInfoForVendor(defaultVendor,
|
|
1934
|
+
sendModelInfoForVendor(null, defaultVendor, defaultModelForVendor(defaultVendor));
|
|
1932
1935
|
}
|
|
1933
1936
|
|
|
1934
1937
|
async function setModel(session, model) {
|
|
@@ -1940,22 +1943,24 @@ function createSDKBridge(opts) {
|
|
|
1940
1943
|
// No active query — just store the model for next startQuery
|
|
1941
1944
|
session.model = model;
|
|
1942
1945
|
sm.saveSessionFile(session);
|
|
1943
|
-
sm.
|
|
1946
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
1944
1947
|
// Confirm against the session vendor so a non-default vendor does not
|
|
1945
1948
|
// receive model metadata labeled as the project's default adapter.
|
|
1946
1949
|
var pendingVendor = session.vendor || (adapter && adapter.vendor) || "claude";
|
|
1947
|
-
|
|
1948
|
-
|
|
1950
|
+
sm.defaultModelByVendor[pendingVendor] = model;
|
|
1951
|
+
sendModelInfoForVendor(session, pendingVendor, model);
|
|
1952
|
+
sendToSession(session, { type: "config_state", model: model, vendor: pendingVendor, sessionId: session.localId, mode: session.permissionMode || sm.currentPermissionMode || "default", effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1949
1953
|
return { ok: true, model: model };
|
|
1950
1954
|
}
|
|
1951
1955
|
try {
|
|
1952
1956
|
await session.queryInstance.setModel(model);
|
|
1953
1957
|
session.model = model;
|
|
1954
1958
|
sm.saveSessionFile(session);
|
|
1955
|
-
sm.
|
|
1959
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
1956
1960
|
var sessionVendor = session.vendor || (adapter && adapter.vendor) || "claude";
|
|
1957
|
-
|
|
1958
|
-
|
|
1961
|
+
sm.defaultModelByVendor[sessionVendor] = model;
|
|
1962
|
+
sendModelInfoForVendor(session, sessionVendor, model);
|
|
1963
|
+
sendToSession(session, { type: "config_state", model: model, vendor: sessionVendor, sessionId: session.localId, mode: session.permissionMode || sm.currentPermissionMode || "default", effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1959
1964
|
return { ok: true, model: model };
|
|
1960
1965
|
} catch (e) {
|
|
1961
1966
|
send({ type: "error", text: "Failed to switch model: " + (e.message || e) });
|
|
@@ -1988,14 +1993,14 @@ function createSDKBridge(opts) {
|
|
|
1988
1993
|
if (!session.queryInstance) {
|
|
1989
1994
|
// No active query — just store the mode for next startQuery
|
|
1990
1995
|
sm.currentPermissionMode = mode;
|
|
1991
|
-
sendToSession(session, { type: "config_state", model: session.model ||
|
|
1996
|
+
sendToSession(session, { type: "config_state", model: session.model || defaultModelForVendor(session.vendor || "claude"), vendor: session.vendor || "claude", sessionId: session.localId, mode: sm.currentPermissionMode, effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1992
1997
|
return;
|
|
1993
1998
|
}
|
|
1994
1999
|
try {
|
|
1995
2000
|
// Route through QueryHandle (works for both in-process and worker paths)
|
|
1996
2001
|
await session.queryInstance.setPermissionMode(mode);
|
|
1997
2002
|
sm.currentPermissionMode = mode;
|
|
1998
|
-
sendToSession(session, { type: "config_state", model: session.model ||
|
|
2003
|
+
sendToSession(session, { type: "config_state", model: session.model || defaultModelForVendor(session.vendor || "claude"), vendor: session.vendor || "claude", sessionId: session.localId, mode: sm.currentPermissionMode, effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1999
2004
|
} catch (e) {
|
|
2000
2005
|
sendToSession(session, { type: "error", text: "Failed to set permission mode: " + (e.message || e) });
|
|
2001
2006
|
}
|
|
@@ -196,13 +196,20 @@ function attachMessageProcessor(ctx) {
|
|
|
196
196
|
send({ type: "slash_commands", commands: sm.slashCommands });
|
|
197
197
|
}
|
|
198
198
|
if (parsed.model) {
|
|
199
|
-
sm.currentModel = sm.currentModel || sm._savedDefaultModel || parsed.model;
|
|
200
199
|
var initVendor = session.vendor || (adapter && adapter.vendor) || "claude";
|
|
201
|
-
|
|
200
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
201
|
+
sm.defaultModelByVendor[initVendor] = sm.defaultModelByVendor[initVendor] || parsed.model;
|
|
202
|
+
var initModels = getModelsForVendor(initVendor);
|
|
203
|
+
var initModel = session.model || sm.defaultModelByVendor[initVendor] || "";
|
|
204
|
+
if (initModels.length > 0 && !initModels.some(function(entry) {
|
|
205
|
+
return entry === initModel || (entry && (entry.value === initModel || entry.id === initModel || entry.resolvedModel === initModel));
|
|
206
|
+
})) initModel = typeof initModels[0] === "string" ? initModels[0] : (initModels[0].value || initModels[0].id || "");
|
|
207
|
+
sendToSession(session, {
|
|
202
208
|
type: "model_info",
|
|
203
|
-
model:
|
|
204
|
-
models:
|
|
209
|
+
model: initModel,
|
|
210
|
+
models: initModels,
|
|
205
211
|
vendor: initVendor,
|
|
212
|
+
sessionId: session.localId,
|
|
206
213
|
availableVendors: sm.availableVendors || [],
|
|
207
214
|
installedVendors: sm.installedVendors || [],
|
|
208
215
|
});
|
package/package.json
CHANGED