### Performance Optimization Commands Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Commands for optimizing build performance. These include compiling specific modules or the entire project, assembling without tests, and leveraging configuration caching. ```bash ./gradlew :app:classes ``` ```bash ./gradlew :joern-analyzers:classes ``` ```bash ./gradlew classes ``` ```bash ./gradlew assemble ``` -------------------------------- ### Version Information and Release Process Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Commands and Git operations for managing project versioning. Includes printing the version, tagging commits, pushing tags, and updating the JBang catalog. ```bash ./gradlew printVersion ``` ```git git tag v0.13.0 ``` ```git git push origin v0.13.0 ``` ```bash ./scripts/update-jbang-catalog.sh ./scripts/update-jbang-catalog.sh v0.13.0 ``` ```git git add jbang-catalog.json git commit -m "Update JBang catalog for release v0.13.0" git push ``` -------------------------------- ### Icon Browser and Usage Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Commands to launch the GUI or console version of the Icon Browser for exploring Look and Feel icons. Also shows how to safely load icons using SwingUtil. ```bash ./gradlew run --args="io.github.jbellis.brokk.gui.SwingIconUtil icons" ``` ```bash ./gradlew run --args="io.github.jbellis.brokk.gui.SwingIconUtil" ``` ```java SwingUtil.uiIcon("IconName") ``` -------------------------------- ### Essential Gradle Tasks Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Common Gradle tasks for developers to build, clean, and run the project. These commands cover full builds, incremental compilation, and artifact generation. ```gradle ./gradlew run ./gradlew build ./gradlew assemble ./gradlew clean ./gradlew classes ./gradlew shadowJar ``` -------------------------------- ### JAR Creation Commands Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Commands related to JAR file creation. Development builds skip JARs for speed. 'shadowJar' explicitly creates JARs, while CI builds and builds with '-PenableShadowJar' include them. ```bash ./gradlew shadowJar ``` ```bash CI=true ./gradlew build ``` ```bash ./gradlew -PenableShadowJar build ``` -------------------------------- ### Testing Gradle Tasks Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Gradle commands for executing tests across the entire project or within specific modules. Includes options for running subsets of tests based on patterns. ```gradle ./gradlew test ./gradlew check ./gradlew :analyzer-api:test ./gradlew :app:test ./gradlew :joern-analyzers:test ./gradlew test --tests "*AnalyzerTest" ./gradlew test --tests ".*EditBlockTest" ./gradlew test --tests "*EditBlock*" ./gradlew test --tests "io.github.jbellis.brokk.git.*" ./gradlew test --tests "*TypescriptAnalyzerTest" ./gradlew :analyzer-api:test --tests "*Analyzer*" ./gradlew :app:test --tests "*GitRepo*" ./gradlew :joern-analyzers:test --tests "*Analyzer*" ``` -------------------------------- ### Individual Project Gradle Tasks Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Specific Gradle tasks for compiling and assembling individual modules within the Brokkai Brokk project. This allows for targeted development and build processes. ```gradle ./gradlew :analyzer-api:compileJava ./gradlew :app:compileJava ./gradlew :joern-analyzers:compileScala ./gradlew :analyzer-api:classes ./gradlew :app:classes ./gradlew :joern-analyzers:classes ./gradlew :analyzer-api:assemble ./gradlew :app:assemble ./gradlew :joern-analyzers:assemble ``` -------------------------------- ### Gradle Caching and Management Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Commands for managing Gradle caches and daemons. 'clean' clears build outputs, '--stop' halts the daemon, and manual clearing of '~/.gradle/caches/' is also an option. ```bash ./gradlew clean ``` ```bash ./gradlew --stop ``` ```bash rm -rf ~/.gradle/caches/ ``` -------------------------------- ### Static Analysis Tools Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Information on static analysis tools used in the project. ErrorProne is configured for Java modules (analyzer-api, app) with custom checks, while NullAway focuses on null safety in the app module. ```APIDOC ErrorProne: Description: Custom checks enabled in build.gradle.kts for enhanced error detection. Scope: Applied to analyzer-api and app modules (Java code only). NullAway: Description: Null safety analysis to prevent NullPointerExceptions, configured with project-specific rules. Scope: Applied to app module only. ``` -------------------------------- ### Scala Code Formatting Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Commands to format Scala code using scalafmt. The first command formats code within the joern-analyzers module, while the second formats all Scala code in the project. ```bash ./gradlew :joern-analyzers:scalafmt ``` ```bash ./gradlew scalafmt ``` -------------------------------- ### Gradle Dependency Analysis Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Commands for managing and analyzing project dependencies using the Gradle Dependency Analysis plugin. 'buildHealth' provides a comprehensive analysis, while 'dependencies' shows the dependency tree. ```bash ./gradlew buildHealth ``` ```bash ./gradlew dependencies ``` -------------------------------- ### Configure Vite Dev Server to Open dev.html Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This snippet shows how to configure Vite's development server to automatically open 'dev.html' upon starting the dev server. It demonstrates two methods: modifying the vite.config.mjs file or updating the npm script. Both methods keep the production build logic intact and allow access to index.html if needed. ```javascript import { defineConfig } from 'vite' import { svelte } from '@sveltejs/vite-plugin-svelte' export default defineConfig(({ command }) => ({ plugins: [svelte()], build: { outDir: '../src/main/resources/mop-web', emptyOutDir: true }, // Only for `vite dev` server server: { port: 5173, // Open /dev.html instead of / open: command === 'serve' ? '/dev.html' : undefined } })) ``` ```json "scripts": { "dev": "vite --port 5173 --open /dev.html", ... } ``` -------------------------------- ### Handling Blocking Calls Safely Source: https://github.com/brokkai/brokk/blob/master/app/src/main/interruptions.md Provides an example of using a non-interrupting alternative for blocking calls when the calling thread should not be interrupted or when a generic interruption handler is in place. ```java IAnalyzer analyzer = getAnalyzerUninterrupted(); ``` -------------------------------- ### Test Reporting Locations Source: https://github.com/brokkai/brokk/blob/master/app/src/main/development.md Locations for generated test reports within the Gradle build output. These reports provide detailed results of test executions for each module and the project as a whole. ```text build/reports/tests/test/index.html analyzer-api/build/reports/tests/test/index.html app/build/reports/tests/test/index.html joern-analyzers/build/reports/tests/test/index.html ``` -------------------------------- ### SearchAgent Interruption Handling Source: https://github.com/brokkai/brokk/blob/master/app/src/main/interruptions.md The `SearchAgent` checks for interruptions using `Thread.interrupted()` at the start of its loop. In interactive mode, the first interruption triggers 'Beast Mode' for a final answer, while subsequent interruptions or any interruption in non-interactive mode throws `InterruptedException`. ```java public void execute(...) throws InterruptedException { while (Thread.interrupted()) { // Checks and clears interrupt status // ... perform search actions ... try { determineNextActions(...); executeToolCalls(...); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Re-interrupt throw e; } } } ``` -------------------------------- ### LiteLLM Model Configuration for Brokk Source: https://github.com/brokkai/brokk/blob/master/docs/litellm.md This section details the model configuration requirements for Brokk when using LiteLLM. It specifies the need for 'gemini-2.0-flash' and 'gemini-2.0-flash-lite' models, which Brokk hardcodes for system tasks. It also lists additional configuration keys that Brokk supplements to LiteLLM's model_info. ```APIDOC Model Naming Requirements: - gemini-2.0-flash: Required for system tasks. - gemini-2.0-flash-lite: Required for system tasks. Brokk's Supplemental Model Info Keys: - free_tier_eligible: boolean (defaults to false) - is_private: boolean (defaults to false) - supports_reasoning_disable: boolean (defaults to false) - concurrent_requests: integer (defaults to null) - tokens_per_minute: integer (defaults to null) Upgrade Agent Configuration: - One of {concurrent_requests, tokens_per_minute} must be set to use Upgrade Agent with the model. ``` -------------------------------- ### Running LiteLLM Locally with Docker Source: https://github.com/brokkai/brokk/blob/master/docs/litellm.md This snippet provides the Docker commands to pull the LiteLLM image and run it with a local configuration file and environment variables for API keys. It maps a local config file to the container and exposes port 4000. ```bash docker pull ghcr.io/berriai/litellm:main-latest docker run -v $(pwd)/docs/litellm_config.yaml:/app/config.yaml -e OPENAI_API_KEY=XXX -e ANTHROPIC_API_KEY=XXY -e DEEPSEEK_API_KEY=XYY -e GEMINI_API_KEY=YYY -e GROK_API_KEY=YYZ -p 4000:4000 ghcr.io/berriai/litellm:main-latest --config /app/config.yaml ``` -------------------------------- ### Brokk MOP Initialization with Proxy Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/index.html This JavaScript code snippet initializes the Brokk MOP. It creates a global `window.brokk` object using a Proxy. This proxy intercepts all property accesses, buffering calls and events into a sequence-ordered array. It's designed to handle early calls from Java before the main application logic is ready. ```javascript function() { const buffer = []; // Unified buffer for all calls and events let seq = 0; // Sequence number to maintain order window.brokk = new Proxy({ _buffer: buffer }, { get(target, prop) { // Allow direct access to internal buffer if (prop === '_buffer') { return target[prop]; } // Return a stub function for any other property access return (...args) => { if (prop === 'onEvent') { console.log('Buffering early event from Java:', JSON.stringify(args)); buffer.push({ type: 'event', payload: args[0], seq: seq++ }); } else if (prop === 'hideSpinner') { console.log('Buffering early call from Java to', prop); buffer.push({ type: 'call', method: prop, args: [], seq: seq++ }); } else { console.log('Buffering early call from Java to', prop); buffer.push({ type: 'call', method: prop, args: args, seq: seq++ }); } // Provide default return values for synchronous methods if (prop === 'getSelection') { return ''; } return undefined; }; } }); })(); ``` -------------------------------- ### RSyntaxTextArea and AutoComplete License Source: https://github.com/brokkai/brokk/blob/master/NOTICE.txt This section outlines the BSD-style license for RSyntaxTextArea and AutoComplete by Robert Futrell, used within the Brokk project. It permits redistribution and use in source and binary forms with specific conditions. ```License Copyright (c) 2021, Robert Futrell All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` -------------------------------- ### C# Person Class and Main Method Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html Defines a C# `Person` class with `Name` and `Age` properties and a `Greet` method. The `Program` class demonstrates creating a `Person` object and calling its `Greet` method. ```csharp using System; public class Person { public string Name { get; } public int Age { get; } public Person(string name, int age) { Name = name ?? throw new ArgumentNullException(nameof(name)); Age = age; } public void Greet() { Console.WriteLine($"Hello, my name is {Name} and I'm {Age} years old."); } } class Program { static void Main() { var person = new Person("Alice", 30); person.Greet(); } } ``` -------------------------------- ### Brokk Gradle Build Commands Source: https://github.com/brokkai/brokk/blob/master/README.md Common Gradle commands for building and managing the Brokk project. Requires JDK 21 or newer. ```Shell ./gradlew run ./gradlew clean ./gradlew test ./gradlew build ./gradlew shadowJar ``` -------------------------------- ### Brokk MOP Initialization and Proxy Source: https://github.com/brokkai/brokk/blob/master/app/src/main/resources/mop-web/index.html Initializes the Brokk MOP by creating a proxy that intercepts and buffers all early calls and events from Java. It maintains a sequence number to ensure ordered processing. ```javascript function() { const buffer = []; // Unified buffer for all calls and events let seq = 0; // Sequence number to maintain order window.brokk = new Proxy({ _buffer: buffer }, { get(target, prop) { // Allow direct access to internal buffer if (prop === '_buffer') { return target[prop]; } // Return a stub function for any other property access return (...args) => { if (prop === 'onEvent') { console.log('Buffering early event from Java:', JSON.stringify(args)); buffer.push({ type: 'event', payload: args[0], seq: seq++ }); } else if (prop === 'hideSpinner') { console.log('Buffering early call from Java to', prop); buffer.push({ type: 'call', method: prop, args: [], seq: seq++ }); } else { console.log('Buffering early call from Java to', prop); buffer.push({ type: 'call', method: prop, args: args, seq: seq++ }); } // Provide default return values for synchronous methods if (prop === 'getSelection') { return ''; } return undefined; }; } }); })(); ``` -------------------------------- ### Update UI with Search Results and Column Fitting Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This snippet updates the UI with search results, populating the commits table and fitting column widths. It selects the first commit if available. If no commits are found, it resets the changes tree and revision information and outputs a 'not found' message. ```java SwingUtilities.invokeLater(() -> { commitsTableModel.setRowCount(0); changesRootNode.removeAllChildren(); changesTreeModel.reload(); if (commitRows.isEmpty()) { revisionTextLabel.setText("Revision:"); revisionIdTextArea.setText("N/A"); chrome.systemOutput("No commits found matching: " + query); return; } for (Object[] rowData : commitRows) { commitsTableModel.addRow(rowData); } chrome.systemOutput("Found " + commitRows.size() + " commits matching: " + query); if (commitsTableModel.getRowCount() > 0) { // Fit column widths TableUtils.fitColumnWidth(commitsTable, 1); // Author TableUtils.fitColumnWidth(commitsTable, 2); // Date commitsTable.setRowSelectionInterval(0, 0); // Listener will handle updates to revision display and changes tree } else { // Ensure changes area and revision display are cleared if no search results changesRootNode.removeAllChildren(); changesTreeModel.reload(); revisionTextLabel.setText("Revision:"); revisionIdTextArea.setText("N/A"); } }); ``` -------------------------------- ### Brokk JavaScript API Implementation Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This snippet defines the core Brokk JavaScript object, which acts as an interface to a Java bridge. It includes methods for handling events, managing user selection, clearing content, setting themes, and displaying spinners. It also handles the replaying of buffered events and method calls that occurred before the main Brokk object was fully initialized. ```javascript const bufferedEvents = window.brokk._eventBuffer || []; window.brokk = { _callQueue: [], _eventBuffer: [], onEvent: (payload) => { console.log('Received event from Java bridge:', JSON.stringify(payload)); eventStore.set(payload); if (payload.epoch) { requestAnimationFrame(() => { if (window.javaBridge) { window.javaBridge.onAck(payload.epoch); } }); } }, getSelection: () => { return window.getSelection()?.toString() ?? ''; }, clear: () => { eventStore.set({ type: 'chunk', text: '', isNew: true, msgType: 'SYSTEM', epoch: 0 }); }, setTheme: (dark) => { themeStore.set(dark); if (dark) { document.body.classList.add('theme-dark'); } else { document.body.classList.remove('theme-dark'); } }, showSpinner: (message) => { spinnerStore.set(message); } }; if (bufferedEvents.length > 0) { console.log('Replaying', bufferedEvents.length, 'buffered events'); bufferedEvents.forEach(event => { window.brokk.onEvent(event); }); } if (pendingCalls.length > 0) { console.log('Replaying', pendingCalls.length, 'buffered method calls'); pendingCalls.forEach(({ method, args }) => { console.log('Replaying call to', method, 'with args:', args); const brokk = window.brokk as Record unknown>; if (typeof brokk[method] === 'function') { brokk[method](...args); } else { console.warn('Method', method, 'no longer exists; skipping replay'); } }); } ``` ```javascript const buffer = window.brokk._buffer || []; window.brokk = { _buffer: [], onEvent: (payload) => { console.log('Received event from Java bridge:', JSON.stringify(payload)); eventStore.set(payload); if (payload.epoch) { requestAnimationFrame(() => { if (window.javaBridge) { window.javaBridge.onAck(payload.epoch); } }); } }, getSelection: () => { return window.getSelection()?.toString() ?? ''; }, clear: () => { eventStore.set({ type: 'chunk', text: '', isNew: true, msgType: 'SYSTEM', epoch: 0 }); }, setTheme: (dark) => { themeStore.set(dark); if (dark) { document.body.classList.add('theme-dark'); } else { document.body.classList.remove('theme-dark'); } }, showSpinner: (message) => { spinnerStore.set(message); } }; if (buffer.length > 0) { console.log('Replaying', buffer.length, 'buffered items'); buffer.sort((a, b) => a.seq - b.seq).forEach(item => { if (item.type === 'event') { console.log('Replaying event with epoch:', item.payload.epoch); window.brokk.onEvent(item.payload); } else { console.log('Replaying call to', item.method, 'with args:', item.args); const brokk = window.brokk as Record unknown>; if (typeof brokk[item.method] === 'function') { brokk[item.method](...item.args); } else { console.warn('Method', item.method, 'no longer exists; skipping replay'); } } }); } ``` -------------------------------- ### JavaScript Simulate Event and Show Edit MD Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This JavaScript code snippet defines functions to simulate events and display markdown content. `showEditMd` simulates 'chunk' events with user and AI content, followed by a custom message. `streamEdit` is a placeholder for editing functionality. ```javascript function showEditMd() { simulateEvent('chunk', {text: contentUser, msgType: 'USER', streaming: false}) simulateEvent('chunk', {text: ai, msgType: 'AI', streaming: false}) simulateEvent('chunk', {text: "# Now we are finished!", msgType: 'CUSTOM', streaming: false}) } function streamEdit() { const contentUser = `fix it`; const contentAi = `I understand the issue with the ordering of buffered events and calls in the JavaScript code, which causes the UI to sometimes clear at the end due to incorrect replay order. The problem stems from having two separate buffers (\`_callQueue\` and \`_eventBuffer\`) and replaying them in the wrong order. I'll fix this by unifying the buffer into a single queue with a sequence number to maintain the correct order of operations during replay. Here's the plan: 1. Modify the temporary stub in \`index.html\` to use a single buffer with a sequence number. 2. Update the replay logic in \`index.ts\` to process this unified buffer in sequence order. Here are the *SEARCH/REPLACE* blocks to implement these changes: <<<<<<< SEARCH frontend-mop/index.html // Immediately define brokk with a proxy to buffer all early calls from Java (function() { const callQueue = [ ] // Stores {method, args} for all calls except onEvent const eventBuffer = [ ] // Stores payloads for onEvent window.brokk = new Proxy({ _callQueue: callQueue, _eventBuffer: eventBuffer }, { get(target, prop) { // Allow direct access to internal queues if (prop === '_callQueue' || prop === '_eventBuffer') { return target[prop]; } // Return a stub function for any other property access return (...args) => { if (prop === 'onEvent') { console.log('Buffering early event from Java:', JSON.stringify(args)); eventBuffer.push(...args); } else { console.log('Buffering early call from Java to', prop); callQueue.push({ method: prop, args }); } // Provide default return values for synchronous methods if (prop === 'getSelection') { return ''; } return undefined; }; } }); })(); ======= // Immediately define brokk with a proxy to buffer all early calls from Java (function() { const buffer = [ ] // Unified buffer for all calls and events let seq = 0 // Sequence number to maintain order window.brokk = new Proxy({ _buffer: buffer }, { get(target, prop) { // Allow direct access to internal buffer if (prop === '_buffer') { return target[prop]; } // Return a stub function for any other property access return (...args) => { if (prop === 'onEvent') { console.log('Buffering early event from Java:', JSON.stringify(args)); buffer.push({ type: 'event', payload: args[0], seq: seq++ }); } else { console.log('Buffering early call from Java to', prop); buffer.push({ type: 'call', method: prop, args: args, seq: seq++ }); } // Provide default return values for synchronous methods if (prop === 'getSelection') { return ''; } return undefined; }; } }); })(); >>>>>>> REPLACE \`\`\` frontend-mop/src/index.ts <<<<<<< SEARCH // Retrieve buffered calls and events from the early stub const pendingCalls = window.brokk._callQueue || [] co ``` -------------------------------- ### java-stack-trace-parser License Source: https://github.com/brokkai/brokk/blob/master/NOTICE.txt This section details the MIT license for the java-stack-trace-parser code used in the Brokk project. It grants broad permissions for use, modification, and distribution. ```License Copyright (c) 2018 Alex Scheitlin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. ``` -------------------------------- ### Markdown Playground Input Handling Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This code snippet sets up an event listener for the 'input' event on an element with the ID 'md-playground'. When the input value changes, it clears the previous Brokk state and then simulates a 'chunk' event with the new content, marked as AI-generated and streaming. ```javascript const mdInput = document.getElementById('md-playground'); let rafId = 0; mdInput.addEventListener('input', () => { cancelAnimationFrame(rafId); rafId = requestAnimationFrame(() => { window.brokk.clear(); simulateEvent('chunk', { text: mdInput.value, msgType: 'AI', streaming: true }); }); }); ``` -------------------------------- ### Populate Commits Table and Update UI Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This code populates the `commitsTableModel` with commit data. It then adjusts column widths for 'Author' and 'Date' and selects the first row if commits are present. If no commits are found, it clears the changes tree and revision information. ```java for (Object[] rowData : commitRows) { commitsTableModel.addRow(rowData); } // Fit column widths for author and date TableUtils.fitColumnWidth(commitsTable, 1); // Author column TableUtils.fitColumnWidth(commitsTable, 2); // Date column if (commitsTableModel.getRowCount() > 0) { commitsTable.setRowSelectionInterval(0, 0); // Listener will handle updates to revision display and changes tree } else { // Ensure changes area and revision display are cleared if no commits changesRootNode.removeAllChildren(); changesTreeModel.reload(); revisionTextLabel.setText("Revision:"); revisionIdTextArea.setText("N/A"); } ``` -------------------------------- ### Package Null Marking Source: https://github.com/brokkai/brokk/blob/master/app/src/main/nullaway.md Instructions for marking new packages as null-safe using JSpecify annotations. This ensures consistency in null handling across the project. ```Java @org.jspecify.annotations.NullMarked package com.example.mypackage; ``` -------------------------------- ### Brokk Initialization and Event Buffering Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html Initializes the Brokk object with a proxy to buffer early calls and events from Java. This ensures that no interactions are lost before the main application logic is ready. It includes a sequence number to maintain the order of operations. ```javascript function () { const buffer = []; let seq = 0; window.brokk = new Proxy({ _buffer: buffer }, { get(target, prop) { if (prop === '_buffer') { return target[prop]; } return (...args) => { if (prop === 'onEvent') { console.log('Buffering early event from Java:', JSON.stringify(args)); buffer.push({type: 'event', payload: args[0], seq: seq++}); } else if (prop === 'hideSpinner') { console.log('Buffering early call from Java to', prop); buffer.push({type: 'call', method: prop, args: [], seq: seq++}); } else { console.log('Buffering early call from Java to', prop); buffer.push({type: 'call', method: prop, args: args, seq: seq++}); } return undefined; }; } }); })(); ``` -------------------------------- ### Modify GitLogTab for Commit Browser Panel Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This Java code snippet demonstrates how to modify the GitLogTab class to correctly integrate the GitCommitBrowserPanel. It addresses an issue where 'commitBrowserPanel' was referenced but not properly initialized, and adjusts the panel's weight and addition to the log panel. ```java // ============ Commit Browser Panel (center ~80%) ============ // Original code might have had an issue with commitBrowserPanel initialization // This section shows the corrected way to initialize and add it. // Example of initialization (assuming GitCommitBrowserPanel exists) // commitBrowserPanel = new GitCommitBrowserPanel(chrome, contextManager); // Corrected panel initialization and addition to the layout JPanel commitBrowserPanel = buildCommitBrowserPanel(); // Assuming this method builds the panel // ... other panel setup ... constraints.gridx = 1; // commit browser (commits + changes) constraints.weightx = 0.80; logPanel.add(commitBrowserPanel, constraints); // ... logging and button state updates ... // logger.warn("Could not select any local branch (target: {}, current git: {}). Clearing commits.", previouslySelectedBranch, currentGitBranch); // commitBrowserPanel.setCommits(List.of()); // pullButton.setEnabled(false); // pushButton.setEnabled(false); ``` -------------------------------- ### Brokkai/Brokk License Terms Source: https://github.com/brokkai/brokk/blob/master/LICENSE.txt Details the conditions for distributing and modifying the Brokkai/Brokk project. It covers copyright notices, warranty disclaimers, and requirements for providing the source code when distributing in object code form. ```text Project: /brokkai/brokk Content: receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. ``` -------------------------------- ### Joern License Information Source: https://github.com/brokkai/brokk/blob/master/NOTICE.txt This entry notes that Brokk incorporates code from Joern, which is licensed under the Apache License 2.0 (ASL 2). The affected files retain their original ASL copyright headers. ```License Joern is licensed under ASL 2 and the affected files retain their ASL copyright header. ``` -------------------------------- ### Brokk MOP Dev Mode HTML Structure Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html Basic HTML structure for the Brokk MOP development mode page, indicating where Java events will be logged. ```html

