chore(minecraft): rename planner to repl naming

This commit is contained in:
Rin
2026-02-18 11:14:41 +08:00
committed by Neko Ayaka
parent ca6f157192
commit 1f7e9468c4
5 changed files with 34 additions and 33 deletions
@@ -36,7 +36,7 @@ Use this skill to run the local bot and interact with its MCP debug interface sa
- Use `get_last_prompt` to inspect latest LLM input.
- Use `execute_repl` for deep object inspection or one-off targeted calls on the running brain.
- Use `inject_chat` to simulate player chat and verify behavior loop.
- Use `get_llm_trace` to assert planner behavior in automation (for example, detect repeated `await skip()` on specific events).
- Use `get_llm_trace` to assert REPL behavior in automation (for example, detect repeated `await skip()` on specific events).
- Use `execute_repl("forget_conversation()")` to clear conversation memory before prompt-engineering tests.
Read `references/mcp-surface.md` for exact tool/resource names and argument schemas.
@@ -46,7 +46,7 @@ Read `references/mcp-surface.md` for exact tool/resource names and argument sche
- `get_state` returns a large variable snapshot; prefer it over REPL for first-pass health checks.
- `get_last_prompt` can return very large payloads; call only when prompt-level debugging is needed.
- `execute_repl` returns a structured result where `returnValue` is stringified; parse mentally as display output, not typed JSON.
- `get_logs(limit=10)` is enough to verify whether an injected event reached planner/executor.
- `get_logs(limit=10)` is enough to verify whether an injected event reached REPL/executor.
- `get_llm_trace(limit, turnId?)` gives structured attempt-level trace data (messages, content, reasoning, usage, duration).
- `get_last_prompt` and `get_llm_trace` are compacted for MCP: system prompt/system-role messages are omitted to reduce token cost.
- Prefer compact value reads in REPL:
@@ -69,7 +69,7 @@ Read `references/mcp-surface.md` for exact tool/resource names and argument sche
- Call `get_logs(limit=10)` and check for:
- bot acknowledgement chat
- action tool feedback (for example `collectBlocks`)
- planner result summary
- REPL result summary
- Call `get_llm_trace(limit=5)` when you need exact model output/reasoning for assertions.
5. Re-check inventory using the same REPL snippet and compare against baseline.
@@ -80,7 +80,7 @@ The bot starts this server during normal runtime from:
- Log verification pattern that worked reliably:
1. `inject_chat(...)`
2. `get_logs(limit: 10)`
3. Confirm sequence: `turn_input` -> `llm_attempt` -> `feedback` -> `planner_result`
3. Confirm sequence: `turn_input` -> `llm_attempt` -> `feedback` -> `repl_result`
## Repeatable Smoke Test Recipe
@@ -95,7 +95,7 @@ Use this exact sequence for fast live validation:
- `inject_chat({ username: \"codex-live-test\", message: \"please gather 3 dirt blocks\" })`
3. Execution proof
- `get_logs({ limit: 10 })`
- Expect acknowledgement chat + `collectBlocks` success feedback + planner summary.
- Expect acknowledgement chat + `collectBlocks` success feedback + REPL summary.
- `get_llm_trace({ limit: 5 })`
- Assert expected LLM behavior (for example response code, or repeated `await skip()`).
- Assert trace payload does not include `role: "system"` entries.
@@ -106,7 +106,7 @@ Use this exact sequence for fast live validation:
To validate read->action behavior:
1. Inject a query-style chat (for example inventory question).
2. Confirm first planner result is no-action with concrete return value (via `get_logs`/`get_llm_trace`).
2. Confirm first REPL result is no-action with concrete return value (via `get_logs`/`get_llm_trace`).
3. Confirm follow-up turn uses that returned value to perform chat/action.
## Runtime Caveat
@@ -41,7 +41,7 @@ interface QueuedEvent {
reject: (err: Error) => void
}
interface PlannerOutcomeSummary {
interface ReplOutcomeSummary {
actionCount: number
okCount: number
errorCount: number
@@ -165,7 +165,7 @@ function getEventPriority(event: BotEvent): number {
export class Brain {
private debugService: DebugService
private readonly planner = new JavaScriptPlanner()
private readonly repl = new JavaScriptPlanner()
private paused = false
// State
@@ -176,7 +176,7 @@ export class Brain {
private giveUpUntil = 0
private giveUpReason: string | undefined
private lastContextView: string | undefined
private lastPlannerOutcome: PlannerOutcomeSummary | undefined
private lastReplOutcome: ReplOutcomeSummary | undefined
private conversationHistory: Message[] = []
private lastLlmInputSnapshot: LlmInputSnapshot | null = null
private runtimeMineflayer: MineflayerWithAgents | null = null
@@ -280,7 +280,7 @@ export class Brain {
source: { type: 'system', id: 'debug-repl' },
timestamp: Date.now(),
}
const variables = this.planner.describeGlobals(
const variables = this.repl.describeGlobals(
this.deps.taskExecutor.getAvailableActions(),
this.createRuntimeGlobals(replEvent, snapshot as unknown as Record<string, unknown>),
)
@@ -400,13 +400,13 @@ export class Brain {
const snapshot = this.deps.reflexManager.getContextSnapshot()
const actionDefs = new Map(this.deps.taskExecutor.getAvailableActions().map(action => [action.name, action]))
const normalizedReplCode = this.normalizeReplCode(code)
const codeToEvaluate = this.planner.canEvaluateAsExpression(normalizedReplCode)
const codeToEvaluate = this.repl.canEvaluateAsExpression(normalizedReplCode)
? `return (\n${normalizedReplCode}\n)`
: normalizedReplCode
this.isReplEvaluating = true
try {
const runResult = await this.planner.evaluate(
const runResult = await this.repl.evaluate(
codeToEvaluate,
this.deps.taskExecutor.getAvailableActions(),
this.createRuntimeGlobals({
@@ -910,11 +910,11 @@ export class Brain {
this.deps.logger.withError(lastError).warn('Brain: No response after all retries')
this.appendLlmLog({
turnId,
kind: 'planner_error',
kind: 'repl_error',
eventType: event.type,
sourceType: event.source.type,
sourceId: event.source.id,
tags: ['planner', 'error', 'empty_response'],
tags: ['repl', 'error', 'empty_response'],
text: 'No LLM response after retries',
})
return
@@ -934,11 +934,12 @@ export class Brain {
const actionDefs = new Map(this.deps.taskExecutor.getAvailableActions().map(action => [action.name, action]))
let turnCancellationToken: CancellationToken | undefined
const codeToEvaluate = this.planner.canEvaluateAsExpression(result)
? `return (\n${result}\n)`
: this.rewriteTrailingExpressionToReturn(result)
const normalizedLlmCode = this.normalizeReplCode(result)
const codeToEvaluate = this.repl.canEvaluateAsExpression(normalizedLlmCode)
? `return (\n${normalizedLlmCode}\n)`
: normalizedLlmCode
const runResult = await this.planner.evaluate(
const runResult = await this.repl.evaluate(
codeToEvaluate,
this.deps.taskExecutor.getAvailableActions(),
this.createRuntimeGlobals(event, snapshot as unknown as Record<string, unknown>, bot),
@@ -962,7 +963,7 @@ export class Brain {
},
)
this.lastPlannerOutcome = {
this.lastReplOutcome = {
actionCount: runResult.actions.length,
okCount: runResult.actions.filter(item => item.ok).length,
errorCount: runResult.actions.filter(item => !item.ok).length,
@@ -972,12 +973,12 @@ export class Brain {
}
this.appendLlmLog({
turnId,
kind: 'planner_result',
kind: 'repl_result',
eventType: event.type,
sourceType: event.source.type,
sourceId: event.source.id,
tags: [
'planner',
'repl',
runResult.actions.length === 0 ? 'no_actions' : 'actions',
runResult.actions.some(item => !item.ok) ? 'error' : 'ok',
],
@@ -1038,11 +1039,11 @@ export class Brain {
this.deps.logger.withError(err).error('Brain: Failed to execute decision')
this.appendLlmLog({
turnId,
kind: 'planner_error',
kind: 'repl_error',
eventType: event.type,
sourceType: event.source.type,
sourceId: event.source.id,
tags: ['planner', 'error'],
tags: ['repl', 'error'],
text: truncateForPrompt(toErrorMessage(err), 360),
metadata: {
code: result,
@@ -1105,13 +1106,13 @@ export class Brain {
parts.push(`[STATE] giveUp active (${remainingSec}s left). reason=${this.giveUpReason ?? 'unknown'}`)
}
if (this.lastPlannerOutcome) {
const ageMs = Date.now() - this.lastPlannerOutcome.updatedAt
const returnValue = truncateForPrompt(this.lastPlannerOutcome.returnValue ?? 'undefined')
const logs = this.lastPlannerOutcome.logs.length > 0
? this.lastPlannerOutcome.logs.map((line, index) => `#${index + 1} ${truncateForPrompt(line, 120)}`).join(' | ')
if (this.lastReplOutcome) {
const ageMs = Date.now() - this.lastReplOutcome.updatedAt
const returnValue = truncateForPrompt(this.lastReplOutcome.returnValue ?? 'undefined')
const logs = this.lastReplOutcome.logs.length > 0
? this.lastReplOutcome.logs.map((line, index) => `#${index + 1} ${truncateForPrompt(line, 120)}`).join(' | ')
: '(none)'
parts.push(`[SCRIPT] Last eval ${ageMs}ms ago: return=${returnValue}; actions=${this.lastPlannerOutcome.actionCount} (ok=${this.lastPlannerOutcome.okCount}, err=${this.lastPlannerOutcome.errorCount}); logs=${logs}`)
parts.push(`[SCRIPT] Last eval ${ageMs}ms ago: return=${returnValue}; actions=${this.lastReplOutcome.actionCount} (ok=${this.lastReplOutcome.okCount}, err=${this.lastReplOutcome.errorCount}); logs=${logs}`)
}
parts.push('[RUNTIME] Globals are refreshed every turn: snapshot, self, environment, social, threat, attention, autonomy, event, now, query, bot, mineflayer, currentInput, llmLog, mem, lastRun, prevRun, lastAction. Player gaze is available in environment.nearbyPlayersGaze when needed.')
@@ -8,12 +8,12 @@ function seedEntries(count: number): LlmLogEntry[] {
return Array.from({ length: count }, (_, index) => ({
id: index + 1,
turnId: Math.floor(index / 2) + 1,
kind: index % 3 === 0 ? 'planner_error' : 'turn_input',
kind: index % 3 === 0 ? 'repl_error' : 'turn_input',
timestamp: 1000 + index,
eventType: 'perception',
sourceType: 'minecraft',
sourceId: index % 2 === 0 ? 'Alex' : 'Steve',
tags: index % 3 === 0 ? ['error', 'planner'] : ['input'],
tags: index % 3 === 0 ? ['error', 'repl'] : ['input'],
text: index % 3 === 0 ? 'Invalid tool parameters' : 'Chat event',
metadata: { i: index },
}))
@@ -1,8 +1,8 @@
export type LlmLogEntryKind
= 'turn_input'
| 'llm_attempt'
| 'planner_result'
| 'planner_error'
| 'repl_result'
| 'repl_error'
| 'scheduler'
| 'feedback'