diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c0549c16..191c2172d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,11 +68,15 @@ Status: stable. - Docs: credit both contributors for Control UI refresh. (#1852) Thanks @EnzeD. - Docs: keep docs header sticky so navbar stays visible while scrolling. (#2445) Thanks @chenyuan99. - Docs: update exe.dev install instructions. (#https://github.com/openclaw/openclaw/pull/3047) Thanks @zackerthescar. +- Build: skip redundant UI install step in the Dockerfile. (#4584) Thanks @obviyus. ### Breaking - **BREAKING:** Gateway auth mode "none" is removed; gateway now requires token/password (Tailscale Serve identity still allowed). ### Fixes +- Telegram: use undici fetch for per-account proxy dispatcher. (#4456) Thanks @spiceoogway. +- Telegram: fix HTML nesting for overlapping styles and links. (#4578) Thanks @ThanhNguyxn. - Telegram: avoid silent empty replies by tracking normalization skips before fallback. (#3796) +- Telegram: accept numeric messageId/chatId in react action and honor channelId fallback. (#4533) Thanks @Ayush10. - Telegram: scope native skill commands to bound agent per bot. (#4360) Thanks @robhparker. - Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R. - Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald. diff --git a/Dockerfile b/Dockerfile index 904d1d97d..ad08bd37c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,6 @@ COPY . . RUN OPENCLAW_A2UI_SKIP_MISSING=1 pnpm build # Force pnpm for UI build (Bun may fail on ARM/Synology architectures) ENV OPENCLAW_PREFER_PNPM=1 -RUN pnpm ui:install RUN pnpm ui:build ENV NODE_ENV=production diff --git a/README.md b/README.md index 1fd5e074c..49085c76f 100644 --- a/README.md +++ b/README.md @@ -481,38 +481,39 @@ Thanks to all clawtributors:
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
const x = 1;\n");
});
+
+ it("properly nests overlapping bold and autolink (#4071)", () => {
+ const res = markdownToTelegramHtml("**start https://example.com** end");
+ expect(res).toMatch(
+ /start https:\/\/example\.com<\/a><\/b> end/,
+ );
+ });
+
+ it("properly nests link inside bold", () => {
+ const res = markdownToTelegramHtml("**bold [link](https://example.com) text**");
+ expect(res).toBe('bold link text');
+ });
+
+ it("properly nests bold wrapping a link with trailing text", () => {
+ const res = markdownToTelegramHtml("**[link](https://example.com) rest**");
+ expect(res).toBe('link rest');
+ });
+
+ it("properly nests bold inside a link", () => {
+ const res = markdownToTelegramHtml("[**bold**](https://example.com)");
+ expect(res).toBe('bold');
+ });
});
diff --git a/src/telegram/proxy.test.ts b/src/telegram/proxy.test.ts
new file mode 100644
index 000000000..71fd5f88e
--- /dev/null
+++ b/src/telegram/proxy.test.ts
@@ -0,0 +1,45 @@
+import { describe, expect, it, vi } from "vitest";
+
+const { ProxyAgent, undiciFetch, proxyAgentSpy, getLastAgent } = vi.hoisted(() => {
+ const undiciFetch = vi.fn();
+ const proxyAgentSpy = vi.fn();
+ class ProxyAgent {
+ static lastCreated: ProxyAgent | undefined;
+ proxyUrl: string;
+ constructor(proxyUrl: string) {
+ this.proxyUrl = proxyUrl;
+ ProxyAgent.lastCreated = this;
+ proxyAgentSpy(proxyUrl);
+ }
+ }
+
+ return {
+ ProxyAgent,
+ undiciFetch,
+ proxyAgentSpy,
+ getLastAgent: () => ProxyAgent.lastCreated,
+ };
+});
+
+vi.mock("undici", () => ({
+ ProxyAgent,
+ fetch: undiciFetch,
+}));
+
+import { makeProxyFetch } from "./proxy.js";
+
+describe("makeProxyFetch", () => {
+ it("uses undici fetch with ProxyAgent dispatcher", async () => {
+ const proxyUrl = "http://proxy.test:8080";
+ undiciFetch.mockResolvedValue({ ok: true });
+
+ const proxyFetch = makeProxyFetch(proxyUrl);
+ await proxyFetch("https://api.telegram.org/bot123/getMe");
+
+ expect(proxyAgentSpy).toHaveBeenCalledWith(proxyUrl);
+ expect(undiciFetch).toHaveBeenCalledWith(
+ "https://api.telegram.org/bot123/getMe",
+ expect.objectContaining({ dispatcher: getLastAgent() }),
+ );
+ });
+});
diff --git a/src/telegram/proxy.ts b/src/telegram/proxy.ts
index 19d53d569..84251d7fe 100644
--- a/src/telegram/proxy.ts
+++ b/src/telegram/proxy.ts
@@ -1,11 +1,11 @@
// @ts-nocheck
-import { ProxyAgent } from "undici";
+import { ProxyAgent, fetch as undiciFetch } from "undici";
import { wrapFetchWithAbortSignal } from "../infra/fetch.js";
export function makeProxyFetch(proxyUrl: string): typeof fetch {
const agent = new ProxyAgent(proxyUrl);
return wrapFetchWithAbortSignal((input: RequestInfo | URL, init?: RequestInit) => {
const base = init ? { ...init } : {};
- return fetch(input, { ...base, dispatcher: agent });
+ return undiciFetch(input, { ...base, dispatcher: agent });
});
}