Brokk MOP - Development Mode

Events from Java will be logged to the console and displayed raw below.

``` -------------------------------- ### Simulate Brokk Events and Chunk Processing Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This snippet demonstrates how to simulate Brokk events, specifically 'clear' and 'chunk' events, which are used for managing chat-like interfaces. It shows how to send user input and AI-generated content in chunks, simulating a streaming effect for the AI's response. ```javascript let index = 0; simulateEvent('clear'); simulateEvent('chunk', {text: contentUser, msgType: 'USER', streaming: true}); const chunks = contentAi.match(/[\s\S]{1,10}/g) || []; const interval = setInterval(() => { if (index < chunks.length) { simulateEvent('chunk', {text: chunks[index], msgType: 'AI', streaming: true}); index++; } else { clearInterval(interval); } }, 10); ``` -------------------------------- ### JavaScript Event and Call Buffering (Unified Buffer) Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html This JavaScript code snippet shows an improved method for buffering early calls and events using a single unified buffer with sequence numbers. It replaces separate queues for calls and events, ensuring correct replay order by processing items based on their sequence. ```javascript (function() { const buffer = []; // Unified buffer for all calls and events let seq = 0; // Sequence number to maintain order window.brokk = new Proxy({ _buffer: buffer }, { get(target, prop) { // Allow direct access to internal buffer if (prop === '_buffer') { return target[prop]; } // Return a stub function for any other property access return (...args) => { if (prop === 'onEvent') { console.log('Buffering early event from Java:', JSON.stringify(args)); buffer.push({ type: 'event', payload: args[0], seq: seq++ }); } else { console.log('Buffering early call from Java to', prop); buffer.push({ type: 'call', method: prop, args: args, seq: seq++ }); } // Provide default return values for synchronous methods if (prop === 'getSelection') { return ''; } return undefined; }; } }); })(); ``` -------------------------------- ### Java Git Create Pull Request API Source: https://github.com/brokkai/brokk/blob/master/frontend-mop/dev.html Provides a Java method `createPullRequest` for creating GitHub pull requests. It handles generating titles and bodies if they are blank, checks for uncommitted changes, and ensures the operation is not performed on the default branch. It also includes error handling and logging. ```APIDOC createPullRequest(title: String, body: String) @Tool("Create a GitHub pull-request for the current branch. " + "If title or body is blank they are auto-generated. " + "This implicitly pushes the branch and sets upstream when needed.") public String createPullRequest( @Nullable @P("PR title (optional)") String title, @Nullable @P("PR description in Markdown (optional)") String body) // Parameters: // title: PR title (optional). If blank, it will be auto-generated. // body: PR description in Markdown (optional). If blank, it will be auto-generated. // Returns: A string containing the URL of the created pull request. // Throws: // IllegalStateException: If the current directory is not a Git repository, cannot determine the default branch, has uncommitted changes, or is attempting to create a PR from the default branch. // RuntimeException: If any other exception occurs during the process. { var cursor = messageCursor(); io.llmOutput("Creating pull request…", ChatMessageType.CUSTOM, true); try { var project = contextManager.getProject(); if (!project.hasGit()) throw new IllegalStateException("Not a Git repository"); var repo = (GitRepo) project.getRepo(); var defaultBranch = repo.getDefaultBranch() .orElseThrow(() -> new IllegalStateException("Cannot determine default branch")); var currentBranch = repo.getCurrentBranch(); if (Objects.equals(currentBranch, defaultBranch)) throw new IllegalStateException("Refusing to open PR from default branch (" + defaultBranch + ')'); if (!repo.getModifiedFiles().isEmpty()) throw new IllegalStateException("Uncommitted changes present; commit first"); var gws = new GitWorkflowService(contextManager); // Auto-generate title/body if blank if (title == null || title.isBlank() || body == null || body.isBlank()) { var suggestion = gws.suggestPullRequestDetails(currentBranch, defaultBranch); if (title == null || title.isBlank()) title = suggestion.title(); if (body == null || body.isBlank()) body = suggestion.description(); } var prUrl = gws.createPullRequest(currentBranch, defaultBranch, title.trim(), body.trim()); var msg = "Opened PR: " + prUrl; io.llmOutput(msg, ChatMessageType.CUSTOM); logger.info(msg); // Persist result to history var newMessages = messagesSince(cursor); contextManager.addToHistory(new TaskResult(contextManager, "Git create PR", newMessages, Set.of(), TaskResult.StopReason.SUCCESS), false); return msg; } catch (Exception e) { var err = "Create PR failed: " + e.getMessage(); io.llmOutput(err, ChatMessageType.CUSTOM); logger.error(err, e); var newMessages = messagesSince(cursor); contextManager.addToHistory(new TaskResult(contextManager, "Git create PR", newMessages, Set.of(), TaskResult.StopReason.TOOL_ERROR), false); throw new RuntimeException(err, e); } } ```