| @@ -380,12 +380,17 @@ | ||
| 380 | 380 | if ( empty( $params['name'] ) || ! str_contains( $params['code'], $params['name'] ) ) { |
| 381 | 381 | throw new Exception( "Code Engine: Function name does not match. The name should be {$params['name']}." ); |
| 382 | 382 | } |
| 383 | 383 | |
| 384 | - // Overwrite the default values with the provided ones | |
| 384 | + // Collect the provided values, keyed by their normalized (dollar-less) name. | |
| 385 | + // Incoming keys come from the AI/MCP schema, where register_function_tools() | |
| 386 | + // strips a leading "$" from the declared name. The stored arg names can still | |
| 387 | + // carry the "$", so we normalize both sides before matching below. Without this | |
| 388 | + // a value provided as "style" never binds to an argument declared "$style". | |
| 389 | + $provided = []; | |
| 385 | 390 | if ( $args ) { |
| 386 | 391 | foreach ( $args as $name => $value ) { |
| 387 | - $params['values'][$name]['input'] = $value; | |
| 392 | + $provided[ ltrim( $name, '$' ) ] = $value; | |
| 388 | 393 | } |
| 389 | 394 | |
| 390 | 395 | $this->log( '⚡ Arguments provided: ' . json_encode( $args ) ); |
| 391 | 396 | } |
| @@ -425,15 +430,16 @@ | ||
| 425 | 430 | // ("syntax error, unexpected token ')'"). call_user_func_array passes them as |
| 426 | 431 | // data, so no value can ever corrupt the call syntax. |
| 427 | 432 | $callArgs = []; |
| 428 | 433 | foreach ( $params['args'] as $arg ) { |
| 434 | + $key = ltrim( $arg, '$' ); // Match the normalized name the caller sent. | |
| 429 | 435 | $value = null; // Not provided and no default -> null. |
| 430 | - if ( array_key_exists( $arg, $params['values'] ) ) { | |
| 431 | - if ( !empty( $params['values'][$arg]['input'] ) ) { | |
| 432 | - $value = $params['values'][$arg]['input']; | |
| 433 | - } else if ( !empty( $params['values'][$arg]['default'] ) ) { | |
| 434 | - $value = $params['values'][$arg]['default']; | |
| 435 | - } | |
| 436 | + // array_key_exists, not !empty: a legitimately provided 0, "0", "" or false | |
| 437 | + // must reach the function instead of silently falling back to the default. | |
| 438 | + if ( array_key_exists( $key, $provided ) ) { | |
| 439 | + $value = $provided[ $key ]; | |
| 440 | + } else if ( isset( $params['values'][$arg]['default'] ) && $params['values'][$arg]['default'] !== '' ) { | |
| 441 | + $value = $params['values'][$arg]['default']; | |
| 436 | 442 | } |
| 437 | 443 | // An array-typed argument can arrive as a string like "[1, 2, 3]"; turn it |
| 438 | 444 | // into a real array so the function receives what its signature expects. |
| 439 | 445 | if ( ( $params['values'][$arg]['type'] ?? null ) === 'array' && is_string( $value ) ) { |