fix(runtime/skills/chop-logs): skip unsafe log gathering near hostiles

This commit is contained in:
2026-05-27 13:07:40 +03:00
parent fe6961e5f7
commit b5954f193d
2 changed files with 30 additions and 0 deletions
+19
View File
@@ -25,6 +25,14 @@ function withTimeout(promise, ms, label) {
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
}
const UNSAFE_HOSTILE_DISTANCE = 8;
function nearbyUnsafeHostile(snapshot) {
const hostile = snapshot?.closestHostile;
const distance = Number(hostile?.distance);
if (!Number.isFinite(distance) || distance > UNSAFE_HOSTILE_DISTANCE) return null;
return { name: hostile?.name ?? "hostile", distance };
}
export const skill = Object.freeze({
id: "gather.logs",
title: "Gather logs",
@@ -34,6 +42,17 @@ export const skill = Object.freeze({
timeoutMs: 90_000,
preconditions(ctx) {
if (!ctx?.bot) return { ok: false, code: "no_bot", detail: "bot missing" };
const unsafeHostile = nearbyUnsafeHostile(ctx.snapshot);
if (unsafeHostile) {
// When defend/flee is cooling down, don't let collectBlock spend its
// whole 60s timeout chopping beside a mob. no_target reuses the
// scheduler's existing short backoff for gather skills.
return {
ok: false,
code: "no_target",
detail: `unsafe to gather logs: ${unsafeHostile.name} ${unsafeHostile.distance.toFixed(1)} blocks away`,
};
}
const known = logBlocks(ctx.bot);
if (known.size === 0) {
return { ok: false, code: "unsupported_version", detail: "no log blocks in registry" };
+11
View File
@@ -37,6 +37,17 @@ test("preconditions gate execution", async () => {
}
});
test("gather.logs precondition refuses nearby hostiles", async () => {
const bot = { registry: { blocksByName: { oak_log: { id: 1 } } } };
const res = await runSkill("gather.logs", {
bot,
snapshot: { closestHostile: { name: "drowned", distance: 6.1 } },
});
assert.equal(res.ok, false);
assert.equal(res.code, "no_target");
assert.match(res.detail, /unsafe to gather logs: drowned 6\.1 blocks away/);
});
test("preconditions that throw produce precondition_failed", async () => {
const teardown = _registerForTest({
id: "test.precondition-throw",