diff --git a/.skills/general-prompt-engineer/SKILL.md b/.skills/general-prompt-engineer/SKILL.md new file mode 100644 index 00000000..e904b9d2 --- /dev/null +++ b/.skills/general-prompt-engineer/SKILL.md @@ -0,0 +1,386 @@ +--- +name: general-prompt-engineer +description: create, repair, compress, and optimize prompts, system messages, tool instructions, schemas, and eval rubrics for general tasks across writing, research, coding, analysis, planning, tutoring, automation, and agent workflows. use when the user wants a new prompt, wants an existing prompt improved, wants prompt failures debugged, or needs better structure for grounding, tool use, output format, or reliability. +--- + +# Prompt Engineer + +Build prompts that are clear, compact, reliable, and easy to evaluate. Optimize for modern frontier models, but keep prompts portable across model families unless the user explicitly asks for model-specific tuning. + +## Default workflow + +1. Diagnose the request. +2. Decide whether prompt changes are the real fix. +3. Gather only missing information. +4. Choose the lightest structure that will work. +5. Draft the prompt. +6. Stress-test it mentally. +7. Deliver only what the user asked for. + +### 1) Diagnose the request + +Extract: +- objective +- target actor or model +- required output +- constraints and non-goals +- source material and freshness needs +- tool or schema needs +- likely failure modes +- interaction mode: interactive, one-shot, or automated + +Before rewriting, check whether the problem is actually caused by: +- the wrong model +- weak or excessive tool design +- missing retrieval or grounding +- missing schema or validation +- missing evals +- an overcomplicated workflow + +If prompt changes are not the main lever, say so and adjust the solution. + +### 2) Gather only missing information + +Ask targeted questions only when the answer would materially change the prompt or output. +Usually clarify: +- output shape +- hard constraints +- source of truth +- allowed tools +- audience or tone, if important +- success criteria or examples, if available + +Do not run a long interview. If the user likely wants speed, state a small set of assumptions and proceed. + +### 3) Choose the lightest structure that will work + +Use this ladder: +- Plain prompt: simple tasks with clear outputs +- Labeled sections: tasks with multiple constraints or source material +- Schema-based prompt: machine-validated output or tool calls +- Staged workflow: multi-step transformations, verification, or research synthesis +- Agent prompt: only when autonomy, tools, or long-horizon execution are required +- Multi-agent design: only if evals or clear role separation justify it + +Do not force a giant template onto a small task. + +## Core rules + +### Instruction clarity + +- Put the main task and required output near the top. +- Use direct verbs. +- Say what to do, not only what to avoid. +- Make constraints measurable when possible. +- Name out-of-bounds behavior explicitly. +- Do not make the model infer facts or parameters you already know. +- Remove contradictions before adding more guidance. + +### Context loading discipline + +- Include only context that helps the task. +- Separate stable instructions from variable task data. +- Label documents, examples, and reference material clearly. +- For source-heavy prompts, keep the operative question easy to find. +- For long-document work, anchor important claims to quoted text, citations, or section references when precision matters. +- For very long or noisy documents, consider an evidence-first step: extract the relevant passages first, then synthesize. +- Remove repeated policies, repeated facts, and ornamental prose. +- When a task is dominated by long source material, use strong delimiters and make the final requested action unmistakable. + +### Reasoning control + +- Do not force visible chain-of-thought by default. +- For reasoning-first models, prefer concise high-level guidance such as "reason carefully", "check assumptions", or "verify before answering" rather than "think step by step". +- Ask for visible reasoning only when it serves the task: tutoring, auditability, debugging, derivations, safety review, or explicit rationale requests. +- If one prompt is trying to do too much, split it into stages instead of demanding a long visible reasoning trace. +- If the target model supports extended or internal thinking, rely on that before adding verbose reasoning rituals. + +### Examples + +- Try zero-shot first for strong modern models. +- Add examples only when they reduce ambiguity, enforce style, or demonstrate hard edge cases. +- Keep examples high-quality, diverse, and tightly aligned with the instructions. +- Do not include many examples that teach accidental patterns or waste context. + +### Structure and output design + +- Use plain markdown or labeled sections for most prompts. +- Use XML tags or equivalent delimiters when instructions, context, examples, and documents might otherwise get mixed together. +- Use schemas when the output must be machine-checked. +- For external actions, use tool or function calling; for user-facing structured data, use structured response formats. +- Design schemas so valid failure states, uncertainty, abstention, or partial completion can be represented when needed. +- Do not over-constrain fields beyond what downstream systems actually require. +- Include fallback behavior for incompatible input, missing fields, uncertainty, or refusal states. +- Treat format validation and content validation as separate problems. + +### Tool-use guidance + +- Add tools only when the task truly needs external information, computation, or actions. +- Keep the tool set small, distinct, and easy to choose between. +- State when each tool should be used and when it should not be used. +- Prefer tools that return high-signal results over bulky raw dumps. +- Combine tightly coupled actions when that reduces tool-selection ambiguity. +- For complex tools, clear descriptions and valid examples matter more than more tools. + +### Grounding and hallucination reduction + +- Give the model permission to say "I don't know" or "not enough information". +- Name the allowed sources of truth. +- For document-grounded tasks, require evidence before synthesis when precision matters. +- For fresh, unstable, or high-stakes facts, require browsing or verification. +- Ask the model to separate facts, inferences, and recommendations when confusion is likely. +- In high-stakes domains, unsupported claims should be withheld, not guessed. + +### Ambiguity handling + +- If ambiguity is blocking and the setting is interactive, ask concise high-leverage questions. +- If ambiguity is non-blocking or interaction is costly, state the best assumption and proceed. +- Avoid clarifying questions that do not materially change the answer. +- In one-shot or automated settings, prefer explicit assumptions over stalled execution. + +### Verbosity control + +- Set a default brevity level when length matters. +- Constrain section count, sentence count, or bullet count when needed. +- Ask for direct answers first, then supporting detail if useful. +- Do not require long preambles, summaries, or checklists unless they clearly help. + +### Modularity and portability + +- Keep prompt blocks reusable: role, objective, context, tools, output, quality bar. +- Separate required behavior from optional preferences. +- Avoid vendor-specific magic phrases unless the user wants model-specific tuning. +- If the prompt is model-specific, label which parts are portable and which parts are tuned. + +## Model-family adjustments + +Use this section only when the target model family is known. + +### GPT-5.x and similar reasoning-first models + +- Keep prompts simple and direct. +- Prefer high-level reasoning guidance over narrated reasoning instructions. +- Use delimiters for clarity. +- Start zero-shot, then add examples only if needed. +- Be explicit about output shape, scope, and verbosity. + +### Claude 4.x, Opus-style models, and extended-thinking modes + +- XML-style structure can work especially well for separating instructions, context, examples, and documents. +- Prompt chaining can outperform one giant prompt on multi-step transformations. +- Well-chosen examples can help with format fidelity and edge cases. +- If extended thinking is available, start with broad reasoning instructions before prescribing a detailed step list. +- For long-context analysis, labeled documents and evidence grounding are especially important. + +### API and production settings + +- Prefer native schema enforcement, tool calling, prompt versioning, and evals over prompt-only fixes. +- Pin model versions when behavior stability matters. +- Re-run evals after each meaningful prompt change. + +## Prompt construction pattern + +Use only the blocks that earn their token cost. + +Minimal pattern: + +```text +Task: +Constraints: +Output: +``` + +Structured pattern: + +```xml +... +... +... +... +... +... +... +``` + +Optional blocks: +- `` +- `` +- `` +- `` + +Use a role only when it meaningfully sharpens expertise, tone, or decision criteria. Avoid generic filler roles. + +## Rewrite policy for existing prompts + +When the user provides a prompt to improve: +1. Preserve what already works. +2. Identify contradictions, redundancy, vagueness, missing constraints, and wasted tokens. +3. Make surgical edits first. +4. Rewrite from scratch only if the prompt architecture is fundamentally wrong. +5. Match the user's requested output: + - edited version only + - clean rebuild only + - both, if useful and requested + +## Special-case guidance + +### System and developer prompts + +- Keep stable behavior here and move per-request data to the task or user layer. +- Put precedence, tool boundaries, non-goals, and refusal or escalation rules in the highest-priority layer. +- Do not bury critical rules inside long policy prose. + +### Research prompts + +Specify: +- freshness requirements +- preferred source types +- citation behavior +- contradiction handling +- whether to ask questions or cover likely interpretations +- how facts, inferences, and recommendations should be separated + +### Writing prompts + +Specify: +- audience +- intent +- tone +- length +- must-include points +- style examples only if style fidelity matters + +### Coding prompts + +Specify: +- environment and versions +- boundaries and non-goals +- files, interfaces, or contracts that matter +- acceptance tests +- minimal-change versus refactor expectations + +### Summarization and extraction prompts + +Specify: +- whether faithfulness, compression, or completeness is the priority +- the exact output schema +- how evidence should be anchored for sensitive claims + +### Translation and transformation prompts + +Specify: +- source language and target language, if known +- fidelity versus naturalness +- terminology that must stay fixed +- formatting or markup preservation rules + +### Tutoring prompts + +Specify: +- learner level +- whether to give the answer immediately or guide toward it +- explanation depth +- how to check understanding +- whether to show full derivations, hints, or worked examples + +### Agent and workflow prompts + +Specify: +- objective and success condition +- allowed tools and forbidden actions +- when to plan versus when to act +- stop conditions and max retries +- checkpoint, handoff, or log format +- memory rules: what to preserve versus discard +- fallback or escalation path + +Use multi-agent designs only when roles are truly distinct and the extra coordination cost is justified. + +### Safety-sensitive prompts + +Require: +- supported claims +- explicit uncertainty +- refusal or escalation behavior where appropriate +- no guessing under pressure + +## Stress-test before delivering + +Mentally test the prompt against: +- a normal case +- a minimal-input case +- an edge case +- an ambiguous case +- a formatting case +- a hallucination-prone case + +For agent or workflow prompts, also test: +- wrong-tool temptation +- stale-data temptation +- scope creep +- over-verbosity +- fallback behavior + +If the prompt fails any test, tighten or simplify it. + +## Evaluation method + +When the user wants reliability, add or suggest a lightweight eval plan: +1. Define success criteria. +2. Build a test set from real cases plus edge and adversarial cases. +3. Prefer automated grading when possible. +4. Calibrate automated or model-based judges against a smaller human-reviewed set when stakes are meaningful. +5. Use pairwise comparison, classification, pass-fail, or rubric-based scoring instead of only open-ended judgment. +6. Track regressions after each prompt change. +7. Start simple. Add workflows or multi-agent designs only if evals justify them. + +Good eval sets usually include: +- common real tasks +- boundary cases +- malformed inputs +- conflicting instructions +- long-context cases +- tool-misuse temptations +- safety-sensitive cases +- multilingual or format-variant inputs, if relevant + +## Deliverables + +Return only what the user asked for. By default: +1. the final prompt +2. brief usage notes +3. stated assumptions, if any +4. optional variants only when clearly useful: + - minimal + - robust + - model-specific + - api message split + +If the user asks for one prompt only, do not add extra frameworks or commentary. + +## Anti-patterns + +- forcing chain-of-thought everywhere +- confusing verbosity with quality +- piling on redundant rules +- using brittle giant templates for small tasks +- requiring tools without a real need +- exposing unnecessary internal process in user-facing outputs +- adding examples that conflict with the instructions +- asking many clarifying questions when a sane assumption would do +- treating a model, retrieval, or tool problem as only a prompt problem +- building multi-agent systems before a simpler design has been evaluated +- vague quality bars like "be excellent" without measurable criteria + +## Final quality bar + +A prompt is ready when it is: +- clear about the task +- explicit about success criteria +- free of contradictions +- no more verbose than necessary +- grounded in the right sources +- structured enough for the task, but not heavier than needed +- resilient to likely ambiguity +- matched to the target model and interaction mode +- easy to maintain, test, and adapt \ No newline at end of file diff --git a/MinecraftClient/Commands/Look.cs b/MinecraftClient/Commands/Look.cs index 69f0dc2d..aedc474b 100644 --- a/MinecraftClient/Commands/Look.cs +++ b/MinecraftClient/Commands/Look.cs @@ -92,6 +92,7 @@ namespace MinecraftClient.Commands return r.SetAndReturn(Status.FailNeedTerrain); handler.UpdateLocation(handler.GetCurrentLocation(), direction); + handler.SendLocationUpdate(); return r.SetAndReturn(Status.Done, "Looking " + direction.ToString()); } @@ -102,6 +103,7 @@ namespace MinecraftClient.Commands return r.SetAndReturn(Status.FailNeedTerrain); handler.UpdateLocation(handler.GetCurrentLocation(), yaw, pitch); + handler.SendLocationUpdate(); return r.SetAndReturn(Status.Done, string.Format(Translations.cmd_look_at, yaw.ToString("0.00"), pitch.ToString("0.00"))); } @@ -113,6 +115,7 @@ namespace MinecraftClient.Commands Location current = handler.GetCurrentLocation(); handler.UpdateLocation(current, location); + handler.SendLocationUpdate(); return r.SetAndReturn(Status.Done, string.Format(Translations.cmd_look_block, location)); } } diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index 6370a972..bae74f75 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -1705,6 +1705,26 @@ namespace MinecraftClient changedSlots.Add(new Tuple((short)slotId, null)); } + private static bool IsServerManagedOutputSlot(Container inventory, int slotId) + { + return (inventory.Type, slotId) switch + { + (ContainerType.PlayerInventory, 0) => true, + (ContainerType.Crafting, 0) => true, + (ContainerType.Anvil, 2) => true, + (ContainerType.BlastFurnace, 2) => true, + (ContainerType.Furnace, 2) => true, + (ContainerType.Smoker, 2) => true, + (ContainerType.Grindstone, 2) => true, + (ContainerType.Cartography, 2) => true, + (ContainerType.Merchant, 2) => true, + (ContainerType.Stonecutter, 1) => true, + (ContainerType.Loom, 3) => true, + (ContainerType.SmightingTable, 3) => true, + _ => false + }; + } + /// /// Click a slot in the specified window /// @@ -1731,8 +1751,9 @@ namespace MinecraftClient // Check if cursor have item (slot -1) if (playerInventory.Items.ContainsKey(-1)) { - // When item on cursor and clicking slot 0, nothing will happen - if (slotId == 0) break; + // Result slots are server-managed and cannot accept cursor items directly. + if (IsServerManagedOutputSlot(inventory, slotId)) + break; // Check target slot also have item? if (inventory.Items.ContainsKey(slotId)) @@ -1778,8 +1799,8 @@ namespace MinecraftClient // Check target slot have item? if (inventory.Items.ContainsKey(slotId)) { - // When taking item from slot 0, server will update us - if (slotId == 0) break; + if (IsServerManagedOutputSlot(inventory, slotId)) + break; // Put target slot item to cursor playerInventory.Items[-1] = inventory.Items[slotId]; @@ -1793,8 +1814,8 @@ namespace MinecraftClient // Check if cursor have item (slot -1) if (playerInventory.Items.ContainsKey(-1)) { - // When item on cursor and clicking slot 0, nothing will happen - if (slotId == 0) break; + if (IsServerManagedOutputSlot(inventory, slotId)) + break; // Check target slot have item? if (inventory.Items.ContainsKey(slotId)) @@ -1830,10 +1851,8 @@ namespace MinecraftClient // Check target slot have item? if (inventory.Items.ContainsKey(slotId)) { - if (slotId == 0) + if (IsServerManagedOutputSlot(inventory, slotId)) { - // no matter how many item in slot 0, only 1 will be taken out - // Also server will update us break; } if (inventory.Items[slotId].Count == 1) @@ -1869,7 +1888,8 @@ namespace MinecraftClient break; case WindowActionType.ShiftClick: case WindowActionType.ShiftRightClick: - if (slotId == 0) break; + if (IsServerManagedOutputSlot(inventory, slotId)) + break; if (item is not null) { /* Target slot have item */ @@ -3035,6 +3055,21 @@ namespace MinecraftClient UpdateLocation(location, false); } + /// + /// Send the current player position and look angles to the server. + /// + /// TRUE if the update packet was sent + public bool SendLocationUpdate() + { + if (InvokeRequired) + return InvokeOnMainThread(SendLocationUpdate); + + Location current = GetCurrentLocation(); + bool onGround = physicsInitialized ? playerPhysics.OnGround : Movement.IsOnGround(world, current); + bool horizontalCollision = physicsInitialized && playerPhysics.HorizontalCollision; + return handler.SendLocationUpdate(current, onGround, horizontalCollision, _yaw, _pitch); + } + /// /// Called when the server sends a new player location, /// or if a ChatBot whishes to update the player's location. diff --git a/MinecraftClient/Mcp/MccMcpCapabilities.cs b/MinecraftClient/Mcp/MccMcpCapabilities.cs index 0b600235..60a03f76 100644 --- a/MinecraftClient/Mcp/MccMcpCapabilities.cs +++ b/MinecraftClient/Mcp/MccMcpCapabilities.cs @@ -1347,9 +1347,27 @@ public sealed class MccMcpCapabilities : IMccMcpCapabilities if (!client.GetTerrainEnabled()) return MccMcpResult.Fail("feature_disabled"); - Location target = new(x, y, z); - client.InvokeOnMainThread(() => client.UpdateLocation(client.GetCurrentLocation(), target)); - return MccMcpResult.Ok(); + return client.InvokeOnMainThread(() => + { + Location current = client.GetCurrentLocation(); + Location target = new(x, y, z); + client.UpdateLocation(current, target); + bool success = client.SendLocationUpdate(); + return success + ? MccMcpResult.Ok(new + { + success, + yaw = client.GetYaw(), + pitch = client.GetPitch(), + location = ToCoordinate(current), + target = ToCoordinate(target) + }) + : MccMcpResult.Fail("action_failed", data: new + { + success, + target = ToCoordinate(target) + }); + }); } public MccMcpResult LookDirection(string direction) @@ -1371,12 +1389,20 @@ public sealed class MccMcpCapabilities : IMccMcpCapabilities { Location current = client.GetCurrentLocation(); client.UpdateLocation(current, parsedDirection); - return MccMcpResult.Ok(new + bool success = client.SendLocationUpdate(); + return success + ? MccMcpResult.Ok(new { + success, direction = parsedDirection.ToString(), yaw = client.GetYaw(), pitch = client.GetPitch(), location = ToCoordinate(current) + }) + : MccMcpResult.Fail("action_failed", data: new + { + success, + direction = parsedDirection.ToString() }); }); } @@ -1397,11 +1423,21 @@ public sealed class MccMcpCapabilities : IMccMcpCapabilities { Location current = client.GetCurrentLocation(); client.UpdateLocation(current, yaw, pitch); - return MccMcpResult.Ok(new + bool success = client.SendLocationUpdate(); + return success + ? MccMcpResult.Ok(new { + success, yaw = client.GetYaw(), pitch = client.GetPitch(), location = ToCoordinate(current) + }) + : MccMcpResult.Fail("action_failed", data: new + { + success, + yaw, + pitch, + location = ToCoordinate(current) }); }); } diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 4946277a..3c3c6271 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -1176,6 +1176,7 @@ namespace MinecraftClient.Scripting protected void LookAtLocation(Location location) { Handler.UpdateLocation(Handler.GetCurrentLocation(), location); + Handler.SendLocationUpdate(); } /// @@ -1186,6 +1187,7 @@ namespace MinecraftClient.Scripting protected void LookAtLocation(float yaw, float pitch) { Handler.UpdateLocation(Handler.GetCurrentLocation(), yaw, pitch); + Handler.SendLocationUpdate(); } /// diff --git a/MinecraftClient/Scripting/MccGameApi.cs b/MinecraftClient/Scripting/MccGameApi.cs index b708f842..391ece50 100644 --- a/MinecraftClient/Scripting/MccGameApi.cs +++ b/MinecraftClient/Scripting/MccGameApi.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using System.Threading.Tasks; using MinecraftClient.Inventory; using MinecraftClient.Mapping; using MinecraftClient.Protocol; @@ -629,6 +630,8 @@ public sealed class MccGameApi /// /// Move to a tracked player by name and verify arrival. + /// Callers running on ChatBot update callbacks should prefer + /// so the main MCC updater thread is not blocked while pathfinding completes. /// public MccGameResult MoveToPlayer(string playerName, bool allowUnsafe = false, bool allowDirectTeleport = false, int maxOffset = 0, int minOffset = 0, int timeoutMs = 0) { @@ -698,6 +701,14 @@ public sealed class MccGameApi : MccGameResult.Fail("action_incomplete", data: resultData); } + /// + /// Run on a worker thread so ChatBot callbacks can poll the result without blocking MCC updates. + /// + public Task> MoveToPlayerAsync(string playerName, bool allowUnsafe = false, bool allowDirectTeleport = false, int maxOffset = 0, int minOffset = 0, int timeoutMs = 0) + { + return Task.Run(() => MoveToPlayer(playerName, allowUnsafe, allowDirectTeleport, maxOffset, minOffset, timeoutMs)); + } + /// /// Select a hotbar item by item type without moving items around. /// @@ -953,6 +964,8 @@ public sealed class MccGameApi /// /// Move to nearby dropped items and verify pickup completion. + /// Callers running on ChatBot update callbacks should prefer + /// so the main MCC updater thread is not blocked while movement and pickup verification complete. /// public MccGameResult PickupItems(string itemType, double radius = 16, int maxItems = 10, bool allowUnsafe = false, int timeoutMs = 0) { @@ -1039,6 +1052,14 @@ public sealed class MccGameApi : MccGameResult.Fail("action_incomplete", data: resultData); } + /// + /// Run on a worker thread so ChatBot callbacks can poll the result without blocking MCC updates. + /// + public Task> PickupItemsAsync(string itemType, double radius = 16, int maxItems = 10, bool allowUnsafe = false, int timeoutMs = 0) + { + return Task.Run(() => PickupItems(itemType, radius, maxItems, allowUnsafe, timeoutMs)); + } + private static MccGameResult NotConnected() { return MccGameResult.Fail("disconnected");