Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1292,8 +1292,11 @@ const registerHandlerTool = defineTool("register_handler", {
"Register (or update) a named JavaScript handler in the sandbox.",
"The code is compiled but NOT executed — call execute_javascript to run it.",
"",
"REQUIRED: Code must define `function handler(event) { ... return result; }`",
"REQUIRED: Code must define `function handler(...) { ... return result; }`",
"Use `async function handler(...)` only when the handler contains await.",
"The function MUST be named exactly 'handler' — not Handler, handle, main.",
"The parameter name is flexible; use 'event' by convention, or omit it if unused.",
"Do NOT use arrow handlers such as `const handler = (event) => { ... }`.",
"",
"⚠️ TO UPDATE EXISTING CODE: Use get_handler_source first!",
"When fixing errors, call get_handler_source(name) to get current code,",
Expand Down Expand Up @@ -1332,8 +1335,9 @@ const registerHandlerTool = defineTool("register_handler", {
code: {
type: "string",
description:
"JavaScript source code. Simple mode: use `return` for output. " +
"Module mode: define `function handler(event) { ... }`.",
"JavaScript source code. Define `function handler(event) { ... return result; }`, " +
"`function handler() { ... return result; }` if no input is needed, " +
"or `async function handler(event) { ... return result; }` if using await.",
},
},
required: ["name", "code"],
Expand Down Expand Up @@ -2893,9 +2897,10 @@ const HELP_TOPICS: Record<string, string> = {
"- Handlers CANNOT call other handlers — they are isolated modules",
"- YOU orchestrate: pass handler A's result as handler B's event",
"",
"TWO CODE STYLES (auto-detected):",
"- Simple: no 'function handler' → wrapped as function body, locals reset each call",
"- Module: defines 'function handler(event)' → module-level state persists",
"HANDLER CODE STYLE:",
"- Every handler must define function handler(event) or async function handler(event)",
"- The function name is mandatory; parameter names are flexible, and zero parameters are allowed",
"- Module-level state persists across execute_javascript calls",
"",
"COMMON MISTAKES:",
"- Function must be named exactly 'handler' (not Handler, handle, main)",
Expand Down Expand Up @@ -2949,7 +2954,7 @@ const HELP_TOPICS: Record<string, string> = {
debugging: [
"DEBUGGING TIPS:",
"- 'not a function' = you guessed a method name. Call module_info/plugin_info to verify.",
"- register_handler returns codeSize and mode (module/simple) — check these",
"- register_handler returns codeSize and mode — check these",
"- If handler errors, try a minimal version first",
"- Build up complexity gradually — add one feature at a time",
"- Use try/catch inside handlers to catch runtime errors cleanly",
Expand Down
15 changes: 12 additions & 3 deletions src/agent/system-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,15 @@ EVERYTHING goes through sandbox tools — register_handler, execute_javascript,
║ MANDATORY HANDLER FORMAT — YOUR CODE WILL BE REJECTED WITHOUT THIS ║
╚══════════════════════════════════════════════════════════════════════╝

Every register_handler call MUST define: function handler(event) { ... return result; }
Every register_handler call MUST define a real handler function with one of these signatures:
function handler(event) { ... return result; }
function handler() { ... return result; } // when no input is needed
async function handler(event) { ... return result; } // only when using await

The function MUST be named exactly "handler". Not Handler, handle, main, run, process.
Code without "function handler" is ALWAYS rejected by the validator.
The parameter name is flexible; examples use "event" because execute_javascript passes JSON event data.
Handlers that do not need input may omit the parameter: function handler() { ... }.
Comment thread
simongdavies marked this conversation as resolved.
Code without "function handler" or "async function handler" is ALWAYS rejected by the validator.

TEMPLATE — copy this structure every time:
import * as pptx from "ha:pptx"; // imports at top
Expand All @@ -54,7 +60,10 @@ TEMPLATE — copy this structure every time:
}

RULES:
- function handler(event) — EXACTLY this signature, no exceptions
- Use function handler(event) for normal code
- Use async function handler(event) only if the handler contains await
- Do NOT use arrow handlers: const handler = (event) => { ... } is rejected
- Parameter names are flexible: event, input, data, args, or no parameter are all allowed
- MUST return a value — handler without return = runtime error
- event is JSON in, return value is JSON out
- One-shot: runs once, returns, done
Expand Down
Loading
Loading