mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-14 03:26:08 +00:00
refactor(auto-reply): trim internal export surface (#106409)
* refactor(auto-reply): trim internal export surface * chore(deadcode): update auto-reply export baseline
This commit is contained in:
committed by
GitHub
parent
7cc40d9e46
commit
b76a7f453b
@@ -1254,22 +1254,16 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"src/auto-reply/command-detection.runtime-types.ts: IsControlCommandMessage",
|
||||
"src/auto-reply/command-detection.runtime-types.ts: ShouldComputeCommandAuthorized",
|
||||
"src/auto-reply/commands-registry.runtime-types.ts: ShouldHandleTextCommands",
|
||||
"src/auto-reply/reply-payload.ts: buildPairingQrReplyChannelData",
|
||||
"src/auto-reply/reply/abort.ts: getAbortMemory",
|
||||
"src/auto-reply/reply/abort.ts: getAbortMemorySizeForTest",
|
||||
"src/auto-reply/reply/abort.ts: resetAbortMemoryForTest",
|
||||
"src/auto-reply/reply/abort.ts: testing",
|
||||
"src/auto-reply/reply/acp-reset-target.ts: testing",
|
||||
"src/auto-reply/reply/agent-runner-cli-dispatch.ts: ReasoningProgressPayload",
|
||||
"src/auto-reply/reply/agent-runner-cli-dispatch.ts: ReasoningTextPayload",
|
||||
"src/auto-reply/reply/agent-runner-execution.ts: AgentRunLoopResult",
|
||||
"src/auto-reply/reply/agent-runner-execution.ts: buildContextOverflowRecoveryText",
|
||||
"src/auto-reply/reply/agent-runner-execution.ts: computeContextAwareReserveTokensFloor",
|
||||
"src/auto-reply/reply/agent-runner-execution.ts: MAX_LIVE_SWITCH_RETRIES",
|
||||
"src/auto-reply/reply/agent-runner-memory.ts: setAgentRunnerMemoryTestDeps",
|
||||
"src/auto-reply/reply/agent-runner-session-reset.ts: setAgentRunnerSessionResetTestDeps",
|
||||
"src/auto-reply/reply/agent-runner-utils.ts: buildEmbeddedRunBaseParams",
|
||||
"src/auto-reply/reply/agent-runner-utils.ts: resolveProviderScopedAuthProfile",
|
||||
"src/auto-reply/reply/block-reply-pipeline.ts: createBlockReplyPayloadKey",
|
||||
"src/auto-reply/reply/commands-diagnostics.ts: createDiagnosticsCommandHandler",
|
||||
"src/auto-reply/reply/commands-login.ts: testing",
|
||||
@@ -1277,7 +1271,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"src/auto-reply/reply/commands-name.ts: parseNameCommand",
|
||||
"src/auto-reply/reply/commands-setunset.ts: parseSetUnsetCommand",
|
||||
"src/auto-reply/reply/commands-setunset.ts: parseSetUnsetCommandAction",
|
||||
"src/auto-reply/reply/commands-subagents/shared.ts: COMMAND",
|
||||
"src/auto-reply/reply/commands-tasks.ts: buildTasksReply",
|
||||
"src/auto-reply/reply/completion-delivery-policy.ts: resolveCompletionChatType",
|
||||
"src/auto-reply/reply/delivery-hints.ts: MESSAGE_TOOL_ONLY_DELIVERY_HINT",
|
||||
@@ -1286,8 +1279,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"src/auto-reply/reply/dispatch-from-config.ts: testing",
|
||||
"src/auto-reply/reply/dispatch-from-config.types.ts: DispatchReplyFromConfig",
|
||||
"src/auto-reply/reply/dispatcher-registry.ts: clearAllDispatchers",
|
||||
"src/auto-reply/reply/effective-reply-route.ts: EffectiveReplyRouteContext",
|
||||
"src/auto-reply/reply/effective-reply-route.ts: EffectiveReplyRouteEntry",
|
||||
"src/auto-reply/reply/get-reply-directives-apply.ts: formatModelOverrideResetEvent",
|
||||
"src/auto-reply/reply/get-reply-fast-path.ts: markCompleteReplyConfig",
|
||||
"src/auto-reply/reply/get-reply-fast-path.ts: withFastReplyConfig",
|
||||
@@ -1296,23 +1287,15 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"src/auto-reply/reply/get-reply-run.ts: resolvePromptSilentReplyConversationType",
|
||||
"src/auto-reply/reply/history.ts: appendHistoryEntry",
|
||||
"src/auto-reply/reply/inbound-dedupe.ts: buildInboundDedupeKey",
|
||||
"src/auto-reply/reply/inbound-dedupe.ts: InboundDedupeClaimResult",
|
||||
"src/auto-reply/reply/mentions.types.ts: BuildMentionRegexes",
|
||||
"src/auto-reply/reply/mentions.types.ts: MatchesMentionPatterns",
|
||||
"src/auto-reply/reply/mentions.types.ts: MatchesMentionWithExplicit",
|
||||
"src/auto-reply/reply/progress-narrator.ts: createProgressNarrator",
|
||||
"src/auto-reply/reply/progress-narrator.ts: ProgressNarrationInput",
|
||||
"src/auto-reply/reply/prompt-prelude.ts: buildReplyPromptBodies",
|
||||
"src/auto-reply/reply/provider-request-error-classifier.ts: PROVIDER_AUTHENTICATION_ERROR_USER_MESSAGE",
|
||||
"src/auto-reply/reply/provider-request-error-classifier.ts: PROVIDER_INTERNAL_ERROR_USER_MESSAGE",
|
||||
"src/auto-reply/reply/provider-request-error-classifier.ts: PROVIDER_MODEL_UNAVAILABLE_USER_MESSAGE",
|
||||
"src/auto-reply/reply/provider-request-error-classifier.ts: PROVIDER_RATE_LIMIT_OR_QUOTA_ERROR_USER_MESSAGE",
|
||||
"src/auto-reply/reply/queue.ts: resetRecentQueuedMessageIdDedupe",
|
||||
"src/auto-reply/reply/queue/cleanup.ts: testing",
|
||||
"src/auto-reply/reply/queue/drain.ts: resolveFollowupAuthorizationKey",
|
||||
"src/auto-reply/reply/queue/enqueue.ts: resetRecentQueuedMessageIdDedupe",
|
||||
"src/auto-reply/reply/reply-dispatcher.runtime-types.ts: CreateReplyDispatcherWithTyping",
|
||||
"src/auto-reply/reply/reply-operation-run-state.ts: ReplyOptionsWithOperationRunState",
|
||||
"src/auto-reply/reply/reply-payloads-dedupe.ts: getMatchingMessagingToolReplyTargets",
|
||||
"src/auto-reply/reply/reply-run-registry.ts: __testing",
|
||||
"src/auto-reply/reply/reply-run-registry.ts: testing",
|
||||
@@ -1320,13 +1303,10 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"src/auto-reply/reply/reply-threading.ts: resolveConfiguredReplyToMode",
|
||||
"src/auto-reply/reply/reply-threading.ts: resolveReplyToModeWithThreading",
|
||||
"src/auto-reply/reply/reply-usage-state.ts: clearReplyUsageStateForTest",
|
||||
"src/auto-reply/reply/session-fork.ts: ForkSessionEntryFromParentParams",
|
||||
"src/auto-reply/reply/session-fork.ts: ForkSessionEntryFromParentResult",
|
||||
"src/auto-reply/reply/session-reset-prompt.ts: buildBareSessionResetPrompt",
|
||||
"src/auto-reply/reply/stage-sandbox-media.ts: appendScpStderrTail",
|
||||
"src/auto-reply/reply/stage-sandbox-media.ts: SCP_STDERR_TAIL_CHARS",
|
||||
"src/auto-reply/reply/stage-sandbox-media.ts: testing",
|
||||
"src/auto-reply/reply/stranded-reply-recovery.ts: STRANDED_REPLY_RETRY_MARKER",
|
||||
"src/auto-reply/usage-bar/template.ts: clearUsageBarTemplateCacheForTest",
|
||||
"src/cli/channel-options.ts: testing",
|
||||
"src/cli/command-path-policy.ts: resolveCliCatalogCommandPath",
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
// Reply payload tests cover internal reply metadata contracts.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildPairingQrReplyChannelData, readPairingQrReplyChannelData } from "./reply-payload.js";
|
||||
import { readPairingQrReplyChannelData } from "./reply-payload.js";
|
||||
|
||||
describe("pairing QR reply channel data", () => {
|
||||
it("builds and reads the private pairing QR payload metadata", () => {
|
||||
const channelData = buildPairingQrReplyChannelData({
|
||||
setupCode: "setup-code",
|
||||
expiresAtMs: 1_800_000_000_000,
|
||||
});
|
||||
it("reads the private pairing QR payload metadata", () => {
|
||||
const channelData = {
|
||||
openclawPairingQr: {
|
||||
setupCode: "setup-code",
|
||||
expiresAtMs: 1_800_000_000_000,
|
||||
},
|
||||
};
|
||||
|
||||
expect(readPairingQrReplyChannelData({ channelData })).toEqual({
|
||||
setupCode: "setup-code",
|
||||
|
||||
@@ -86,17 +86,6 @@ function normalizePairingQrExpiresAtMs(value: unknown): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
|
||||
}
|
||||
|
||||
export function buildPairingQrReplyChannelData(
|
||||
params: PairingQrReplyChannelData,
|
||||
): Record<string, unknown> {
|
||||
return {
|
||||
[PAIRING_QR_REPLY_CHANNEL_DATA_KEY]: {
|
||||
setupCode: params.setupCode,
|
||||
expiresAtMs: params.expiresAtMs,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function readPairingQrReplyChannelData(
|
||||
payload: Pick<ReplyPayload, "channelData">,
|
||||
): PairingQrReplyChannelData | undefined {
|
||||
|
||||
@@ -9,16 +9,20 @@ import {
|
||||
onAgentEvent,
|
||||
resetAgentEventsForTest,
|
||||
} from "../../infra/agent-events.js";
|
||||
import type {
|
||||
ReasoningProgressPayload,
|
||||
ReasoningTextPayload,
|
||||
} from "./agent-runner-cli-dispatch.js";
|
||||
import {
|
||||
createCliToolSummaryTracker,
|
||||
keepCliSessionBindingOnlyWhenReused,
|
||||
runCliAgentWithLifecycle,
|
||||
} from "./agent-runner-cli-dispatch.js";
|
||||
|
||||
type RunCliAgentWithLifecycleParams = Parameters<typeof runCliAgentWithLifecycle>[0];
|
||||
type ReasoningTextPayload = Parameters<
|
||||
NonNullable<RunCliAgentWithLifecycleParams["onReasoningText"]>
|
||||
>[0];
|
||||
type ReasoningProgressPayload = Parameters<
|
||||
NonNullable<RunCliAgentWithLifecycleParams["onReasoningProgress"]>
|
||||
>[0];
|
||||
|
||||
const cliDispatchState = vi.hoisted(() => ({
|
||||
runCliAgentMock: vi.fn(),
|
||||
}));
|
||||
|
||||
@@ -147,12 +147,12 @@ function createAssistantTextBridge(params: {
|
||||
});
|
||||
}
|
||||
|
||||
export type ReasoningTextPayload = {
|
||||
type ReasoningTextPayload = {
|
||||
text: string;
|
||||
isReasoningSnapshot?: boolean;
|
||||
};
|
||||
|
||||
export type ReasoningProgressPayload = {
|
||||
type ReasoningProgressPayload = {
|
||||
progressTokens: number;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { OAuthRefreshFailureError } from "../../agents/auth-profiles/oauth-refresh-failure.js";
|
||||
import { testing as cliBackendsTesting } from "../../agents/cli-backends.js";
|
||||
import { formatBillingErrorMessage } from "../../agents/embedded-agent-helpers.js";
|
||||
import { AUTH_INVALID_TOKEN_USER_TEXT } from "../../agents/embedded-agent-helpers/errors.js";
|
||||
import { FailoverError } from "../../agents/failover-error.js";
|
||||
import { LiveSessionModelSwitchError } from "../../agents/live-model-switch-error.js";
|
||||
import { MissingProviderAuthError } from "../../agents/model-auth.js";
|
||||
@@ -35,16 +36,17 @@ import {
|
||||
resolveRunAfterAutoFallbackPrimaryProbeRecheck,
|
||||
} from "./agent-runner-execution.js";
|
||||
import { HEARTBEAT_EXTERNAL_RUN_FAILURE_TEXT } from "./agent-runner-failure-copy.js";
|
||||
import {
|
||||
PROVIDER_AUTHENTICATION_ERROR_USER_MESSAGE,
|
||||
PROVIDER_CONVERSATION_STATE_ERROR_USER_MESSAGE,
|
||||
PROVIDER_INTERNAL_ERROR_USER_MESSAGE,
|
||||
PROVIDER_RATE_LIMIT_OR_QUOTA_ERROR_USER_MESSAGE,
|
||||
} from "./provider-request-error-classifier.js";
|
||||
import { PROVIDER_CONVERSATION_STATE_ERROR_USER_MESSAGE } from "./provider-request-error-classifier.js";
|
||||
import type { FollowupRun } from "./queue.js";
|
||||
import { createReplyOperation, type ReplyOperation } from "./reply-run-registry.js";
|
||||
import type { TypingSignaler } from "./typing-mode.js";
|
||||
|
||||
const PROVIDER_AUTHENTICATION_ERROR_USER_MESSAGE = `⚠️ ${AUTH_INVALID_TOKEN_USER_TEXT}`;
|
||||
const PROVIDER_RATE_LIMIT_OR_QUOTA_ERROR_USER_MESSAGE =
|
||||
"⚠️ The model provider returned HTTP 429 before replying. This can mean rate limiting, exhausted quota, or an account balance/billing issue. Check the selected provider/model, API key, and provider billing/quota dashboard, then try again.";
|
||||
const PROVIDER_INTERNAL_ERROR_USER_MESSAGE =
|
||||
"⚠️ The model provider returned a temporary internal error before replying. Try again in a moment, or switch to another model if it keeps happening.";
|
||||
|
||||
const state = vi.hoisted(() => ({
|
||||
runEmbeddedAgentMock: vi.fn(),
|
||||
runCliAgentMock: vi.fn(),
|
||||
|
||||
@@ -418,7 +418,7 @@ export type RuntimeFallbackAttempt = {
|
||||
};
|
||||
|
||||
/** Result of running an agent turn through fallback/retry handling. */
|
||||
export type AgentRunLoopResult =
|
||||
type AgentRunLoopResult =
|
||||
| {
|
||||
kind: "success";
|
||||
runId: string;
|
||||
|
||||
@@ -22,13 +22,20 @@ vi.mock("../../utils/provider-utils.js", () => ({
|
||||
isReasoningTagProvider: (...args: unknown[]) => hoisted.isReasoningTagProviderMock(...args),
|
||||
}));
|
||||
|
||||
const {
|
||||
buildThreadingToolContext,
|
||||
buildEmbeddedRunBaseParams,
|
||||
buildEmbeddedRunExecutionParams,
|
||||
resolveModelFallbackOptions,
|
||||
resolveProviderScopedAuthProfile,
|
||||
} = await import("./agent-runner-utils.js");
|
||||
const { buildThreadingToolContext, buildEmbeddedRunExecutionParams, resolveModelFallbackOptions } =
|
||||
await import("./agent-runner-utils.js");
|
||||
const { resolveProviderScopedAuthProfile } = await import("./agent-runner-auth-profile.js");
|
||||
const { buildEmbeddedRunBaseParams: buildEmbeddedRunBaseParamsCore } =
|
||||
await import("./agent-runner-run-params.js");
|
||||
|
||||
function buildEmbeddedRunBaseParams(
|
||||
params: Omit<Parameters<typeof buildEmbeddedRunBaseParamsCore>[0], "isReasoningTagProvider">,
|
||||
) {
|
||||
return buildEmbeddedRunBaseParamsCore({
|
||||
...params,
|
||||
isReasoningTagProvider: hoisted.isReasoningTagProviderMock,
|
||||
});
|
||||
}
|
||||
|
||||
function makeRun(overrides: Partial<FollowupRun["run"]> = {}): FollowupRun["run"] {
|
||||
return {
|
||||
|
||||
@@ -26,11 +26,8 @@ import {
|
||||
import type { SessionEntry } from "../../config/sessions.js";
|
||||
import { isReasoningTagProvider } from "../../utils/provider-utils.js";
|
||||
import type { TemplateContext } from "../templating.js";
|
||||
import {
|
||||
resolveProviderScopedAuthProfile,
|
||||
resolveRunAuthProfile,
|
||||
} from "./agent-runner-auth-profile.js";
|
||||
export { resolveProviderScopedAuthProfile, resolveRunAuthProfile };
|
||||
import { resolveRunAuthProfile } from "./agent-runner-auth-profile.js";
|
||||
export { resolveRunAuthProfile };
|
||||
import { buildEmbeddedRunBaseParams as buildEmbeddedRunBaseParamsCore } from "./agent-runner-run-params.js";
|
||||
export { resolveModelFallbackOptions } from "./agent-runner-run-params.js";
|
||||
import { hasInboundAudio } from "./inbound-media.js";
|
||||
@@ -231,9 +228,7 @@ export function resolveRunFastModeForFallbackCandidate(params: {
|
||||
};
|
||||
}
|
||||
/** Builds base embedded run params with auth and provider runtime hints. */
|
||||
export function buildEmbeddedRunBaseParams(
|
||||
params: Parameters<typeof buildEmbeddedRunBaseParamsCore>[0],
|
||||
) {
|
||||
function buildEmbeddedRunBaseParams(params: Parameters<typeof buildEmbeddedRunBaseParamsCore>[0]) {
|
||||
return buildEmbeddedRunBaseParamsCore({
|
||||
...params,
|
||||
isReasoningTagProvider,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import path from "node:path";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { TemplateContext } from "../templating.js";
|
||||
import type { AgentRunLoopResult } from "./agent-runner-execution.js";
|
||||
import type { FollowupRun, QueueSettings } from "./queue.js";
|
||||
import type { ReplyOperation } from "./reply-run-registry.js";
|
||||
import { createMockFollowupRun, createMockTypingController } from "./test-helpers.js";
|
||||
@@ -102,6 +101,10 @@ vi.mock("./session-run-accounting.js", () => ({
|
||||
|
||||
const { runReplyAgent } = await import("./agent-runner.js");
|
||||
|
||||
type AgentRunLoopResult = Awaited<
|
||||
ReturnType<typeof import("./agent-runner-execution.js").runAgentTurnWithFallback>
|
||||
>;
|
||||
|
||||
function createReplyOperation(): ReplyOperation {
|
||||
return {
|
||||
result: undefined,
|
||||
|
||||
@@ -28,7 +28,6 @@ import {
|
||||
import {
|
||||
REPLY_OPERATION_RUN_STATE,
|
||||
type ReplyOperationRunState,
|
||||
type ReplyOptionsWithOperationRunState,
|
||||
} from "./reply-operation-run-state.js";
|
||||
import {
|
||||
createReplyOperation,
|
||||
@@ -38,6 +37,10 @@ import {
|
||||
import { consumeReplyUsageState } from "./reply-usage-state.js";
|
||||
import { createMockTypingController } from "./test-helpers.js";
|
||||
|
||||
type ReplyOptionsWithOperationRunState = {
|
||||
[REPLY_OPERATION_RUN_STATE]?: ReplyOperationRunState;
|
||||
};
|
||||
|
||||
type AgentRunParams = {
|
||||
sessionId?: string;
|
||||
sessionFile?: string;
|
||||
|
||||
@@ -16,9 +16,10 @@ import {
|
||||
stopWithText,
|
||||
} from "./commands-subagents-dispatch.js";
|
||||
import { handleSubagentsCommand } from "./commands-subagents.js";
|
||||
import { COMMAND } from "./commands-subagents/shared.js";
|
||||
import type { HandleCommandsParams } from "./commands-types.js";
|
||||
|
||||
const COMMAND = "/subagents";
|
||||
|
||||
const listControlledSubagentRunsMock = vi.hoisted(() => vi.fn(() => []));
|
||||
|
||||
vi.mock("./commands-subagents-control.runtime.js", () => ({
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
|
||||
export type { ChatMessage } from "../commands-subagents-text.js";
|
||||
|
||||
export const COMMAND = "/subagents";
|
||||
const COMMAND = "/subagents";
|
||||
const COMMAND_FOCUS = "/focus";
|
||||
const COMMAND_UNFOCUS = "/unfocus";
|
||||
const COMMAND_AGENTS = "/agents";
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// Tests effective reply route selection from context, session, and fallback state.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
isSystemEventProvider,
|
||||
resolveEffectiveReplyRoute,
|
||||
type EffectiveReplyRouteContext,
|
||||
type EffectiveReplyRouteEntry,
|
||||
} from "./effective-reply-route.js";
|
||||
import { isSystemEventProvider, resolveEffectiveReplyRoute } from "./effective-reply-route.js";
|
||||
|
||||
type EffectiveReplyRouteParams = Parameters<typeof resolveEffectiveReplyRoute>[0];
|
||||
type EffectiveReplyRouteContext = EffectiveReplyRouteParams["ctx"];
|
||||
type EffectiveReplyRouteEntry = NonNullable<EffectiveReplyRouteParams["entry"]>;
|
||||
|
||||
const ctx = (params: EffectiveReplyRouteContext): EffectiveReplyRouteContext => params;
|
||||
const entry = (params: EffectiveReplyRouteEntry): EffectiveReplyRouteEntry => params;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { INTERNAL_MESSAGE_CHANNEL, normalizeMessageChannel } from "../../utils/m
|
||||
import type { FinalizedMsgContext } from "../templating.js";
|
||||
|
||||
/** Current finalized context fields used for reply route resolution. */
|
||||
export type EffectiveReplyRouteContext = Pick<
|
||||
type EffectiveReplyRouteContext = Pick<
|
||||
FinalizedMsgContext,
|
||||
| "Provider"
|
||||
| "Surface"
|
||||
@@ -19,7 +19,7 @@ export type EffectiveReplyRouteContext = Pick<
|
||||
>;
|
||||
|
||||
/** Persisted session fields used as route fallback/inheritance. */
|
||||
export type EffectiveReplyRouteEntry = Pick<
|
||||
type EffectiveReplyRouteEntry = Pick<
|
||||
SessionEntry,
|
||||
"deliveryContext" | "lastChannel" | "lastTo" | "lastAccountId" | "route" | "chatType" | "origin"
|
||||
>;
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import type { MsgContext } from "../templating.js";
|
||||
import {
|
||||
buildInboundDedupeKey,
|
||||
resetInboundDedupe,
|
||||
type InboundDedupeClaimResult,
|
||||
} from "./inbound-dedupe.js";
|
||||
import { buildInboundDedupeKey, resetInboundDedupe } from "./inbound-dedupe.js";
|
||||
|
||||
type InboundDedupeClaimResult = ReturnType<typeof import("./inbound-dedupe.js").claimInboundDedupe>;
|
||||
|
||||
const sharedInboundContext: MsgContext = {
|
||||
Provider: "discord",
|
||||
|
||||
@@ -29,7 +29,7 @@ const inboundDedupeInFlight = resolveGlobalSingleton(
|
||||
() => new Set<string>(),
|
||||
);
|
||||
|
||||
export type InboundDedupeClaimResult =
|
||||
type InboundDedupeClaimResult =
|
||||
| { status: "invalid" }
|
||||
| { status: "duplicate"; key: string }
|
||||
| { status: "inflight"; key: string }
|
||||
|
||||
@@ -18,9 +18,12 @@ vi.mock("../../logging/subsystem.js", async (importOriginal) => {
|
||||
import {
|
||||
attachProgressNarratorToReplyOptions,
|
||||
createProgressNarrator,
|
||||
type ProgressNarrationInput,
|
||||
} from "./progress-narrator.js";
|
||||
|
||||
type ProgressNarrationInput = Parameters<
|
||||
NonNullable<Parameters<typeof createProgressNarrator>[0]["generate"]>
|
||||
>[0];
|
||||
|
||||
const cfg = {} as OpenClawConfig;
|
||||
|
||||
// The narrator runs generations on a detached promise; drain microtasks so
|
||||
|
||||
@@ -39,7 +39,7 @@ const NARRATION_SYSTEM_PROMPT = [
|
||||
"Reply with the status text only.",
|
||||
].join(" ");
|
||||
|
||||
export type ProgressNarrationInput = {
|
||||
type ProgressNarrationInput = {
|
||||
userMessage: string;
|
||||
activityNotes: readonly string[];
|
||||
previousText: string;
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
/** Tests provider request error classification for retry/fallback decisions. */
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { AUTH_INVALID_TOKEN_USER_TEXT } from "../../agents/embedded-agent-helpers/errors.js";
|
||||
import { FailoverError } from "../../agents/failover-error.js";
|
||||
import {
|
||||
classifyProviderRequestError,
|
||||
PROVIDER_AUTHENTICATION_ERROR_USER_MESSAGE,
|
||||
PROVIDER_CONVERSATION_STATE_ERROR_USER_MESSAGE,
|
||||
PROVIDER_INTERNAL_ERROR_USER_MESSAGE,
|
||||
PROVIDER_MODEL_UNAVAILABLE_USER_MESSAGE,
|
||||
PROVIDER_RATE_LIMIT_OR_QUOTA_ERROR_USER_MESSAGE,
|
||||
} from "./provider-request-error-classifier.js";
|
||||
|
||||
const PROVIDER_AUTHENTICATION_ERROR_USER_MESSAGE = `⚠️ ${AUTH_INVALID_TOKEN_USER_TEXT}`;
|
||||
const PROVIDER_RATE_LIMIT_OR_QUOTA_ERROR_USER_MESSAGE =
|
||||
"⚠️ The model provider returned HTTP 429 before replying. This can mean rate limiting, exhausted quota, or an account balance/billing issue. Check the selected provider/model, API key, and provider billing/quota dashboard, then try again.";
|
||||
const PROVIDER_INTERNAL_ERROR_USER_MESSAGE =
|
||||
"⚠️ The model provider returned a temporary internal error before replying. Try again in a moment, or switch to another model if it keeps happening.";
|
||||
const PROVIDER_MODEL_UNAVAILABLE_USER_MESSAGE =
|
||||
"⚠️ The configured model is unavailable from the provider — it may have been renamed, retired, or is not offered on this account. This needs a config update (agents.defaults.model); retrying or starting a new session won't fix it.";
|
||||
|
||||
describe("provider request error classifier", () => {
|
||||
it("classifies provider HTTP 401 authentication failures", () => {
|
||||
const message =
|
||||
|
||||
@@ -26,20 +26,20 @@ type ProviderRequestErrorClassification = {
|
||||
export const PROVIDER_CONVERSATION_STATE_ERROR_USER_MESSAGE =
|
||||
"⚠️ The model provider rejected the conversation state. Please try again, or use /new to start a fresh session.";
|
||||
|
||||
export const PROVIDER_RATE_LIMIT_OR_QUOTA_ERROR_USER_MESSAGE =
|
||||
const PROVIDER_RATE_LIMIT_OR_QUOTA_ERROR_USER_MESSAGE =
|
||||
"⚠️ The model provider returned HTTP 429 before replying. This can mean rate limiting, exhausted quota, or an account balance/billing issue. Check the selected provider/model, API key, and provider billing/quota dashboard, then try again.";
|
||||
|
||||
export const PROVIDER_INTERNAL_ERROR_USER_MESSAGE =
|
||||
const PROVIDER_INTERNAL_ERROR_USER_MESSAGE =
|
||||
"⚠️ The model provider returned a temporary internal error before replying. Try again in a moment, or switch to another model if it keeps happening.";
|
||||
|
||||
export const PROVIDER_AUTHENTICATION_ERROR_USER_MESSAGE = `⚠️ ${AUTH_INVALID_TOKEN_USER_TEXT}`;
|
||||
const PROVIDER_AUTHENTICATION_ERROR_USER_MESSAGE = `⚠️ ${AUTH_INVALID_TOKEN_USER_TEXT}`;
|
||||
|
||||
/**
|
||||
* User-facing copy for a configured model the provider no longer serves.
|
||||
* Distinct from generic failures because retrying or starting a new session
|
||||
* cannot help: the model id itself must be changed in config.
|
||||
*/
|
||||
export const PROVIDER_MODEL_UNAVAILABLE_USER_MESSAGE =
|
||||
const PROVIDER_MODEL_UNAVAILABLE_USER_MESSAGE =
|
||||
"⚠️ The configured model is unavailable from the provider — it may have been renamed, retired, or is not offered on this account. This needs a config update (agents.defaults.model); retrying or starting a new session won't fix it.";
|
||||
|
||||
/** Classifies provider request failures that are actionable for users. */
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
export { clearSessionQueues } from "./queue/cleanup.js";
|
||||
export type { ClearSessionQueueResult } from "./queue/cleanup.js";
|
||||
export { scheduleFollowupDrain } from "./queue/drain.js";
|
||||
export {
|
||||
enqueueFollowupRun,
|
||||
getFollowupQueueDepth,
|
||||
resetRecentQueuedMessageIdDedupe,
|
||||
} from "./queue/enqueue.js";
|
||||
export { enqueueFollowupRun, getFollowupQueueDepth } from "./queue/enqueue.js";
|
||||
export { resolveQueueSettings } from "./queue/settings-runtime.js";
|
||||
export { refreshQueuedFollowupSession } from "./queue/state.js";
|
||||
export type { FollowupRun, QueueSettings } from "./queue/types.js";
|
||||
|
||||
@@ -10,7 +10,7 @@ export type ReplyOperationRunState = {
|
||||
// heartbeat cleanup never infers it from whichever operation is active later.
|
||||
export const REPLY_OPERATION_RUN_STATE = Symbol("openclaw.replyOperationRunState");
|
||||
|
||||
export type ReplyOptionsWithOperationRunState = {
|
||||
type ReplyOptionsWithOperationRunState = {
|
||||
[REPLY_OPERATION_RUN_STATE]?: ReplyOperationRunState;
|
||||
};
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ type ForkSessionFromParentParams = {
|
||||
|
||||
type ForkedParentSessionEntry = ParentForkedSessionTranscript;
|
||||
|
||||
export type ForkSessionEntryFromParentResult =
|
||||
type ForkSessionEntryFromParentResult =
|
||||
| {
|
||||
status: "forked";
|
||||
fork: ForkedParentSessionEntry;
|
||||
@@ -66,7 +66,7 @@ export type ForkSessionEntryFromParentResult =
|
||||
| { status: "missing-parent" }
|
||||
| { status: "failed" };
|
||||
|
||||
export type ForkSessionEntryFromParentParams = Omit<ForkSessionFromParentParams, "parentEntry"> & {
|
||||
type ForkSessionEntryFromParentParams = Omit<ForkSessionFromParentParams, "parentEntry"> & {
|
||||
parentSessionKey: string;
|
||||
parentStoreKeys?: readonly string[];
|
||||
sessionKey: string;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { completeFollowupRunLifecycle, markFollowupRunEnqueued } from "./queue/types.js";
|
||||
import {
|
||||
buildStrandedReplyRetryFollowupRun,
|
||||
STRANDED_REPLY_RETRY_MARKER,
|
||||
} from "./stranded-reply-recovery.js";
|
||||
import { buildStrandedReplyRetryFollowupRun } from "./stranded-reply-recovery.js";
|
||||
import { createMockFollowupRun } from "./test-helpers.js";
|
||||
|
||||
const STRANDED_REPLY_RETRY_MARKER = "stranded-reply-retry";
|
||||
|
||||
describe("buildStrandedReplyRetryFollowupRun lifecycle ownership", () => {
|
||||
it("does not share the client turn's queuedLifecycle with the system retry", () => {
|
||||
const onComplete = vi.fn();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { markReplyPayloadForSourceSuppressionDelivery } from "../reply-payload.j
|
||||
import type { ReplyPayload } from "../types.js";
|
||||
import type { FollowupRun } from "./queue/types.js";
|
||||
|
||||
export const STRANDED_REPLY_RETRY_MARKER = "stranded-reply-retry";
|
||||
const STRANDED_REPLY_RETRY_MARKER = "stranded-reply-retry";
|
||||
const STRANDED_REPLY_DELIVERY_FAILURE_TEXT =
|
||||
"I generated a reply but could not deliver it to this chat. Please try again.";
|
||||
|
||||
|
||||
@@ -15,10 +15,7 @@ import {
|
||||
import { ErrorCodes } from "../../../packages/gateway-protocol/src/index.js";
|
||||
import { CHAT_SEND_SESSION_KEY_MAX_LENGTH } from "../../../packages/gateway-protocol/src/schema.js";
|
||||
import type { ModelCatalogEntry } from "../../agents/model-catalog.types.js";
|
||||
import {
|
||||
buildPairingQrReplyChannelData,
|
||||
setReplyPayloadMetadata,
|
||||
} from "../../auto-reply/reply-payload.js";
|
||||
import { setReplyPayloadMetadata } from "../../auto-reply/reply-payload.js";
|
||||
import type { MsgContext } from "../../auto-reply/templating.js";
|
||||
import {
|
||||
appendTranscriptMessage,
|
||||
@@ -2651,10 +2648,12 @@ describe("chat directive tag stripping for non-streaming final payloads", () =>
|
||||
kind: "final",
|
||||
payload: {
|
||||
text: "Scan this QR code with the OpenClaw iOS app:",
|
||||
channelData: buildPairingQrReplyChannelData({
|
||||
setupCode,
|
||||
expiresAtMs: Date.now() + 10 * 60_000,
|
||||
}),
|
||||
channelData: {
|
||||
openclawPairingQr: {
|
||||
setupCode,
|
||||
expiresAtMs: Date.now() + 10 * 60_000,
|
||||
},
|
||||
},
|
||||
sensitiveMedia: true,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { RunEmbeddedAgentParams } from "../agents/embedded-agent-runner/run/params.js";
|
||||
import type {
|
||||
ForkSessionEntryFromParentParams,
|
||||
ForkSessionEntryFromParentResult,
|
||||
} from "../auto-reply/reply/session-fork.js";
|
||||
import type { SessionEntry } from "../config/sessions/types.js";
|
||||
import { MODEL_SELECTION_LOCKED_MESSAGE } from "../sessions/model-overrides.js";
|
||||
import { runExclusiveSessionLifecycleMutation } from "../sessions/session-lifecycle-admission.js";
|
||||
@@ -17,6 +13,11 @@ import {
|
||||
resolveRealtimeVoiceAgentConsultToolsAllow,
|
||||
} from "./agent-consult-tool.js";
|
||||
|
||||
type ForkSessionEntryFromParent =
|
||||
typeof import("../auto-reply/reply/session-fork.js").forkSessionEntryFromParent;
|
||||
type ForkSessionEntryFromParentParams = Parameters<ForkSessionEntryFromParent>[0];
|
||||
type ForkSessionEntryFromParentResult = Awaited<ReturnType<ForkSessionEntryFromParent>>;
|
||||
|
||||
function createAgentRuntime(payloads: unknown[] = [{ text: "Speak this." }]) {
|
||||
const sessionStore: Record<
|
||||
string,
|
||||
|
||||
Reference in New Issue
Block a user