diff --git a/src/agent/index.ts b/src/agent/index.ts index de3be39..c23f028 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -2038,9 +2038,10 @@ const executeJavascriptTool = defineTool("execute_javascript", { result: `Result saved to ${relativePath} (${(fullResultBytes / 1024).toFixed(1)} KB).\n` + `Preview (first 500 chars):\n${preview}\n\n` + - `Use read_output("${relativePath}") to read the full result.\n` + - `Use read_output("${relativePath}", startLine, endLine) for specific sections.\n` + - `You can also read this file from handler code via host:fs-read.`, + `IMPORTANT: Read the full output by writing a handler that reads "${relativePath}" via host:fs-read.\n` + + `Process the data in handler code — do NOT summarize or propose changes based only on the preview.\n` + + `Only use read_output("${relativePath}") directly if you need a quick look at a specific section;\n` + + `read_output("${relativePath}", startLine, endLine) supports line ranges.`, ...(consoleOutput?.length ? { consoleOutput } : {}), _resourceStats: resourceStats, _stats: stats ?? undefined, @@ -2898,7 +2899,7 @@ const HELP_TOPICS: Record = { "- YOU orchestrate: pass handler A's result as handler B's event", "", "HANDLER CODE STYLE:", - "- Every handler must define function handler(event) or async function handler(event)", + "- Every handler must define function handler(...) or async function handler(...)", "- The function name is mandatory; parameter names are flexible, and zero parameters are allowed", "- Module-level state persists across execute_javascript calls", "", diff --git a/src/code-validator/guest/runtime/src/validator.rs b/src/code-validator/guest/runtime/src/validator.rs index a279e6b..7ec4a27 100644 --- a/src/code-validator/guest/runtime/src/validator.rs +++ b/src/code-validator/guest/runtime/src/validator.rs @@ -1003,7 +1003,12 @@ fn check_handler_function(source: &str) -> bool { } /// Diagnose handler declarations that look close but are not the required shape. +/// If a valid `function handler` already exists at the top level, skip the +/// misnamed-function check so nested helpers (e.g. `function process(...)`) are +/// not flagged as errors. fn check_handler_signature_issue(source: &str) -> Option<(String, Option)> { + let has_valid_handler = check_handler_function(source); + for (line_index, line) in source.lines().enumerate() { let trimmed = line.trim(); let line_number = Some((line_index + 1) as u32); @@ -1052,7 +1057,9 @@ fn check_handler_signature_issue(source: &str) -> Option<(String, Option)> let name = &rest[..name_end]; if name == "handler" { continue; - } else if matches!(name, "Handler" | "handle" | "main" | "run" | "process") { + } else if !has_valid_handler + && matches!(name, "Handler" | "handle" | "main" | "run" | "process") + { return Some(( alloc::format!( "Handler function must be named exactly 'handler'. Found function '{}'. Fix: rename it to function handler(event) {{ ... return result; }}.", @@ -1101,8 +1108,11 @@ fn check_handler_has_return(source: &str) -> bool { } } b'f' => { - // Skip nested function and function* declarations + // Skip nested function declarations, generators, and + // anonymous function expressions (function(...) { ... }) if (rest[i..].starts_with("function ") + || rest[i..].starts_with("function(") + || rest[i..].starts_with("function*(") || rest[i..].starts_with("function*")) && let Some(after_nested) = skip_nested_block(rest, i) {