fix: land #569 and restore gate (thanks @bjesuiter)

This commit is contained in:
Peter Steinberger 2026-01-09 14:03:33 +01:00
parent 71ecfb0b86
commit ce9769ab09
11 changed files with 55 additions and 50 deletions

View File

@ -46,6 +46,7 @@
- Control UI: show/patch per-session reasoning level and render extracted reasoning in chat.
- Control UI: queue outgoing chat messages, add Enter-to-send, and show queued items. (#527) — thanks @YuriNachos
- Control UI: drop explicit `ui:install` step; `ui:build` now auto-installs UI deps (docs + update flow).
- Control UI: default control UI asset base to relative paths for subpath hosting. (#569) — thanks @bjesuiter
- Telegram: retry long-polling conflicts with backoff to avoid fatal exits.
- Telegram: fix grammY fetch type mismatch when injecting `fetch`. (#512) — thanks @YuriNachos
- WhatsApp: resolve @lid JIDs via Baileys mapping to unblock inbound messages. (#415)

View File

@ -80,7 +80,7 @@ describe("Agent-specific sandbox config", () => {
expect(context).toBeDefined();
expect(context?.enabled).toBe(true);
});
}, 20000);
it("should allow agent-specific docker setupCommand overrides", async () => {
const { resolveSandboxContext } = await import("./sandbox.js");

View File

@ -179,14 +179,22 @@ async function ensureDevGatewayConfig(opts: { reset?: boolean }) {
mode: "local",
bind: "loopback",
},
agent: {
workspace,
skipBootstrap: true,
},
identity: {
name: DEV_IDENTITY_NAME,
theme: DEV_IDENTITY_THEME,
emoji: DEV_IDENTITY_EMOJI,
agents: {
defaults: {
workspace,
skipBootstrap: true,
},
list: [
{
id: "main",
default: true,
identity: {
name: DEV_IDENTITY_NAME,
theme: DEV_IDENTITY_THEME,
emoji: DEV_IDENTITY_EMOJI,
},
},
],
},
});
await ensureDevWorkspace(workspace);

View File

@ -289,7 +289,7 @@ describe("doctor", () => {
"+15555550123",
]);
expect(written.routing).toBeUndefined();
});
}, 20000);
it("migrates legacy Clawdis services", async () => {
readConfigFileSnapshot.mockResolvedValue({

View File

@ -10,12 +10,6 @@ const DEFAULT_MINIMAX_CONTEXT_WINDOW = 200000;
const DEFAULT_MINIMAX_MAX_TOKENS = 8192;
export const MINIMAX_HOSTED_MODEL_REF = `minimax/${MINIMAX_HOSTED_MODEL_ID}`;
const DEFAULT_MINIMAX_BASE_URL = "https://api.minimax.io/v1";
export const MINIMAX_HOSTED_MODEL_ID = "MiniMax-M2.1";
const DEFAULT_MINIMAX_CONTEXT_WINDOW = 200000;
const DEFAULT_MINIMAX_MAX_TOKENS = 8192;
export const MINIMAX_HOSTED_MODEL_REF = `minimax/${MINIMAX_HOSTED_MODEL_ID}`;
export async function writeOAuthCredentials(
provider: OAuthProvider,
creds: OAuthCredentials,
@ -176,7 +170,7 @@ export function applyMinimaxHostedProviderConfig(
cfg: ClawdbotConfig,
params?: { baseUrl?: string },
): ClawdbotConfig {
const models = { ...cfg.agent?.models };
const models = { ...cfg.agents?.defaults?.models };
models[MINIMAX_HOSTED_MODEL_REF] = {
...models[MINIMAX_HOSTED_MODEL_REF],
alias: models[MINIMAX_HOSTED_MODEL_REF]?.alias ?? "Minimax",
@ -212,9 +206,12 @@ export function applyMinimaxHostedProviderConfig(
return {
...cfg,
agent: {
...cfg.agent,
models,
agents: {
...cfg.agents,
defaults: {
...cfg.agents?.defaults,
models,
},
},
models: {
mode: cfg.models?.mode ?? "merge",
@ -254,17 +251,21 @@ export function applyMinimaxHostedConfig(
const next = applyMinimaxHostedProviderConfig(cfg, params);
return {
...next,
agent: {
...next.agent,
model: {
...(next.agent?.model &&
"fallbacks" in (next.agent.model as Record<string, unknown>)
? {
fallbacks: (next.agent.model as { fallbacks?: string[] })
.fallbacks,
}
: undefined),
primary: MINIMAX_HOSTED_MODEL_REF,
agents: {
...next.agents,
defaults: {
...next.agents?.defaults,
model: {
...(next.agents?.defaults?.model &&
"fallbacks" in (next.agents.defaults.model as Record<string, unknown>)
? {
fallbacks: (
next.agents.defaults.model as { fallbacks?: string[] }
).fallbacks,
}
: undefined),
primary: MINIMAX_HOSTED_MODEL_REF,
},
},
},
};

View File

@ -546,7 +546,8 @@ async function promptWhatsAppAllowFrom(
"WhatsApp number",
);
const entry = await prompter.text({
message: "Your personal WhatsApp number (the phone you will message from)",
message:
"Your personal WhatsApp number (the phone you will message from)",
placeholder: "+15555550123",
initialValue: existingAllowFrom[0],
validate: (value) => {
@ -613,7 +614,8 @@ async function promptWhatsAppAllowFrom(
"WhatsApp number",
);
const entry = await prompter.text({
message: "Your personal WhatsApp number (the phone you will message from)",
message:
"Your personal WhatsApp number (the phone you will message from)",
placeholder: "+15555550123",
initialValue: existingAllowFrom[0],
validate: (value) => {

View File

@ -1202,7 +1202,7 @@ export type AgentDefaultsConfig = {
every?: string;
/** Heartbeat model override (provider/model). */
model?: string;
/** Delivery target (last|whatsapp|telegram|discord|signal|imessage|none). */
/** Delivery target (last|whatsapp|telegram|discord|slack|signal|imessage|msteams|none). */
target?:
| "last"
| "whatsapp"
@ -1211,6 +1211,7 @@ export type AgentDefaultsConfig = {
| "slack"
| "signal"
| "imessage"
| "msteams"
| "none";
/** Optional delivery override (E.164 for WhatsApp, chat id for Telegram). */
to?: string;

View File

@ -603,6 +603,7 @@ const HeartbeatSchema = z
z.literal("slack"),
z.literal("signal"),
z.literal("imessage"),
z.literal("msteams"),
z.literal("none"),
])
.optional(),

View File

@ -56,8 +56,9 @@ export async function monitorMSTeamsProvider(
const textLimit = resolveTextChunkLimit(cfg, "msteams");
const MB = 1024 * 1024;
const mediaMaxBytes =
typeof cfg.agent?.mediaMaxMb === "number" && cfg.agent.mediaMaxMb > 0
? Math.floor(cfg.agent.mediaMaxMb * MB)
typeof cfg.agents?.defaults?.mediaMaxMb === "number" &&
cfg.agents.defaults.mediaMaxMb > 0
? Math.floor(cfg.agents.defaults.mediaMaxMb * MB)
: 8 * MB;
const conversationStore =
opts.conversationStore ?? createMSTeamsConversationStoreFs();

View File

@ -122,9 +122,7 @@ export async function sendMessageTelegram(
const client: ApiClientOptions | undefined = fetchImpl
? { fetch: fetchImpl as unknown as ApiClientOptions["fetch"] }
: undefined;
const api =
opts.api ??
new Bot(token, client ? { client } : undefined).api;
const api = opts.api ?? new Bot(token, client ? { client } : undefined).api;
const mediaUrl = opts.mediaUrl?.trim();
// Build optional params for forum topics and reply threading.
@ -296,9 +294,7 @@ export async function reactMessageTelegram(
const client: ApiClientOptions | undefined = fetchImpl
? { fetch: fetchImpl as unknown as ApiClientOptions["fetch"] }
: undefined;
const api =
opts.api ??
new Bot(token, client ? { client } : undefined).api;
const api = opts.api ?? new Bot(token, client ? { client } : undefined).api;
const request = createTelegramRetryRunner({
retry: opts.retry,
configRetry: account.config.retry,

View File

@ -11,10 +11,7 @@ export async function setTelegramWebhook(opts: {
const client: ApiClientOptions | undefined = fetchImpl
? { fetch: fetchImpl as unknown as ApiClientOptions["fetch"] }
: undefined;
const bot = new Bot(
opts.token,
client ? { client } : undefined,
);
const bot = new Bot(opts.token, client ? { client } : undefined);
await bot.api.setWebhook(opts.url, {
secret_token: opts.secret,
drop_pending_updates: opts.dropPendingUpdates ?? false,
@ -26,9 +23,6 @@ export async function deleteTelegramWebhook(opts: { token: string }) {
const client: ApiClientOptions | undefined = fetchImpl
? { fetch: fetchImpl as unknown as ApiClientOptions["fetch"] }
: undefined;
const bot = new Bot(
opts.token,
client ? { client } : undefined,
);
const bot = new Bot(opts.token, client ? { client } : undefined);
await bot.api.deleteWebhook();
}