fix: repair main CI regressions

This commit is contained in:
Shakker
2026-07-15 04:03:54 +01:00
parent acbe29c411
commit 2c95bd2387
12 changed files with 52 additions and 37 deletions
+1
View File
@@ -40,6 +40,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- **Mattermost progress command details:** accept the documented `streaming.preview.commandText` and `streaming.progress.commandText` modes in channel config validation and bundled metadata. Thanks @shakkernerd.
- **Control UI chat transcripts:** preserve loaded history across session and pane returns, bound automatic backscroll loading, virtualize long transcripts, and keep prepends, streaming, and responsive layouts from flickering or jumping. Thanks @shakkernerd.
- **Codex dynamic tool outcomes:** use the shared tool-result failure contract for arbitrary lifecycle metadata, preventing successful Skill Workshop results from being displayed and persisted as failed calls. Fixes #107684. Thanks @shakkernerd.
- **Nested resource ignores:** honor slash-free patterns and escaped literal exclamation marks in nested ignore files during skill and resource discovery. Thanks @moguangyu5-design.
@@ -87,11 +87,13 @@ const MattermostStreamingProgressSchema = z
maxLines: z.number().int().positive().optional(),
maxLineChars: z.number().int().positive().optional(),
toolProgress: z.boolean().optional(),
commandText: z.enum(["raw", "status"]).optional(),
})
.strict();
const MattermostStreamingPreviewSchema = z
.object({
toolProgress: z.boolean().optional(),
commandText: z.enum(["raw", "status"]).optional(),
})
.strict();
const MattermostStreamingBlockSchema = z
@@ -64,7 +64,9 @@ describe("MattermostConfigSchema", () => {
label: "Shelling",
maxLines: 4,
toolProgress: false,
commandText: "status",
},
preview: { commandText: "raw" },
},
accounts: {
quiet: {
@@ -67,17 +67,17 @@ export function createEmbeddedRunFailoverRetryController(input: {
get consecutiveSameModelRateLimitRetries() {
return consecutiveSameModelRateLimitRetries;
},
resetSameModelRateLimitRetries() {
resetSameModelRateLimitRetries: () => {
consecutiveSameModelRateLimitRetries = resolveNextSameModelRateLimitRetryCount({
retriesSoFar: consecutiveSameModelRateLimitRetries,
retriedSameModelRateLimit: false,
});
},
maybeEscalateRateLimitProfileFallback(paramsLocal: {
maybeEscalateRateLimitProfileFallback: (paramsLocal: {
failoverProvider: string;
failoverModel: string;
logFallbackDecision: (decision: "fallback_model", extra?: { status?: number }) => void;
}) {
}) => {
rateLimitProfileRotations += 1;
if (rateLimitProfileRotations <= rateLimitProfileRotationLimit || !fallbackConfigured) {
return;
@@ -100,11 +100,11 @@ export function createEmbeddedRunFailoverRetryController(input: {
},
);
},
async maybeMarkAuthProfileFailure(failure: {
maybeMarkAuthProfileFailure: async (failure: {
profileId?: string;
reason?: AuthProfileFailureReason | null;
modelId?: string;
}) {
}) => {
if (params.authProfileStateMode === "read-only") {
return;
}
@@ -125,10 +125,10 @@ export function createEmbeddedRunFailoverRetryController(input: {
modelId: failure.modelId,
});
},
resolveAuthProfileFailureReason(
resolveAuthProfileFailureReason: (
failoverReason: FailoverReason | null,
opts?: { providerStarted?: boolean; transientRateLimit?: boolean },
) {
) => {
return resolveAuthProfileFailureReason({
failoverReason,
providerStarted: opts?.providerStarted,
@@ -136,7 +136,7 @@ export function createEmbeddedRunFailoverRetryController(input: {
policy: params.authProfileFailurePolicy,
});
},
async maybeBackoffBeforeOverloadFailover(reason: FailoverReason | null) {
maybeBackoffBeforeOverloadFailover: async (reason: FailoverReason | null) => {
if (reason !== "overloaded" || overloadFailoverBackoffMs <= 0) {
return;
}
@@ -145,7 +145,9 @@ export function createEmbeddedRunFailoverRetryController(input: {
);
await sleepForRetry(overloadFailoverBackoffMs);
},
async maybeRetrySameModelRateLimit(retry?: { retryAfterSeconds?: number }): Promise<boolean> {
maybeRetrySameModelRateLimit: async (retry?: {
retryAfterSeconds?: number;
}): Promise<boolean> => {
if (consecutiveSameModelRateLimitRetries >= MAX_SAME_MODEL_RATE_LIMIT_RETRIES) {
return false;
}
@@ -73,7 +73,7 @@ type AttemptControl = {
noteLaneTaskProgress: () => void;
onToolOutcome: ToolOutcomeObserver;
allocateToolOutcomeOrdinal: (toolCallId?: string) => number;
onToolStreamBoundary: () => void;
onToolStreamBoundary: NonNullable<EmbeddedRunAttemptParams["onToolStreamBoundary"]>;
onRunProgress: NonNullable<EmbeddedRunAttemptParams["onRunProgress"]>;
onToolResult: NonNullable<EmbeddedRunAttemptParams["onToolResult"]>;
onAgentEvent: NonNullable<EmbeddedRunAttemptParams["onAgentEvent"]>;
@@ -144,7 +144,7 @@ export function createEmbeddedRunSessionPromptState(input: {
activateInternalPrompt(MID_TURN_PRECHECK_CONTINUATION_PROMPT, true),
onUserMessagePersisted,
waitForCurrentUserMessagePersistence,
async prepareCompactedTranscriptRetry() {
prepareCompactedTranscriptRetry: async () => {
await waitForCurrentUserMessagePersistence();
if (activePrompt.internal) {
suppressNextUserMessagePersistence = activePrompt.persisted;
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
export type ChatHistoryPagination =
| { hasMore: false; totalMessages?: number; completeSnapshot?: true }
| { hasMore: true; nextOffset: number; totalMessages?: number };
+1 -4
View File
@@ -43,6 +43,7 @@ import {
resolveUiSelectedSessionAgentId,
} from "../../lib/sessions/session-key.ts";
import { normalizeLowercaseStringOrEmpty } from "../../lib/string-coerce.ts";
import type { ChatHistoryPagination } from "./chat-history-pagination.ts";
import {
isRetryableStartupUnavailable,
isUnknownGatewayMethodError,
@@ -377,10 +378,6 @@ export type ChatHistoryResult = {
metadata?: ChatMetadataResult;
};
export type ChatHistoryPagination =
| { hasMore: false; totalMessages?: number; completeSnapshot?: true }
| { hasMore: true; nextOffset: number; totalMessages?: number };
export function resolveChatHistoryPagination(
result: ChatHistoryResult | undefined,
): ChatHistoryPagination {
+10 -2
View File
@@ -748,11 +748,19 @@ describe("chat pane catalog session lifecycle", () => {
pane.hasOlderMessages = vi.fn(() => true);
pane.loadOlderMessages = vi.fn(async () => undefined);
vi.stubGlobal("IntersectionObserver", undefined);
class TestTouchEvent extends Event {
readonly touches: Array<{ clientY: number }>;
constructor(type: string, clientY: number) {
super(type);
this.touches = [{ clientY }];
}
}
vi.stubGlobal("TouchEvent", TestTouchEvent);
const thread = document.createElement("div");
const touchEvent = (type: string, clientY: number) => {
const event = new TouchEvent(type);
const event = new TestTouchEvent(type, clientY);
Object.defineProperty(event, "currentTarget", { value: thread });
Object.defineProperty(event, "touches", { value: [{ clientY }] });
return event;
};
+1 -1
View File
@@ -63,6 +63,7 @@ import { OpenClawLightDomElement } from "../../lit/openclaw-element.ts";
import { PollController } from "../../lit/poll-controller.ts";
import { catalogMessageId } from "./catalog-message-id.ts";
import { refreshChatAvatar } from "./chat-avatar.ts";
import type { ChatHistoryPagination } from "./chat-history-pagination.ts";
import {
applyChatAgentsList,
clearChatHistory,
@@ -70,7 +71,6 @@ import {
loadOlderChatHistoryPage,
resolveChatHistoryPagination,
syncSelectedSessionMessageSubscription,
type ChatHistoryPagination,
} from "./chat-history.ts";
import { dismissChatError, resolveAssistantAttachmentAuthToken } from "./chat-pane-state.ts";
import { markQueuedChatSendsWaitingForReconnect } from "./chat-queue.ts";
+1 -1
View File
@@ -10,7 +10,7 @@ import {
type UiSessionDefaultsHost,
} from "../../lib/sessions/session-key.ts";
import { normalizeLowercaseStringOrEmpty } from "../../lib/string-coerce.ts";
import type { ChatHistoryPagination } from "./chat-history.ts";
import type { ChatHistoryPagination } from "./chat-history-pagination.ts";
import { readTranscriptSequence } from "./history-merge.ts";
import { getSessionCacheValue, setSessionCacheValue } from "./session-cache.ts";