This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch feat/llmao
in repository https://gitbox.apache.org/repos/asf/sling-tooling-jenkins.git


The following commit(s) were added to refs/heads/feat/llmao by this push:
     new 4247dab  feat: more pi output for understanding/troubleshooting
4247dab is described below

commit 4247dabe88dbc4a8f31655c2ba6ef75201243d8b
Author: Robert Munteanu <[email protected]>
AuthorDate: Wed Oct 14 09:23:53 2026 +0100

    feat: more pi output for understanding/troubleshooting
---
 README.md                                          |  4 +--
 resources/org/apache/sling/jenkins/llmao/run-pi.sh |  3 +-
 .../sling/jenkins/llmao/tool-output-logger.mjs     | 37 +++++++++++++++++++---
 3 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index cb4bf8a..3cd92b8 100644
--- a/README.md
+++ b/README.md
@@ -85,7 +85,7 @@ Provide either an input string or an input file; the library 
has no default task
 
 The library runs [Pi](https://pi.dev) in Docker, configured for LLMAO's 
OpenAI-compatible endpoint at `https://llm.apache.org/v1`, with the selected 
model and temperature `0.0`. Pi can read, search, edit, and write project files 
and run shell commands. Automatic extensions, MCP, automatic project 
instructions, stored sessions, and compaction remain disabled.
 
-A bundled tool-output logger is explicitly loaded. It writes shell commands 
(up to 2,000 characters), shell-result tails (up to 6,000 characters), and 
errors from other tools to stderr in the Jenkins console. It redacts the 
`LLMAO_PAT` value before truncation and does not log successful file reads, 
prompts, or reasoning. It does not alter tool results or the final 
SUCCESS/FAILURE response on stdout.
+A bundled output logger is explicitly loaded. It writes Pi's assistant text, 
model-response stop reasons/errors, agent/request progress, tool starts and 
completion status, and tool-result tails to stderr in the Jenkins console. 
Tool-call summaries include shell commands, paths, and search patterns (up to 
2,000 characters), but not file contents supplied to edit/write tools. 
Assistant text and tool results are limited to their last 6,000 characters; 
successful file/skill-read contents, pr [...]
 
 Pi retries transient provider/network errors, including HTTP 429 rate limits, 
up to 10 times per failed model turn at one-minute intervals. Retries stay in 
the same Pi session, preserving tool history and edits; provider-level retries 
remain disabled. This polls for quota recovery rather than parsing LLMAO's 
custom reset timestamp, and the existing job/process timeouts still apply.
 
@@ -241,4 +241,4 @@ docker build --tag sling-llmao-pi:1.1.0-jdk21-v3 
resources/org/apache/sling/jenk
 python3 tests/pi-docker.py --integration
 ```
 
-The integration test exercises skill discovery/loading, real 
read/edit/write/find/shell tool calls, Java 21 with both Maven commands and the 
absence of older JDKs/wrappers, Maven batch-mode settings, environment-token 
authentication, model selection, tracked/new-file diffs, SUCCESS/FAILURE 
mapping, malformed/empty answers, API errors, multi-turn token/cache totals, 
retries, missing/zero usage, cancellation, and container removal. It uses only 
disposable fixture projects and does not call [...]
+The integration test exercises skill discovery/loading, real 
read/edit/write/find/shell tool calls, assistant/progress/tool console output 
with private read contents, Java 21 with both Maven commands and the absence of 
older JDKs/wrappers, Maven batch-mode settings, environment-token 
authentication, model selection, tracked/new-file diffs, SUCCESS/FAILURE 
mapping, malformed/empty answers, API errors, multi-turn token/cache totals, 
retries, missing/zero usage, cancellation, and container  [...]
diff --git a/resources/org/apache/sling/jenkins/llmao/run-pi.sh 
b/resources/org/apache/sling/jenkins/llmao/run-pi.sh
index ee94cf6..db8a1f4 100644
--- a/resources/org/apache/sling/jenkins/llmao/run-pi.sh
+++ b/resources/org/apache/sling/jenkins/llmao/run-pi.sh
@@ -40,7 +40,8 @@ git -C "$HOME/sling-whiteboard" sparse-checkout set skills >&2
 printf 'Sling skills revision: ' >&2
 git -C "$HOME/sling-whiteboard" rev-parse HEAD >&2
 
-# Print mode emits only the final assistant text to stdout; errors use stderr.
+# Print mode keeps the final assistant text on stdout for the result check.
+# The output logger sends assistant/progress/tool diagnostics to stderr.
 exec timeout --kill-after=5s 1500s pi \
     --provider llmao --model "$LLMAO_MODEL" \
     --print --tools read,bash,edit,write,grep,find,ls --no-session \
diff --git a/resources/org/apache/sling/jenkins/llmao/tool-output-logger.mjs 
b/resources/org/apache/sling/jenkins/llmao/tool-output-logger.mjs
index 0722eb2..743411f 100644
--- a/resources/org/apache/sling/jenkins/llmao/tool-output-logger.mjs
+++ b/resources/org/apache/sling/jenkins/llmao/tool-output-logger.mjs
@@ -18,24 +18,51 @@
  */
 
 export default function toolOutputLogger(pi) {
-    function log(value, limit = 6000) {
+    function log(value, limit = 6000, prefix = 'Pi tool') {
         let text = String(value ?? '');
         const secret = process.env.LLMAO_PAT;
         if (secret) text = text.split(secret).join('[REDACTED]');
         text = text.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
         if (text.length > limit) text = `[...truncated; last ${limit} 
characters...]\n${text.slice(-limit)}`;
-        process.stderr.write(`[Pi tool] ${text}\n`);
+        process.stderr.write(`[${prefix}] ${text}\n`);
     }
 
+    function textBlocks(content) {
+        return (Array.isArray(content) ? content : []).filter(block => 
block?.type === 'text').map(block => block.text).join('\n');
+    }
+
+    function progress(value) {
+        log(value, 6000, 'Pi');
+    }
+
+    pi.on('agent_start', () => { progress('Agent started'); });
+    pi.on('before_provider_request', () => { progress('Requesting the next 
model response'); });
+
+    pi.on('message_end', event => {
+        const message = event.message;
+        if (message?.role !== 'assistant') return;
+        const output = textBlocks(message.content);
+        if (output) progress(`Assistant output:\n${output}`);
+        progress(`Model response ended: ${message.stopReason ?? 'unknown'}`);
+        if (message.errorMessage) progress(message.errorMessage);
+        if (message.stopReason === 'length') progress('Model output was 
truncated. Increase llmaoMaxTokens only if the gateway quota allows it.');
+        // Observe only: do not change the assistant message or print 
reasoning.
+    });
+
+    pi.on('agent_settled', event => { progress(event.aborted ? 'Agent aborted' 
: 'Agent settled'); });
+
     pi.on('tool_call', event => {
         if (event.toolName === 'bash') log(`bash 
command:\n${event.input?.command ?? ''}`, 2000);
+        else log(`${event.toolName}: starting${event.input?.path ? ` 
(${event.input.path})` : ''}${event.input?.pattern ? ` 
pattern=${event.input.pattern}` : ''}`, 2000);
     });
 
     pi.on('tool_result', event => {
-        if (event.toolName !== 'bash' && !event.isError) return;
         log(`${event.toolName}: ${event.isError ? 'ERROR' : 
'OK'}${event.input?.path ? ` (${event.input.path})` : ''}`);
-        const output = (event.content ?? []).filter(block => block.type === 
'text').map(block => block.text).join('\n');
-        if (output) log(output);
+        // Keep successful file/skill reads private, but show other tool 
output.
+        if (event.toolName !== 'read' || event.isError) {
+            const output = textBlocks(event.content);
+            if (output) log(output);
+        }
         // Return nothing: logging must not change the result seen by the 
model.
     });
 }

Reply via email to