"use strict"; const assert = require("node:assert/strict"); const { test } = require("node:test"); const { parseDecision, extractCliResponse, tokenUsage, makePrompt } = require("../gemini_bot_logic"); test("accepts one bounded action", () => { assert.deepEqual(parseDecision('{"action":"explore","direction":"north","blocks":16}'), { action: "explore", direction: "north", blocks: 16 }); assert.deepEqual(parseDecision('```json\n{"action":"mine","block":"stone"}\n```'), { action: "mine", block: "stone" }); assert.deepEqual(parseDecision('{"action":"follow","player":"IffyBinkie6134"}'), { action: "follow", player: "IffyBinkie6134" }); }); test("rejects code, chat commands, arbitrary targets, and extra prose", () => { for (const value of [ 'Explain: {"action":"mine","block":"stone"}', '{"action":"say","message":"/op stranger"}', '{"action":"place","block":"bedrock"}', '{"action":"follow","player":"stranger"}', '{"action":"explore","direction":"down","blocks":16}', '{"action":"explore","direction":"north","blocks":9999}', '{"action":"run","code":"process.exit(1)"}', '{"action":"mine","block":"stone"}{"action":"say","message":"hi"}', '{"action":"mine","block":"stone"', ]) assert.throws(() => parseDecision(value)); }); test("reads CLI envelope, and fails closed on API errors", () => { const envelope = { response: '{"action":"wait"}', stats: { models: {} } }; assert.deepEqual(extractCliResponse(JSON.stringify(envelope)).decision, { action: "wait" }); assert.throws(() => extractCliResponse(JSON.stringify({ response: null, error: { code: 429 } }))); assert.throws(() => extractCliResponse("invalid")); }); test("aggregates per-model CLI token metrics", () => { assert.deepEqual(tokenUsage({ models: { "gemini-3.5-flash-lite": { tokens: { prompt: 120, candidates: 25 } } } }), { models_used: ["gemini-3.5-flash-lite"], prompt_tokens: 120, completion_tokens: 25 }); assert.deepEqual(tokenUsage({ tokens: { input: 10, output: 2 } }), { models_used: [], prompt_tokens: 10, completion_tokens: 2 }); }); test("prompt contains one observed world and the short admin request", () => { const prompt = makePrompt({ position: { x: 0, y: 70, z: 0 }, nearby_blocks: ["stone"] }, "segue o Naldo"); assert.match(prompt, /Naldo_Bot/); assert.match(prompt, /segue o Naldo/); assert.match(prompt, /nearby_blocks/); assert.ok(prompt.length < 3000); });