mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-22 13:28:10 +00:00
Respect the configured QMD status timeout during vector availability probes and skip checkpoint-style session transcript exports while preserving valid session IDs that merely contain checkpoint words. Includes maintainer fixups for latest-main timer-dependent CI and SMS status/test drift. Thanks @shawnduggan. Verification: - `mise exec node@24.13.0 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.agents-core.config.ts src/agents/bash-tools.exec-foreground-failures.test.ts --maxWorkers=1` - `mise exec node@24.16.0 -- node scripts/run-vitest.mjs run src/channels/draft-stream-loop.test.ts --maxWorkers=1` - `mise exec node@24.16.0 -- node scripts/run-vitest.mjs run extensions/sms/src/channel.test.ts extensions/sms/src/inbound.test.ts extensions/sms/src/twilio.test.ts extensions/sms/src/gateway.test.ts --maxWorkers=1` - `mise exec node@24.16.0 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway-server.config.ts src/gateway/server.agent.gateway-server-agent-b.test.ts --maxWorkers=1` - `mise exec node@24.16.0 -- node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo` - `mise exec node@24.16.0 -- node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test.tsbuildinfo` - `mise exec node@24.16.0 -- node scripts/run-oxlint-shards.mjs --threads=8` - `git diff --check` - GitHub Actions: run `26708853296` and required checks passed on `0c97217a9de501cb861fee731d5c008781da056c`.
107 lines
3.8 KiB
TypeScript
107 lines
3.8 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
isCliBindingFlushed,
|
|
restoreCliRunnerTestDeps,
|
|
setCliRunnerTestDeps,
|
|
} from "./cli-runner.js";
|
|
|
|
describe("isCliBindingFlushed", () => {
|
|
const workspaceDir = "/tmp/openclaw-workspace";
|
|
|
|
beforeEach(() => {
|
|
vi.useRealTimers();
|
|
restoreCliRunnerTestDeps();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.clearAllTimers();
|
|
vi.useRealTimers();
|
|
restoreCliRunnerTestDeps();
|
|
});
|
|
|
|
it("returns false when no sessionId is provided", async () => {
|
|
const probe = vi.fn(async () => true);
|
|
setCliRunnerTestDeps({ claudeCliSessionTranscriptHasContent: probe });
|
|
|
|
expect(await isCliBindingFlushed(undefined, "claude-cli")).toBe(false);
|
|
expect(probe).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("returns true when the transcript has content on the first probe", async () => {
|
|
const probe = vi.fn(async () => true);
|
|
setCliRunnerTestDeps({ claudeCliSessionTranscriptHasContent: probe });
|
|
|
|
expect(await isCliBindingFlushed("sid-fresh", "claude-cli", workspaceDir)).toBe(true);
|
|
expect(probe).toHaveBeenCalledTimes(1);
|
|
expect(probe).toHaveBeenCalledWith({ sessionId: "sid-fresh", workspaceDir });
|
|
});
|
|
|
|
it("retries up to three times before giving up", async () => {
|
|
const delay = vi.fn(async () => undefined);
|
|
const probe = vi.fn(async () => false);
|
|
setCliRunnerTestDeps({ claudeCliSessionTranscriptHasContent: probe, delay });
|
|
|
|
expect(await isCliBindingFlushed("sid-cold", "claude-cli", workspaceDir)).toBe(false);
|
|
expect(probe).toHaveBeenCalledTimes(3);
|
|
expect(delay).toHaveBeenCalledTimes(2);
|
|
expect(delay).toHaveBeenNthCalledWith(1, 50);
|
|
expect(delay).toHaveBeenNthCalledWith(2, 150);
|
|
});
|
|
|
|
it("succeeds when the transcript becomes visible on a later retry", async () => {
|
|
const delay = vi.fn(async () => undefined);
|
|
let calls = 0;
|
|
const probe = vi.fn(async () => {
|
|
calls += 1;
|
|
return calls >= 2;
|
|
});
|
|
setCliRunnerTestDeps({ claudeCliSessionTranscriptHasContent: probe, delay });
|
|
|
|
expect(await isCliBindingFlushed("sid-late", "claude-cli", workspaceDir)).toBe(true);
|
|
expect(probe).toHaveBeenCalledTimes(2);
|
|
expect(delay).toHaveBeenCalledExactlyOnceWith(50);
|
|
});
|
|
|
|
it("schedules at most 0 + 50 + 150ms of delay across the bounded retry", async () => {
|
|
vi.useFakeTimers();
|
|
try {
|
|
const probe = vi.fn(async () => false);
|
|
setCliRunnerTestDeps({ claudeCliSessionTranscriptHasContent: probe });
|
|
|
|
const settled = vi.fn();
|
|
const errored = vi.fn();
|
|
isCliBindingFlushed("sid-bounded", "claude-cli", workspaceDir).then(settled, errored);
|
|
|
|
await vi.advanceTimersByTimeAsync(0);
|
|
await vi.advanceTimersByTimeAsync(50);
|
|
await vi.advanceTimersByTimeAsync(150);
|
|
|
|
expect(settled).toHaveBeenCalledTimes(1);
|
|
expect(settled.mock.calls[0]?.[0]).toBe(false);
|
|
expect(errored).not.toHaveBeenCalled();
|
|
expect(probe).toHaveBeenCalledTimes(3);
|
|
} finally {
|
|
vi.clearAllTimers();
|
|
vi.useRealTimers();
|
|
}
|
|
});
|
|
|
|
it("returns true without probing for non-claude-cli providers", async () => {
|
|
const probe = vi.fn(async () => false);
|
|
setCliRunnerTestDeps({ claudeCliSessionTranscriptHasContent: probe });
|
|
|
|
expect(await isCliBindingFlushed("sid-codex", "codex-cli")).toBe(true);
|
|
expect(await isCliBindingFlushed("sid-anthropic", "anthropic")).toBe(true);
|
|
expect(await isCliBindingFlushed("sid-openai", "openai")).toBe(true);
|
|
expect(probe).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("returns true without probing when provider is undefined", async () => {
|
|
const probe = vi.fn(async () => false);
|
|
setCliRunnerTestDeps({ claudeCliSessionTranscriptHasContent: probe });
|
|
|
|
expect(await isCliBindingFlushed("sid-x", undefined)).toBe(true);
|
|
expect(probe).not.toHaveBeenCalled();
|
|
});
|
|
});
|