This commit is contained in:
@@ -58,18 +58,26 @@ await writeFile(
|
||||
`#!/bin/sh\ncase "$1 $2" in\n"worktree create") [ "$9" = "--label" ] && [ "\${10}" = "Fix native host" ] || exit 8; printf '%s\\n%s\\n' "$6" "\${10}" > '${herdrCreation}'; git -C '${root}' worktree add -b "$6" '${destination}' "$8" >&2 || exit 1; printf '{"result":{"workspace":{"workspace_id":"w2"},"worktree":{"path":"${destination}","branch":"%s","is_linked_worktree":true}}}' "$6"; exit ;;\nesac\ncase "$1 $2 $4" in\n"workspace list ") echo '{"result":{"workspaces":[{"workspace_id":"w1"}]}}' ;;\n"worktree list w1") echo '${inventory(root, "w1")}' ;;\n"worktree list w2") echo '${inventory(destination, "w2")}' ;;\n*) exit 9 ;;\nesac\n`,
|
||||
);
|
||||
await chmod(join(bin, "herdr"), 0o755);
|
||||
const built = await Bun.build({
|
||||
entrypoints: [resolve("tests/fixtures/native-host-plugin.ts")],
|
||||
outdir: join(temp, "plugin"),
|
||||
naming: "index.js",
|
||||
target: "bun",
|
||||
format: "esm",
|
||||
});
|
||||
if (!built.success) throw new Error(String(built.logs));
|
||||
for (const [name, fixture] of [
|
||||
["agents", "native-agents-plugin"],
|
||||
["multi-work", "native-host-plugin"],
|
||||
] as const) {
|
||||
const built = await Bun.build({
|
||||
entrypoints: [resolve(`tests/fixtures/${fixture}.ts`)],
|
||||
outdir: join(temp, "plugin", name),
|
||||
naming: "index.js",
|
||||
target: "bun",
|
||||
format: "esm",
|
||||
});
|
||||
if (!built.success) throw new Error(String(built.logs));
|
||||
}
|
||||
await writeFile(
|
||||
join(config, "opencode.json"),
|
||||
JSON.stringify({
|
||||
plugins: [join(temp, "plugin")],
|
||||
plugins: [
|
||||
{ package: join(temp, "plugin", "agents") },
|
||||
{ package: join(temp, "plugin", "multi-work") },
|
||||
],
|
||||
agents: {
|
||||
build: { permissions: [{ action: "herdr_worktree", resource: "*", effect: "deny" }] },
|
||||
},
|
||||
@@ -290,8 +298,83 @@ try {
|
||||
if (attempt === 99) throw new Error("Native cancellation did not interrupt the child");
|
||||
await Bun.sleep(50);
|
||||
}
|
||||
releaseModel.resolve();
|
||||
holdModel = false;
|
||||
for (const plugins of [
|
||||
[{ package: join(temp, "plugin", "multi-work") }],
|
||||
[
|
||||
{ package: join(temp, "plugin", "multi-work") },
|
||||
{ package: join(temp, "plugin", "agents") },
|
||||
],
|
||||
]) {
|
||||
server.kill();
|
||||
await server.exited;
|
||||
await writeFile(
|
||||
join(config, "opencode.json"),
|
||||
JSON.stringify({ plugins, update: "disable" }),
|
||||
);
|
||||
server = start();
|
||||
await ready();
|
||||
for (let attempt = 0; attempt < 100; attempt++) {
|
||||
const { data } = await client.plugin.list({ location });
|
||||
const multi = data.find((plugin) => plugin.id === "stanp-opencode.multi-work");
|
||||
if (multi?.state.status === "failed") break;
|
||||
if (attempt === 99 || multi?.state.status === "active")
|
||||
throw new Error(
|
||||
`Missing or late Agents did not fail Multi-work activation: ${JSON.stringify(data)}`,
|
||||
);
|
||||
await Bun.sleep(100);
|
||||
}
|
||||
}
|
||||
server.kill();
|
||||
await server.exited;
|
||||
const quotaBuild = await Bun.build({
|
||||
entrypoints: [resolve("src/quota-plugin.ts")],
|
||||
outdir: join(temp, "plugin", "quota"),
|
||||
naming: "index.js",
|
||||
target: "bun",
|
||||
format: "esm",
|
||||
});
|
||||
if (!quotaBuild.success) throw new Error(String(quotaBuild.logs));
|
||||
await writeFile(
|
||||
join(config, "opencode.json"),
|
||||
JSON.stringify({
|
||||
plugins: [{ package: join(temp, "plugin", "quota") }],
|
||||
update: "disable",
|
||||
}),
|
||||
);
|
||||
server = start();
|
||||
await ready();
|
||||
for (let attempt = 0; attempt < 100; attempt++) {
|
||||
const independent = await client.plugin.list({ location });
|
||||
if (
|
||||
independent.data.some(
|
||||
(plugin) =>
|
||||
plugin.id === "stanp-opencode.agents" ||
|
||||
plugin.id === "stanp-opencode.multi-work",
|
||||
)
|
||||
)
|
||||
throw new Error("Quota-only configuration loaded Agents or Multi-work");
|
||||
if (
|
||||
independent.data.some(
|
||||
(plugin) =>
|
||||
plugin.id === "stanp-opencode.quota" && plugin.state.status === "active",
|
||||
)
|
||||
)
|
||||
break;
|
||||
if (attempt === 99) throw new Error("Quota did not activate independently");
|
||||
await Bun.sleep(100);
|
||||
}
|
||||
const quotaStatus = await client.rpc.call({
|
||||
rpcID: "stanp-opencode.quota",
|
||||
method: "status",
|
||||
location,
|
||||
input: {},
|
||||
});
|
||||
if (quotaStatus.output !== null)
|
||||
throw new Error("Unauthenticated Quota RPC should return null");
|
||||
console.log(
|
||||
"PASS: configured build deny + session override, native foreground result, child move-before-prompt, persisted binding resume after host restart, background completion + parent notification, native foreground interruption",
|
||||
"PASS: configured build deny + session override, native foreground result, child move-before-prompt, persisted binding resume after host restart, background completion + parent notification, native foreground interruption, missing/late Agents fail closed, independent Quota and stable RPC",
|
||||
);
|
||||
} finally {
|
||||
releaseModel.resolve();
|
||||
|
||||
Reference in New Issue
Block a user