mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-02 21:03:34 +03:00
fix create tool in the AI chat (#6673)
AI PDF creation ("create a PDF for me") has been broken since the
Policies backend (#6527) introduced PolicyExecutor as the tool execution
pipeline. PolicyExecutor runs normal single-input tools with a per-file
loop, but generator tools like `create-pdf-from-html-agent` take no
input file and build their output purely from parameters. With zero
input files the loop ran zero times, so the endpoint was never called
and the step silently produced nothing. The chat reported success
("Created Purchase Order") while no document ever appeared.
This adds an `else if (inputFiles.isEmpty())` branch so a generator tool
is called once with an empty file list, matching what the multi-input
branch already does for an empty input. Two files changed: the
one-line-ish fix in `PolicyExecutor`, and a regression test covering the
no-input case.
---------
Co-authored-by: James Brunton <jbrunton96@gmail.com>
This commit is contained in:
co-authored by
James Brunton
parent
3870ac3d7d
commit
1a770af47c
+4
@@ -116,6 +116,10 @@ public class PolicyExecutor {
|
||||
ToolResult r = callEndpoint(step, inputFiles, supportingFiles);
|
||||
files.addAll(r.files());
|
||||
report = r.report();
|
||||
} else if (inputFiles.isEmpty()) {
|
||||
ToolResult r = callEndpoint(step, List.of(), supportingFiles);
|
||||
files.addAll(r.files());
|
||||
report = r.report();
|
||||
} else {
|
||||
for (Resource file : inputFiles) {
|
||||
ToolResult r = callEndpoint(step, List.of(file), supportingFiles);
|
||||
|
||||
+35
@@ -2,6 +2,7 @@ package stirling.software.proprietary.policy.engine;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -149,6 +150,40 @@ class PolicyExecutorTest {
|
||||
verify(internalApiClient, times(2)).post(eq(ROTATE), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void noInputGeneratorEndpointIsCalledOnceWithNoFile() throws IOException {
|
||||
// A "create" workflow has no source documents: a generator tool (e.g.
|
||||
// create-pdf-from-html-agent) produces its output purely from parameters. Per-file
|
||||
// dispatch would skip it entirely (zero files = zero calls), so it must still run once.
|
||||
String createPdf = "/api/v1/ai/tools/create-pdf-from-html-agent";
|
||||
when(toolMetadataService.isMultiInput(createPdf)).thenReturn(false);
|
||||
when(toolMetadataService.shouldUnpackZipResponse(createPdf)).thenReturn(false);
|
||||
stubEndpoint(createPdf, pdf("generated", "purchase-order.pdf"));
|
||||
|
||||
PolicyExecutionResult result =
|
||||
executor.execute(
|
||||
definition(
|
||||
new PipelineStep(
|
||||
createPdf,
|
||||
Map.of(
|
||||
"htmlContent",
|
||||
"<p>hi</p>",
|
||||
"filename",
|
||||
"purchase-order.pdf"))),
|
||||
PolicyInputs.of(List.of()),
|
||||
PolicyProgressListener.NOOP);
|
||||
|
||||
assertEquals(1, result.files().size());
|
||||
assertEquals("purchase-order.pdf", result.files().get(0).getFilename());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<MultiValueMap<String, Object>> bodyCaptor =
|
||||
ArgumentCaptor.forClass(MultiValueMap.class);
|
||||
verify(internalApiClient, times(1)).post(eq(createPdf), bodyCaptor.capture());
|
||||
// No document stream: the body carries only the generator's parameters, no fileInput.
|
||||
assertNull(bodyCaptor.getValue().get("fileInput"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void zipResponseIsUnpackedIntoIndividualFiles() throws IOException {
|
||||
when(toolMetadataService.isMultiInput(SPLIT)).thenReturn(false);
|
||||
|
||||
Reference in New Issue
Block a user