Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions packages/provider-muse/src/server/status.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import * as NodeServices from "@effect/platform-node/NodeServices";
import { expect, it } from "@effect/vitest";
import { MuseSettings } from "../settings.ts";
import * as Effect from "effect/Effect";
import * as Fiber from "effect/Fiber";
import * as FileSystem from "effect/FileSystem";
import * as Schema from "effect/Schema";
import * as Sink from "effect/Sink";
import * as Stream from "effect/Stream";
import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner";
import * as TestClock from "effect/testing/TestClock";
import { vi } from "vite-plus/test";

import { writeFakeCli } from "@t3tools/provider-testing/fakeCli";
Expand Down Expand Up @@ -54,6 +59,25 @@ const fakeCli = (source = 'process.stdout.write("muse 1.0.3-R2198.1\\n");') =>
return writeFakeCli({ directory, name: "muse", source });
});

const slowVersionSpawner = (delayMs: number) =>
ChildProcessSpawner.make(() =>
Effect.succeed(
ChildProcessSpawner.makeHandle({
pid: ChildProcessSpawner.ProcessId(900_000_001),
exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(0)).pipe(Effect.delay(delayMs)),
isRunning: Effect.succeed(false),
kill: () => Effect.void,
unref: Effect.succeed(Effect.void),
stdin: Sink.drain,
stdout: Stream.succeed(new TextEncoder().encode("muse 1.4.12-R6909.1\n")),
stderr: Stream.empty,
all: Stream.empty,
getInputFd: () => Sink.drain,
getOutputFd: () => Stream.empty,
}),
),
);

it.layer(NodeServices.layer)("Muse status", (it) => {
it.effect("does not expose CLI stderr or start an SDK host after a failed version check", () =>
Effect.scoped(
Expand Down Expand Up @@ -128,4 +152,44 @@ it.layer(NodeServices.layer)("Muse status", (it) => {
}),
),
);

it.effect("waits for a version check that takes several seconds to answer", () =>
Effect.gen(function* () {
const host = makeHost(metaCatalog);
const probing = yield* checkMuseProviderStatus(
settings({ enabled: true, binaryPath: "muse" }),
undefined,
undefined,
async () => host,
).pipe(
Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, slowVersionSpawner(6_000)),
Effect.forkChild({ startImmediately: true }),
);
yield* TestClock.adjust("6 seconds");
const snapshot = yield* Fiber.join(probing);
expect(snapshot.status).toBe("ready");
expect(snapshot.version).toBe("1.4.12-R6909.1");
}),
);

it.effect("stops a version check after fifteen seconds without starting the SDK", () =>
Effect.gen(function* () {
const createHost = vi.fn(async () => makeHost(metaCatalog));
const probing = yield* checkMuseProviderStatus(
settings({ enabled: true, binaryPath: "muse" }),
undefined,
undefined,
createHost,
).pipe(
Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, slowVersionSpawner(16_000)),
Effect.forkChild({ startImmediately: true }),
);
yield* TestClock.adjust("15 seconds");
const snapshot = yield* Fiber.join(probing);
expect(snapshot.status).toBe("error");
expect(snapshot.message).toBe("Muse Code CLI version check timed out.");
expect(snapshot.version).toBeNull();
expect(createHost).not.toHaveBeenCalled();
}),
);
});
6 changes: 4 additions & 2 deletions packages/provider-muse/src/server/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import { discoverMuseModels, museModelCapabilities } from "./modelCatalog.ts";
import {
buildServerProvider,
COMPACT_SLASH_COMMAND,
DEFAULT_TIMEOUT_MS,
isCommandMissingCause,
providerModelsFromSettings,
spawnAndCollect,
type ProviderProbeResult,
} from "@t3tools/provider-core/server/snapshotProbe";

// Muse can take 4-9 seconds to start inside a Windows job object.
const MUSE_VERSION_PROBE_TIMEOUT = "15 seconds";

const MUSE_PRESENTATION = {
displayName: "Muse Code",
showInteractionModeToggle: false,
Expand Down Expand Up @@ -81,7 +83,7 @@ export const checkMuseProviderStatus = Effect.fn("checkMuseProviderStatus")(func
...(cwd ? { cwd } : {}),
}),
);
}).pipe(Effect.timeoutOption(DEFAULT_TIMEOUT_MS), Effect.result);
}).pipe(Effect.timeoutOption(MUSE_VERSION_PROBE_TIMEOUT), Effect.result);

if (Result.isFailure(versionResult)) {
const missing = isCommandMissingCause(versionResult.failure);
Expand Down
Loading