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
33 changes: 32 additions & 1 deletion inc/Engine/AI/conversation-loop.php
Original file line number Diff line number Diff line change
Expand Up @@ -1817,7 +1817,8 @@ function datamachine_build_tool_trace( string $tool_name, array $tool_call, arra
if ( strlen( (string) $redacted_arguments_json ) <= 2000 ) {
$trace['arguments_redacted'] = $redacted_arguments;
} else {
$trace['arguments_omitted'] = 'redacted_arguments_too_large';
$trace['arguments_redacted'] = datamachine_bound_tool_trace_value( $redacted_arguments );
$trace['arguments_omitted'] = 'redacted_arguments_too_large';
}

return array_filter(
Expand All @@ -1826,6 +1827,36 @@ function datamachine_build_tool_trace( string $tool_name, array $tool_call, arra
);
}

/**
* Keep non-secret scalar tool arguments visible when full arguments are large.
*
* @param mixed $value Redacted trace value.
* @return mixed Bounded trace value.
*/
function datamachine_bound_tool_trace_value( mixed $value ): mixed {
if ( is_array( $value ) ) {
$bounded = array();
$count = 0;
foreach ( $value as $key => $child ) {
if ( $count >= 20 ) {
$bounded['__truncated__'] = true;
break;
}

$bounded[ $key ] = datamachine_bound_tool_trace_value( $child );
++$count;
}

return $bounded;
}

if ( is_string( $value ) && strlen( $value ) > 240 ) {
return substr( $value, 0, 237 ) . '...';
}

return $value;
}

/** @return array<string,mixed> */
function datamachine_tool_trace_metadata( array $tool_result ): array {
$execution_metadata = is_array( $tool_result['execution_metadata'] ?? null ) ? $tool_result['execution_metadata'] : array();
Expand Down
22 changes: 22 additions & 0 deletions tests/tool-trace-metadata-smoke.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ function assert_tool_trace_metadata( bool $condition, string $message, array &$f
assert_tool_trace_metadata( 'terminal' === $trace['metadata']['runner'], 'trace preserves generic execution metadata', $failures, $passes );
assert_tool_trace_metadata( 'artifacts/stdout.txt' === $trace['artifact_refs']['stdout'], 'trace preserves artifact refs', $failures, $passes );

$large_trace = DataMachine\Engine\AI\datamachine_build_tool_trace(
'manage_github_issue',
array( 'id' => 'call_large' ),
array(
'action' => 'comment',
'repo' => 'owner/repo',
'issue_number' => 123,
'body' => str_repeat( 'Large body. ', 400 ),
),
array( 'success' => false, 'error' => 'GitHub API error (403): Resource not accessible by integration' ),
array(),
1,
1000.0,
1000.1
);

assert_tool_trace_metadata( 'redacted_arguments_too_large' === $large_trace['arguments_omitted'], 'large trace marks omitted full arguments', $failures, $passes );
assert_tool_trace_metadata( 'comment' === $large_trace['arguments_redacted']['action'], 'large trace keeps bounded action argument', $failures, $passes );
assert_tool_trace_metadata( 'owner/repo' === $large_trace['arguments_redacted']['repo'], 'large trace keeps bounded repo argument', $failures, $passes );
assert_tool_trace_metadata( 123 === $large_trace['arguments_redacted']['issue_number'], 'large trace keeps bounded issue number argument', $failures, $passes );
assert_tool_trace_metadata( strlen( $large_trace['arguments_redacted']['body'] ) <= 240, 'large trace truncates long string arguments', $failures, $passes );

$summary = DataMachine\Engine\AI\datamachine_summarize_tool_execution_results(
array(
array(
Expand Down
Loading