85 lines
3.1 KiB
TypeScript
85 lines
3.1 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import type { Plugin } from "@opencode/plugin";
|
|
import type { Context } from "@opencode/plugin/effect/plugin";
|
|
import { Effect } from "effect";
|
|
import quota from "../src/quota-plugin.js";
|
|
import multiWork from "../src/multi-work.js";
|
|
import { QuotaRpc } from "../src/quota-rpc.js";
|
|
import { AgentsRpc } from "../src/agents-rpc.js";
|
|
|
|
test("Quota loads independently and retains its RPC ID and nullable status", async () => {
|
|
let controller: ReadableStreamDefaultController<unknown>;
|
|
const stream = new ReadableStream({
|
|
start(value) {
|
|
controller = value;
|
|
},
|
|
});
|
|
let status: (() => Promise<null>) | undefined;
|
|
let disposed = false;
|
|
let modelHook = false;
|
|
const context = {
|
|
options: {},
|
|
location: { directory: "/fixture" },
|
|
integration: {
|
|
connection: {
|
|
async active() {
|
|
return undefined;
|
|
},
|
|
},
|
|
},
|
|
event: {
|
|
subscribe({ signal }: { signal: AbortSignal }) {
|
|
signal.addEventListener("abort", () => controller.close(), { once: true });
|
|
return stream;
|
|
},
|
|
},
|
|
rpc: {
|
|
async register(definition: typeof QuotaRpc, handlers: { status: () => Promise<null> }) {
|
|
expect(definition.id).toBe("stanp-opencode.quota");
|
|
status = handlers.status;
|
|
return {
|
|
async dispose() {
|
|
disposed = true;
|
|
},
|
|
events: { async emit() {} },
|
|
};
|
|
},
|
|
},
|
|
session: {
|
|
async hook(name: string) {
|
|
expect(name).toBe("model.request");
|
|
modelHook = true;
|
|
return { async dispose() {} };
|
|
},
|
|
},
|
|
};
|
|
// SAFETY: Quota with no credentials uses only these native host services.
|
|
// Absent agent/model/MCP APIs fail if independence regresses.
|
|
const setup = quota.setup as (
|
|
context: Pick<Plugin.Context, "options">,
|
|
) => ReturnType<typeof quota.setup>;
|
|
const cleanup = await setup(context);
|
|
expect(quota.id).toBe("stanp-opencode.quota");
|
|
expect(await status!()).toBeNull();
|
|
expect(modelHook).toBe(true);
|
|
if (cleanup) await cleanup();
|
|
expect(disposed).toBe(true);
|
|
});
|
|
|
|
test("Multi-work rejects missing Agents before any Herdr operations or registrations", async () => {
|
|
const context = {
|
|
rpc: (definition: typeof AgentsRpc) => {
|
|
expect(definition.id).toBe("stanp-opencode.agents");
|
|
return { permissions: () => Effect.fail(new Error("RPC not registered")) };
|
|
},
|
|
};
|
|
// SAFETY: Missing Agents fails at the first RPC call; no other host service is accessed.
|
|
const activate = multiWork.effect as (
|
|
context: Pick<Context, "options">,
|
|
) => ReturnType<typeof multiWork.effect>;
|
|
const result = await Effect.runPromiseExit(
|
|
Effect.scoped(activate({ ...context, options: {} })),
|
|
);
|
|
expect(String(result)).toContain("Multi-work requires Agents loaded before it");
|
|
});
|