switchroom 0.16.13 → 0.16.14
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/dist/cli/switchroom.js +2 -2
- package/dist/host-control/main.js +1 -1
- package/package.json +1 -1
- package/telegram-plugin/dist/gateway/gateway.js +12 -6
- package/telegram-plugin/gateway/gateway.ts +24 -3
- package/telegram-plugin/gateway/model-command.ts +1 -1
- package/telegram-plugin/uat/scenarios/jtbd-model-litellm-sr-dm.test.ts +3 -3
package/dist/cli/switchroom.js
CHANGED
|
@@ -51674,8 +51674,8 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
51674
51674
|
import { dirname, join } from "node:path";
|
|
51675
51675
|
|
|
51676
51676
|
// src/build-info.ts
|
|
51677
|
-
var VERSION = "0.16.
|
|
51678
|
-
var COMMIT_SHA = "
|
|
51677
|
+
var VERSION = "0.16.14";
|
|
51678
|
+
var COMMIT_SHA = "6daa5e37";
|
|
51679
51679
|
|
|
51680
51680
|
// src/cli/resolve-version.ts
|
|
51681
51681
|
function readPackageVersion() {
|
|
@@ -22587,7 +22587,7 @@ import { existsSync as existsSync6, readFileSync as readFileSync4 } from "node:f
|
|
|
22587
22587
|
import { dirname as dirname4, join as join2 } from "node:path";
|
|
22588
22588
|
|
|
22589
22589
|
// src/build-info.ts
|
|
22590
|
-
var VERSION = "0.16.
|
|
22590
|
+
var VERSION = "0.16.14";
|
|
22591
22591
|
|
|
22592
22592
|
// src/cli/resolve-version.ts
|
|
22593
22593
|
function readPackageVersion() {
|
package/package.json
CHANGED
|
@@ -56064,11 +56064,11 @@ function readTurnActiveMarkerAgeMs(stateDir, now) {
|
|
|
56064
56064
|
}
|
|
56065
56065
|
|
|
56066
56066
|
// ../src/build-info.ts
|
|
56067
|
-
var VERSION = "0.16.
|
|
56068
|
-
var COMMIT_SHA = "
|
|
56069
|
-
var COMMIT_DATE = "2026-06-
|
|
56070
|
-
var LATEST_PR =
|
|
56071
|
-
var COMMITS_AHEAD_OF_TAG =
|
|
56067
|
+
var VERSION = "0.16.14";
|
|
56068
|
+
var COMMIT_SHA = "6daa5e37";
|
|
56069
|
+
var COMMIT_DATE = "2026-06-28T19:14:51Z";
|
|
56070
|
+
var LATEST_PR = 2639;
|
|
56071
|
+
var COMMITS_AHEAD_OF_TAG = 0;
|
|
56072
56072
|
|
|
56073
56073
|
// gateway/boot-version.ts
|
|
56074
56074
|
function formatRelativeAgo(iso) {
|
|
@@ -68285,13 +68285,19 @@ bot.on("callback_query:data", async (ctx) => {
|
|
|
68285
68285
|
return;
|
|
68286
68286
|
}
|
|
68287
68287
|
await ctx.answerCallbackQuery({ text: "Switching\u2026" }).catch(() => {});
|
|
68288
|
+
let didInterimSrEdit = false;
|
|
68289
|
+
if (data.startsWith(MODEL_CALLBACK_SR)) {
|
|
68290
|
+
const srLabel = escapeHtmlForTg(srFriendlyLabel(data.slice(MODEL_CALLBACK_SR.length)));
|
|
68291
|
+
await ctx.editMessageText(`\u23F3 Switching session to <b>${srLabel}</b>\u2026`, { parse_mode: "HTML", reply_markup: { inline_keyboard: [] } }).catch(() => {});
|
|
68292
|
+
didInterimSrEdit = true;
|
|
68293
|
+
}
|
|
68288
68294
|
try {
|
|
68289
68295
|
const prevSessionModel = activeSessionModelOverride;
|
|
68290
68296
|
const outcome = await handleModelMenuCallback(data, modelDeps);
|
|
68291
68297
|
if (outcome.selectedModel) {
|
|
68292
68298
|
activeSessionModelOverride = outcome.selectedModel;
|
|
68293
68299
|
}
|
|
68294
|
-
if (outcome.toastOnly)
|
|
68300
|
+
if (outcome.toastOnly && !didInterimSrEdit)
|
|
68295
68301
|
return;
|
|
68296
68302
|
if (outcome.selectedModel && isSrToClaudeTransition(prevSessionModel, outcome.selectedModel)) {
|
|
68297
68303
|
const agentName3 = getMyAgentName();
|
|
@@ -278,6 +278,8 @@ import {
|
|
|
278
278
|
isSrToClaudeTransition,
|
|
279
279
|
MODEL_CALLBACK_PREFIX,
|
|
280
280
|
MODEL_CALLBACK_HEADER,
|
|
281
|
+
MODEL_CALLBACK_SR,
|
|
282
|
+
srFriendlyLabel,
|
|
281
283
|
type ModelMenuDeps,
|
|
282
284
|
type ModelCommandDeps,
|
|
283
285
|
type ModelMenuReply,
|
|
@@ -20849,6 +20851,23 @@ bot.on('callback_query:data', async ctx => {
|
|
|
20849
20851
|
return
|
|
20850
20852
|
}
|
|
20851
20853
|
await ctx.answerCallbackQuery({ text: 'Switching…' }).catch(() => {})
|
|
20854
|
+
// sr-* inject waits for claude to respond (can take 10-30s). Edit the
|
|
20855
|
+
// menu immediately to show a "working on it" state so the operator isn't
|
|
20856
|
+
// left looking at a stale menu with no feedback. The final edit (✅/❌)
|
|
20857
|
+
// replaces this once the inject returns.
|
|
20858
|
+
// NOTE: this await yields the event loop, so a new inbound turn could
|
|
20859
|
+
// start between here and handleModelMenuCallback's inner isBusy() check.
|
|
20860
|
+
// We track whether we applied the interim edit so we can skip the
|
|
20861
|
+
// toastOnly short-circuit if we did — a toastOnly return after the interim
|
|
20862
|
+
// edit would leave the menu stuck button-less.
|
|
20863
|
+
let didInterimSrEdit = false
|
|
20864
|
+
if (data.startsWith(MODEL_CALLBACK_SR)) {
|
|
20865
|
+
const srLabel = escapeHtmlForTg(srFriendlyLabel(data.slice(MODEL_CALLBACK_SR.length)))
|
|
20866
|
+
await ctx
|
|
20867
|
+
.editMessageText(`⏳ Switching session to <b>${srLabel}</b>…`, { parse_mode: 'HTML', reply_markup: { inline_keyboard: [] } })
|
|
20868
|
+
.catch(() => {})
|
|
20869
|
+
didInterimSrEdit = true
|
|
20870
|
+
}
|
|
20852
20871
|
try {
|
|
20853
20872
|
const prevSessionModel = activeSessionModelOverride
|
|
20854
20873
|
const outcome = await handleModelMenuCallback(data, modelDeps)
|
|
@@ -20858,9 +20877,11 @@ bot.on('callback_query:data', async ctx => {
|
|
|
20858
20877
|
if (outcome.selectedModel) {
|
|
20859
20878
|
activeSessionModelOverride = outcome.selectedModel
|
|
20860
20879
|
}
|
|
20861
|
-
// toastOnly:
|
|
20862
|
-
//
|
|
20863
|
-
|
|
20880
|
+
// toastOnly: leave the menu untouched — but only if we haven't already
|
|
20881
|
+
// cleared its buttons with the interim sr-* edit. If we have, fall
|
|
20882
|
+
// through to the final edit so the message is recovered (busyReply or
|
|
20883
|
+
// the full menu) rather than left permanently button-less.
|
|
20884
|
+
if (outcome.toastOnly && !didInterimSrEdit) return
|
|
20864
20885
|
|
|
20865
20886
|
// sr-* → Claude transition via the model menu: trigger a graceful restart.
|
|
20866
20887
|
// Switching FROM an sr-* (LiteLLM/OpenRouter) model BACK to a Claude model
|
|
@@ -345,7 +345,7 @@ export function expandSrAlias(arg: string): string {
|
|
|
345
345
|
return SR_MODEL_ALIASES[arg.toLowerCase()] ?? arg
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
function srFriendlyLabel(srName: string): string {
|
|
348
|
+
export function srFriendlyLabel(srName: string): string {
|
|
349
349
|
return SR_MODEL_LABELS[srName] ?? srName.replace(/^sr-/, '').replace(/-/g, ' ')
|
|
350
350
|
}
|
|
351
351
|
|
|
@@ -140,11 +140,11 @@ describe("uat: /model sr-* LiteLLM routing — section headers + session switch
|
|
|
140
140
|
const sc = await spinUp({ agent: AGENT });
|
|
141
141
|
try {
|
|
142
142
|
await sc.sendDM("/model");
|
|
143
|
-
//
|
|
144
|
-
//
|
|
143
|
+
// 90s — test 2 runs after test 1's restore restart. The model-switch
|
|
144
|
+
// restart can take 30–60s to fully boot; 90s gives comfortable margin.
|
|
145
145
|
const menu = await sc.expectMessage(/Default \(new sessions\):/i, {
|
|
146
146
|
from: "bot",
|
|
147
|
-
timeout:
|
|
147
|
+
timeout: 90_000,
|
|
148
148
|
});
|
|
149
149
|
const kb = await sc.driver.getKeyboard(sc.botUserId, menu.messageId);
|
|
150
150
|
const flat = (kb ?? []).flat();
|