mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 03:45:46 -06:00
fix: repair main CI regressions
This commit is contained in:
@@ -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 };
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user