Development Log

A detailed, reverse-chronological record of all changes, fixes, and architectural decisions made during the development of Graphite Pro.

[Beta v.0.6.9]

2025-11-04

This is a major feature release that introduces the Conversation Node, a powerful new tool for managing complex, linear discussions within the graph. This feature allows users to encapsulate detailed sub-tasks into a single, interactive node, which can both inherit and provide rich context to the main canvas.

Added

  • Introduced the Conversation Node Plugin.
    • Feature: A new "Conversation Node" can be created from the "Plugins" menu. It provides a self-contained, vertically scrolling chat interface (similar to standard chatbots) directly on the canvas.
    • Context Inheritance: When created, the node automatically makes a one-time copy of its parent's entire conversation history and displays it visually. This "snapshots" the context, allowing the new conversation to start with a full understanding of the preceding discussion.
    • Focused Interaction: Users can engage in a detailed, multi-step conversation with the AI entirely within the node's UI, preventing clutter on the main graph.
    • Context Provision: The entire internal chat log of the Conversation Node (inherited history + new messages) can be used as a rich source of context for any new nodes that branch off from it.
  • Architectural Integration for the New Node Type.
    • Dedicated UI: The node's internal UI was built using a custom QGraphicsScene and QGraphicsView, where each message is a distinct ChatMessageBubbleItem. This ensures full integration with application features.
    • Search and Highlighting: The application's search functionality (Ctrl+F) now works seamlessly inside Conversation Nodes, correctly highlighting the specific message bubble that contains the search term.
    • Full Persistence: The ChatSessionManager has been updated to serialize and deserialize Conversation Nodes, including their entire internal chat history and connections, ensuring that sessions are saved and loaded perfectly.
    • Plugin Interoperability: All other plugin nodes (like Py-Coder and WebNode) can now be correctly branched from a Conversation Node, allowing for complex, chained workflows.

Fixed

  • Made the graphite-Web Plugin Context-Aware.
    • Problem: The graphite-Web node was not using the conversation history. This meant that contextual queries (e.g., "what is its price?") would fail because the search agent lacked the necessary context to understand what "it" referred to.
    • Solution: The web search workflow has been rebuilt. The agent now uses an LLM to analyze the conversation history and transform the user's input into a self-contained, effective search query. The summarization step also receives the full conversation history, allowing it to generate a final answer that is relevant to the ongoing discussion.
    • Result: The graphite-Web plugin now correctly handles contextual follow-up questions, making it a much more powerful and intuitive tool for research.
  • Refined Chat UI for Conversation Node.
    • Problem: The initial design of the internal chat UI used visually jarring colors (bright green and blue) that did not fit the node's aesthetic.
    • Solution: The chat bubbles were redesigned with a professional, neutral color scheme (dark grays) to create a more focused and visually pleasing user experience.

[Beta v.0.6.8]

2025-11-04

This is a major stability and user experience release that resolves critical threading crashes, fixes widespread UI inconsistencies, and introduces a new long-hover interaction to visualize conversation flow.

Architectural Refactor

  • Corrected Application Threading Model to Eliminate Crashes.
    • Problem: The application was unstable and would frequently crash with QThread: Destroyed while thread is still running and QObject::killTimer: Timers cannot be stopped from another thread. This was caused by a fundamental architectural flaw where worker thread objects were being prematurely garbage-collected or improperly managed from the main GUI thread.
    • Solution: The threading architecture was completely rebuilt to adhere to Qt's strict threading and memory management rules.
      1. Correct Object Ownership: Worker threads are now stored as member variables of the ChatWindow, creating a persistent reference that prevents them from being destroyed while running.
      2. Safe Self-Destruction: All worker threads now use the deleteLater() slot connected to their finished and error signals. This is the standard Qt "fire-and-forget" pattern, ensuring threads schedule their own safe cleanup from the main event loop.
      3. Removal of Unsafe Code: All manual thread cleanup methods (cleanup_..._thread) and the dangerous stop_all_workers procedure were removed entirely, as they were the root cause of the crashes.
    • Result: The application is now architecturally sound and stable, with all critical threading crashes resolved.

Added

  • Implemented Ancestor Connection Animation on Long Hover.
    • Feature: A new HoverAnimationMixin class was created to provide shared functionality to all node types. When a user hovers their mouse over any node for a brief period (750ms), the connection lines for all of its ancestors are animated with flowing arrows, tracing the conversational path back to the root.
    • Benefit: This provides intuitive, real-time visual feedback, making it easy to understand the history and context of any node within a complex graph. The animation stops immediately when the hover ends.

Fixed

  • Resolved Keyboard Shortcut Interference with Text Input.
    • Problem: The keyboard shortcuts for canvas navigation (W, A, S, D, Q, E) were incorrectly intercepting key presses when the user was trying to type inside a Note, Frame title, PyCoderNode, or WebNode.
    • Solution: The keyPressEvent handler in ChatView was updated to be context-aware. It now checks if the currently focused item is a text input field or in a custom editing mode. If so, the navigation shortcuts are bypassed, allowing for normal text input.
  • Restored Hover Highlight Effect on All Nodes.
    • Problem: An architectural mistake in the implementation of the HoverAnimationMixin caused it to incorrectly override the hoverEnterEvent and hoverLeaveEvent methods of all nodes, breaking the standard visual hover highlight effect.
    • Solution: The mixin was refactored to provide helper methods (_handle_hover_enter, _handle_hover_leave) instead of overriding the events directly. Each node class now correctly calls both its superclass's event handler and the mixin's helper, restoring the hover highlight while enabling the new animation feature.
  • Corrected Lost Connections for Plugin Nodes.
    • Problem: Connections branching off from PyCoderNode and WebNode were not being saved, causing them to disappear when a chat session was reloaded.
    • Solution:
      1. The serialization logic was fixed to save the children_indices for PyCoderNode and WebNode, ensuring these relationships are persisted.
      2. The plugin creation logic was updated to correctly establish the bidirectional parent-child link in the live object graph when these nodes are created.

[Beta v.0.6.7]

2025-11-03

This release introduces the Web Search Plugin, a major new feature that integrates real-time web information directly into the Graphite canvas. It allows users to perform web-grounded queries with a built-in safety and relevance validation process.

Added

  • Introduced the Web Search Plugin (graphite-Web).
    • Feature: A new "graphite-Web" node can be created from the "Plugins" menu or the Command Palette (Ctrl+K). This node provides a dedicated interface to run web queries.
    • Workflow: The node orchestrates a multi-step process in the background:
      1. Performs a web search based on the user's query.
      2. Fetches content from the top search results.
      3. Validates each piece of content for safety and relevance using a dedicated AI call.
      4. Summarizes the validated content to provide a concise, direct answer to the original query.
    • UI: The WebNode has a distinct orange theme and provides real-time status updates as it progresses through the search, fetch, validate, and summarize stages. Final results include a formatted summary and clickable source links.
  • Expanded System Architecture for Web Functionality.
    • New Agents: Implemented a WebSearchAgent and WebWorkerThread to handle the complex, multi-step retrieval and validation logic without freezing the UI.
    • Serialization: The ChatSessionManager has been updated to fully support saving and loading the new WebNode and its connections, ensuring complete data persistence.
    • Plugin Integration: The PluginPortal and ChatScene were extended to manage the lifecycle of the new web components.

Fixed

  • Resolved Critical Signal/Slot Initialization Error.
    • Problem: The application would crash when creating a WebNode due to an AttributeError, as the node's signals were not correctly registered.
    • Solution: The base class for WebNode was corrected from QGraphicsItem to QGraphicsObject, which is required for using Qt's signal and slot mechanism in graphics items. This resolved the instability and made the plugin functional.
  • Corrected API Routing for Web Validation.
    • Problem: The web validation step was incorrectly hard-coded to use a specific API, ignoring the user's selection of "Ollama (Local)" mode and causing errors if an API key was not configured.
    • Solution: The API provider logic was refactored to strictly adhere to the globally selected mode (Ollama vs. API). The validation task now correctly routes to the user's chosen provider, restoring logical consistency.
  • Updated Deprecated Dependency.
    • Problem: A RuntimeWarning was being issued because the duckduckgo-search library had been renamed.
    • Solution: The import statement was updated to use the new package name, ddgs, ensuring future compatibility and silencing the warning.
  • Fixed Painter State Error in Web Connection Animation.
    • Problem: A QPainter warning (Painter ended with 1 saved states) was triggered when hovering over a WebNode connection. This was caused by an argument type mismatch in the animation drawing method, leading to an unbalanced painter state.
    • Solution: Implemented a local drawArrow method in WebConnectionItem to correctly handle its specific drawing logic, ensuring the painter's state is properly saved and restored. This eliminates the warning and potential rendering artifacts.

[Beta v.0.6.6]

2025-11-03

This release introduces comprehensive keyboard navigation for the canvas, improving accessibility and workflow speed. It also includes several quality-of-life improvements and a critical bug fix for the cursor state.

Added

  • Implemented Full Keyboard Navigation.
    • WASD Panning: The canvas can now be panned smoothly using the W, A, S, and D keys. Movement is continuous while keys are held down.
    • Q/E Zoom: Users can now zoom in with the 'E' key and zoom out with the 'Q' key, providing a keyboard-centric alternative to mouse-wheel zooming.
    • Logical Node Traversal (Ctrl + Arrow Keys): A new system allows for precise navigation between related nodes:
      • Ctrl+Up: Jumps to the parent of the currently selected node.
      • Ctrl+Down: Jumps to the first child of the currently selected node.
      • Ctrl+Left/Ctrl+Right: Jumps to the previous or next sibling node in the same branch.
  • Added Welcome Screen Preference.
    • Feature: An option to "Show Welcome Screen on Startup" has been added to the Settings > Appearance dialog.
    • Effect: When unchecked, the application will bypass the welcome screen and launch directly into the main interface, loading the most recent chat session. This preference is saved and persists across launches.

Fixed

  • Resolved Stuck Panning Cursor Bug.
    • Problem: The cursor would get stuck in the "closed hand" panning state if the user released the middle mouse button while the cursor was outside the application window.
    • Solution: The view's mouseMoveEvent was enhanced to reliably check the global state of the mouse buttons. It now correctly detects when the middle mouse button is no longer pressed and resets the cursor to its default state, regardless of where the release event occurred.
  • Corrected Welcome Screen Behavior.
    • Problem: The welcome screen would remain open in the background after a user selected a project or started a new chat.
    • Solution: The welcome screen now automatically closes itself upon performing an action that opens the main chat window, streamlining the application startup flow.

[Beta v.0.6.5]

2025-11-03

This release refines the AI's code generation output and resolves critical architectural bugs related to plugin functionality, resulting in a more stable and predictable user experience.

Architectural Refactor

  • Standardized AI Code Block Generation.
    • Problem: The AI model would often split a single logical code block across multiple markdown fences, causing the application to create a separate CodeNode for each fragment. This resulted in a cluttered and disorganized canvas.
    • Solution:
      1. The ChatAgent's system prompt has been updated with a strict new rule: all code, regardless of the number of segments, must be wrapped within a single <code_block>...</code_block> XML tag.
      2. The response parsing logic in ChatWindow was re-architected to prioritize this new tag. It now first searches for <code_block>; if found, it extracts the entire content and treats it as a single unit for one CodeNode.
      3. A fallback mechanism was retained: if the tag is not found, the parser reverts to the old behavior of identifying individual markdown fences.
    • Result: This ensures that all code generated in a single AI response is consolidated into one CodeNode, providing a clean, coherent output. The fallback maintains robustness if the model fails to adhere to the new format.

Fixed

  • Corrected PyCoderNode Contextual Attachment Logic.
    • Problem: The PyCoder plugin could be incorrectly attached to a CodeNode. When executed, this would cause a fatal AttributeError because CodeNode objects do not possess a conversation_history, which is essential for providing context to the AI.
    • Solution:
      1. The plugin creation logic in graphite_plugin_portal.py was updated. It now intelligently determines the correct parent for the PyCoderNode. If the user has a CodeNode selected, the system automatically traverses up to its parent ChatNode and attaches the PyCoder plugin there instead.
      2. Defensive code was added to graphite_window.py. The execution logic now verifies the parent node's type before attempting to access conversation_history, ensuring it always retrieves context from a valid source (ChatNode or another PyCoderNode).
    • Result: The application no longer crashes when using the PyCoder plugin in this scenario. The plugin's attachment behavior is now architecturally sound and predictable.
  • Resolved ImportError on Startup.
    • Problem: The application would fail to launch due to a circular or incorrect import statement where graphite_plugin_portal.py attempted to import PyCoderNode from graphite_node.py instead of the correct graphite_pycoder.py module.
    • Solution: The invalid import path was corrected, resolving the dependency conflict and allowing the application to start normally.

[Beta v.0.6.4]

2025-11-02

This release introduces a powerful and flexible content export system, allowing users to save the contents of individual nodes to a variety of standard file formats. The architecture for this feature is designed to be modular and easily extensible.

Architectural Refactor

  • Created a Centralized Exporter Module.
    • Problem: Implementing export logic directly within UI classes would lead to scattered, duplicated code that is difficult to maintain.
    • Solution: A new graphite_exporter.py file was created to house a dedicated Exporter class. This class encapsulates all file conversion and writing logic for each supported format. UI components now simply call the Exporter with the content and desired format, decoupling the user interface from the file generation process.
    • Result: This modular design makes it simple to add new export formats in the future without modifying any UI code.

Added

  • Implemented Multi-Format Node Content Export.
    • Feature: A new "Export to Doc" submenu is now available in the right-click context menu for ChatNode, CodeNode, and DocumentNode.
    • Formats:
      • Text File (.txt): Exports the raw text content.
      • Markdown File (.md): Exports the raw content, preserving markdown syntax. For code nodes, it automatically wraps the code in a markdown code block.
      • HTML Document (.html): Converts the node's markdown content into a self-contained, styled HTML file.
      • Word Document (.docx): Exports the content into a standard .docx file. (Requires python-docx)
      • PDF Document (.pdf): Renders the content into a PDF file, with special monospace formatting for code. (Requires reportlab)
      • Python Script (.py): An additional option exclusive to CodeNode for direct script saving.
    • Image Export: The "Save Image As..." option for ImageNode was renamed to "Export Image" for consistency.
  • Graceful Handling of Optional Dependencies.
    • Feature: The application now intelligently handles cases where optional libraries required for certain export formats (reportlab for PDF, python-docx for DOCX) are not installed.
    • User Experience: If a user attempts to export to a format with a missing dependency, the application will not crash. Instead, a clear and informative message box appears, explaining which library is needed and providing the pip install command to install it.

Fixed

  • Resolved Crash on Export Dialogs.
    • Problem: The application would crash with an AttributeError when showing the success/failure message box after an export, because the dialog's parent was being set incorrectly.
    • Solution: The logic for retrieving the main window was corrected. Instead of an unreliable self.parent() call, the code now correctly traverses the object hierarchy from the QGraphicsItem (the node) to its scene, and then to the scene's window property, ensuring a valid QWidget parent is always found for the dialogs. This also fixed a bug where the dialogs were missing the application icon.

[Beta v.0.6.3]

2025-11-02

This update focuses on significant UI refinement and consistency, enhancing the visual language and interactive feedback of the core node-graph system.

Added

  • Persistent Node Connection Points.
    • Feature: All ChatNode and PyCoderNode items now feature permanently visible connection points.
    • Detail: These points are rendered as colored half-circles that seamlessly emerge from the left (input) and right (output) sides of the node. The color of the connection point matches the node's identity color (e.g., green for user nodes, blue for AI nodes, purple for PyCoder), reinforcing the visual flow of information.
    • Result: This provides a clear, consistent, and aesthetically pleasing visual language for how nodes are connected, removing ambiguity about where connection lines terminate.
  • Universal Connection Hover Animation.
    • Feature: The animated "flowing arrow" effect, previously exclusive to primary chat connections, has been implemented across all directional connection types.
    • Effect: Hovering over any connection line (including those for code blocks, documents, images, and the PyCoder plugin) now triggers the animation, providing consistent visual feedback for interactivity and data flow across the entire canvas. The animation color is styled to match the specific connection type.

Fixed

  • Resolved Visual Gap in Connection Lines.
    • Problem: In a previous implementation, connection lines appeared to stop short of their target nodes because the connection dots they were anchored to were only visible on hover.
    • Solution: By making the new half-circle connection points permanently visible, the connection lines now appear to terminate perfectly at the node's edge, creating a visually complete and polished look.

[Beta v.0.6.2]

2025-11-01

This is a rapid-response update focused on critical stability fixes, a quality-of-life improvement for the new Container system, and the introduction of a comprehensive, application-wide themeing architecture. A series of architectural flaws related to object lifecycles, coordinate systems, and import dependencies were identified and resolved, eliminating crashes and addressing visual bugs across the UI.

Architectural Refactor

  • Centralized Theme and Color Palette System.
    • Problem: Hardcoded colors were scattered across numerous UI components, including both Qt stylesheets and custom paint methods within QGraphicsItems. This made the application rigid and difficult to style.
    • Solution: A new, scalable themeing architecture was implemented.
      1. A ColorPalette class was created in graphite_styles.py to act as a single source of truth for all custom-drawn UI elements (nodes, connections, highlights, etc.).
      2. A central THEMES dictionary now maps theme names ("dark", "mono") to both a full application stylesheet and a corresponding ColorPalette object.
      3. A global apply_theme function was established in graphite_config.py. This function updates the application's stylesheet and signals all open windows to repaint themselves using the new palette, ensuring a consistent, application-wide theme change.
    • Result: This decouples visual presentation from component logic, resolves numerous visual bugs at their source, and enables the rapid development of future themes.

Added

  • Introduced Dual-Mode "PyCoder" Plugin.
    • Feature: The PyCoder plugin has been re-architected to support two distinct operational modes, providing both intelligent automation and direct user control.
    • AI-Driven Mode (Default): The AI now functions as a "tool-using" agent. It receives a high-level user prompt and independently determines whether to write and execute Python code to find the answer. The entire workflow—code generation, execution, output capture, and final analysis—is fully automated. This allows users to ask complex computational questions in natural language.
    • Manual Mode: The original functionality is preserved as a "Manual" mode. Users can switch to this mode to write, run, and debug their own Python code in a dedicated scratchpad, optionally receiving AI analysis on their code and its output.
    • Result: This transforms PyCoder from a simple code executor into a versatile and intelligent problem-solving tool, greatly expanding the application's capabilities.
  • Upgraded PyCoder to be Context-Aware.
    • Feature: The AI-Driven mode of the Py-Coder plugin now receives the full conversation history from its parent node.
    • Effect: The agent can now use the preceding conversation as context when generating code. This allows for more intuitive and powerful requests, such as referring to data or concepts mentioned in previous messages (e.g., "Take that list of names from before and sort it alphabetically").
    • Implementation: The PyCoderExecutionWorker was updated to accept the parent's conversation_history, and the PyCoderExecutionAgent's system prompt was enhanced to instruct it on how to leverage this contextual information.
  • Implemented Automated Error Correction for PyCoder.
    • Feature: The AI-Driven Py-Coder agent is now capable of self-correction. If the code it generates results in an error, it will automatically attempt to debug and fix it.
    • Workflow:
      1. The agent generates and executes code.
      2. If an error is detected in the output, the error log is fed back to a specialized PyCoderRepairAgent.
      3. The repair agent returns a corrected version of the code, which is then re-executed.
      4. This process repeats up to a maximum of four attempts. On the final attempt, the agent is prompted to try a completely different approach.
    • Result: This significantly increases the reliability and success rate of the PyCoder feature, allowing it to overcome common coding mistakes without user intervention.
  • Added a Real-Time Status Tracker to the PyCoder Node.
    • Feature: The verbose "Execution Log" text area has been replaced with a clean, intuitive checklist UI (StatusTrackerWidget).
    • Effect: This new component provides at-a-glance feedback on the agent's progress, showing the status (Pending, Running, Success, Failure) of each stage in the workflow: Analyzing Prompt, Generating Code, Executing & Repairing, and Final Analysis. The "Running" state features a smooth, custom-drawn vector animation.
    • Implementation: This was achieved by creating a new StatusIconWidget that uses QPainter for crisp vector rendering, eliminating the pixelation issues of the previous icon-based approach. The worker thread now communicates with the UI using a structured system of Enums for stages and statuses, making the architecture more robust.
  • Implemented Monochromatic Theme.
    • Feature: A new "Monochromatic Mode" option is now available in Settings > Appearance. The user's choice is persisted across application sessions.
    • Effect: When enabled, it applies a grayscale color palette across the entire application, affecting everything from window backgrounds and buttons to custom-drawn node outlines and connection lines. This provides a lower-contrast, less colorful user experience.
  • Implemented "Ghost Frame" Preview for Collapsed Containers.
    • Feature: Hovering the cursor over a collapsed Container for 2 seconds now displays a semi-transparent "ghost" preview. This preview is centered on the cursor and shows the full size and shape the container will occupy when expanded.
    • Purpose: This provides essential spatial context, allowing users to plan their canvas layout and organize items around a collapsed group without needing to expand it first. The feature uses a QTimer to manage the hover delay and another QTimer to automatically dismiss the preview after 3 seconds.

Fixed

  • Resolved Critical Infinite Loop When Replying to PyCoder Nodes.
    • Problem: Responding to a PyCoderNode would cause the application to hang with an infinite loading animation.
    • Solution (Architectural): The issue was traced to a critical flaw in the chat deserialization logic (graphite_core.py). A node was being incorrectly set as its own parent (child_node.parent_node = child_node), creating a self-referential loop in the graph's data structure. When the ChatWorker attempted to traverse this branch to build the conversation history, it entered an unbreakable while loop, causing the thread to hang indefinitely. The fix involved correcting the parent assignment to child_node.parent_node = node, restoring the integrity of the graph structure and eliminating the infinite loop.
  • Integrated PyCoder Node into the Conversational Flow.
    • Problem: The PyCoderNode was architecturally treated as a terminal "tool" node, not a conversational participant. This prevented users from branching new replies from it, causing new messages to start a disconnected conversation instead.
    • Solution: The PyCoderNode was structurally upgraded to act as a proper conversational node.
      1. It was given children, conversation_history, and is_user attributes, making it compatible with the scene's branching logic.
      2. The scene's node creation and connection logic was updated to recognize PyCoderNode as a valid parent.
      3. The application's state management now correctly sets the PyCoderNode as the active context after execution, ensuring subsequent user messages correctly attach to it.
      4. A secondary bug was fixed where ConnectionItems would crash when trying to connect to a PyCoderNode due to missing width and height attributes; these were added to standardize the node's interface.
    • Result: This change ensures that the PyCoder tool is no longer a "dead end" in the conversation, allowing for a seamless and logical flow between text-based chat and code execution.
  • Resolved Critical AttributeError on Chat Loading and Rendering.
    • Problem: A crash occurred when loading a chat or rendering the PyCoderNode's status tracker, caused by an AttributeError: unsupported keyword 'cap'.
    • Solution: The QPen constructor in the StatusIconWidget's paintEvent was being called with unsupported keyword arguments. The code was refactored to first instantiate the QPen object and then use its setter methods (setCapStyle, setJoinStyle) to configure it correctly, aligning with the PySide6 API and resolving the rendering crash. A similar error related to previousSibling() was also fixed by using direct widget references.
  • Resolved Critical Circular Import Error on Launch.
    • Problem: A circular dependency was introduced between high-level UI modules (graphite_app.py, graphite_window.py) and lower-level modules (graphite_dialogs.py), preventing the application from launching.
    • Solution: Theme utility functions (apply_theme, get_current_palette) were correctly moved from the high-level graphite_app.py module to the low-level graphite_config.py module, breaking the import cycle and restoring proper architectural layering.
  • Ensured PyCoder Node Conforms to All Graph Rules.
    • Problem: The PyCoderNode and its connection did not respect scene-wide layout rules like "Snap to Grid," "Smart Guides," and "Orthogonal Connections."
    • Solution: The node's event handling was properly integrated with the scene's drag-and-drop lifecycle. It now correctly signals the start and end of a drag, allowing the scene to apply snapping and alignment logic. The PyCoderConnectionItem was also updated to check for and render in an orthogonal style when the mode is active.
  • Ensured UI Consistency Across All Components in Monochromatic Mode.
    • Problem: Several UI elements retained their original colors when the monochromatic theme was enabled, creating a visually inconsistent experience. This included the send/attach buttons, minimap indicators, dialog windows, context menus, and the System Prompt note header.
    • Solution: All custom paint methods and stylesheet definitions throughout the application were refactored to source their colors from the new central ColorPalette, making them fully theme-aware. Contrast-detection logic was also added to ensure icon and text colors remain legible on dynamic backgrounds.
  • Resolved Critical RuntimeError on Scene Clearing and Chat Loading.
    • Problem: The application would crash with an Internal C++ object already deleted error when clearing the scene to load a new chat. This was caused by QVariantAnimation objects (used for pulsing effects on Containers and Frames) continuing to run after their parent QGraphicsItem was destroyed.
    • Solution (Architectural): The root cause was twofold: animations were instantiated incorrectly, and their lifecycles were not managed during scene cleanup.
      1. The QVariantAnimations were correctly re-instantiated without being parented to the QGraphicsItems (which are not QObjects).
      2. The itemChange method in both Container and Frame was corrected to reliably detect when an item is being removed from a scene (change == QGraphicsItem.ItemSceneHasChanged and value is None).
      3. In this cleanup path, all active animations and timers (pulse_animation, outline_animation, ghost_frame_timer, cursor_timer) are now explicitly stopped, preventing them from accessing deleted objects.
  • Corrected "Ghost Frame" Positioning Logic.
    • Problem: The initial implementation of the ghost frame appeared at an incorrect offset, as it was mixing the container's local coordinates with the scene's global coordinates.
    • Solution: The positioning logic in the _show_ghost_frame method was rewritten. It now correctly uses the current global cursor position, maps it to scene coordinates, and then calculates the top-left corner of the preview to ensure it always appears perfectly centered on the user's cursor.
  • Fixed Recursive Connection Bug with Nested Containers.
    • Problem: If a Frame was placed inside a Container, moving the outer Container would not update the connections for the nodes inside the nested Frame.
    • Solution: The Container's _update_child_connections method was made recursive. It now uses a new helper method, _get_all_descendant_nodes, to traverse the entire hierarchy of nested items (including other Containers and Frames) to build a complete list of all nodes that require a connection update.

[Beta v.0.6.1] - 2025-11-01 (Container System & Connection Logic Overhaul)

This update introduces the Container, a powerful new organizational tool, alongside a critical overhaul of the scene's connection rendering logic. The new Container system allows for complex nesting of any canvas item, while the connection fixes ensure that all visual links behave predictably and consistently, especially when interacting with grouped or collapsed items. This lays a more robust architectural foundation for future layout and interaction features.

Added

  • Introduced the "Container" Grouping System.
    • Feature: A new, versatile grouping item that can contain any combination of other items on the canvas, including Chat Nodes, Notes, Charts, Frames, and even other Containers for deep nesting.
    • Interaction:
      • Creation: Select any items and press Ctrl+Shift+G or use the Command Palette.
      • Collapsible State: Containers can be collapsed into a compact, node-like object to hide their contents and simplify the graph view. A pulsing glow indicates that a container is collapsed and holds hidden items.
      • Management: A dedicated header provides access to a collapse/expand button, a color picker for customization, and an editable title.

Fixed

  • Resolved Critical Bug in Container Movement.
    • Problem: When a Container was moved, the connection lines for the items inside it did not update their positions, appearing visually "stuck" on the canvas.
    • Solution: The itemChange method in the Container class was updated to correctly propagate position changes through the scene by calling scene.nodeMoved(). Its logic was aligned with the existing Frame class to ensure consistent, predictable behavior across all grouping items.
  • Overhauled Connection Logic for Collapsed Containers.
    • Problem: Connections to or from items within a collapsed Container would remain attached to the last known position of the invisible items, resulting in visually broken lines stretching across the canvas. Connections between two items inside the same collapsed container remained visible but disconnected.
    • Solution: The update_path method for all connection types (ConnectionItem, ContentConnectionItem, etc.) was overhauled. Connections now intelligently detect if their start or end node is within a collapsed Container.
      • If an endpoint is hidden, the connection line now dynamically retargets its visual endpoint to the boundary of the Container itself.
      • If both endpoints of a connection are within the same collapsed container, the connection is now correctly hidden to reduce visual clutter.
  • Corrected Connection Anchor Point Misalignment.
    • Problem: A visual regression caused a small gap to appear between the start of a connection line and the edge of its source node or container.
    • Solution: The issue was traced to an incorrect calculation that used the item's boundingRect() (which can include padding) instead of its precise visual geometry. The connection logic was refined to calculate attachment points based on the item's core visual dimensions, ensuring a pixel-perfect alignment.

[Beta v.0.6.0] - 2025-11-01 (Navigational Minimap & Context-Aware Highlighting)

This release introduces a major new UI feature: the Navigational Minimap. This component provides a high-level, interactive "timeline" of the entire chat graph, enabling users to quickly assess the conversation's structure and jump to any point with a single click. To complement this, a new context-aware highlighting system has been implemented to help users maintain their orientation after navigating.

Architectural Refactor

  • Decoupled the Minimap into a Standalone Module (graphite_minimap.py).
    • Problem: The initial implementation of the MinimapWidget was placed within graphite_widgets.py, a general-purpose file. This made the code less modular and harder to maintain.
    • Solution: All code related to the MinimapWidget has been moved to a new, dedicated graphite_minimap.py file. This enforces a clear separation of concerns, improves project organization, and simplifies future development of the minimap feature. The graphite_view.py file was updated to import the widget from its new location.
  • Introduced a scene_changed Signal for Decoupled UI Updates.
    • Problem: UI components that depend on the scene's state (like the new minimap) previously had no efficient way to know when to refresh their content.
    • Solution: A new scene_changed signal was added to the ChatScene class. This signal is now emitted whenever a node is added, removed, moved, or when the layout is reorganized. The MinimapWidget connects to this signal, allowing it to automatically and efficiently stay in sync with the canvas state without being tightly coupled to the scene's internal logic.

Added

  • Implemented the Navigational Minimap Widget.
    • Feature: A new, floating UI element now appears on the right side of the main view. It renders a compact, scrollable list of colored notches (green for user, blue for AI) representing every chat node in the conversation.
    • Interaction:
      • Hover-to-Preview: A 500ms hover delay on any notch reveals a tooltip with a preview of the corresponding node's text.
      • Click-to-Navigate: Clicking a notch instantly centers the main view on that node.
      • Scroll Navigation: Using the mouse wheel while hovering over the minimap scrolls through the list of nodes, with the widget displaying a "viewport" of up to 25 nodes at a time.
      • Proximity Awareness: The minimap fades to a lower opacity when the cursor is far away and becomes fully opaque when the cursor is near, keeping it unobtrusive.
  • Created a "Last Visited" Node Highlighter.
    • Feature: When navigating via the minimap, the previously selected node is now highlighted with a distinct yellow dashed outline.
    • Purpose: This provides an immediate visual anchor, allowing users to easily jump back to their previous point of focus after exploring another part of the chat graph. A new is_last_navigated flag was added to the ChatNode to manage this state.

Changed

  • Optimized Minimap Rendering for Large Graphs.
    • Problem: The initial minimap design mapped each notch's position directly to the node's scene coordinates, creating large gaps for spatially distant nodes.
    • Solution: The rendering logic was completely redesigned. The minimap now treats the node list as a compact, ordered sequence. Notches are rendered with even spacing based on their index in the list, ensuring a neat, stacked appearance regardless of the actual node layout on the canvas.

[Beta v.0.5.9] - 2025-10-31 (Interactive Welcome Screen & Revamped Startup Experience)

This release fundamentally redesigns the application's startup sequence by introducing a dynamic Welcome Screen. This new dashboard serves as a central hub, providing immediate access to recent projects and an animated carousel of conversation starters to inspire users. The application flow has been re-architected to present this screen alongside the main ChatWindow, creating a more intuitive and powerful initial user experience.

Architectural Refactor

  • Decoupled the Welcome Screen into a Dedicated Module.
    • Problem: The WelcomeScreen was a high-level application component residing within graphite_widgets.py, a file intended for low-level, reusable UI elements. This created tight coupling and circular import errors.
    • Solution: The WelcomeScreen and its related StarterNodeWidget have been moved to a new, dedicated graphite_welcome_screen.py file. This refactoring breaks the circular dependencies, improves modularity, and clarifies the architectural separation between foundational widgets and feature-specific windows.
  • Re-architected the Application Startup Flow.
    • Problem: The previous startup sequence was linear: the WelcomeScreen acted as a gatekeeper that would close before opening the main window. The desired behavior was for both windows to co-exist.
    • Solution: The logic in graphite_app.py has been rewritten. It now instantiates both the ChatWindow and the WelcomeScreen and passes them to the SplashScreen. After its timeout, the SplashScreen is now responsible for showing both windows, establishing the correct co-existing application state. The WelcomeScreen's methods were updated to operate on the existing ChatWindow instance rather than creating a new one.

Added

  • Implemented an Infinitely Cycling "Conversation Starters" Carousel.
    • Feature: The list of conversation starters on the Welcome Screen now scrolls automatically and infinitely from right to left.
    • Implementation: To create a seamless loop, the list of starter nodes is duplicated within the QHBoxLayout. A QTimer is used to incrementally advance the scrollbar's position at a regular interval. When the scroll position reaches the halfway point (the end of the original content), it is silently reset to the beginning, giving the illusion of an endless, continuous animation. The animation also intelligently pauses on mouse hover.

Changed

  • Redesigned "Conversation Starter" Nodes for Visual Consistency and Readability.
    • Problem: The starter prompts were implemented as standard QPushButtons, which did not wrap text and were stylistically inconsistent with the application's core node-based UI.
    • Solution: The QPushButton was replaced with a new custom StarterNodeWidget. This QFrame-based widget is styled to visually mimic the ChatNode found in the main application, featuring a gradient background and a colored border. It contains a QLabel with setWordWrap(True) enabled, ensuring that all prompt text is fully visible and correctly formatted.
  • Expanded and Curated the List of Conversation Starters.
    • Problem: The initial list of starter prompts was minimal.
    • Solution: The number of prompts has been significantly increased to provide users with a much wider and more inspiring range of ideas to explore, from creative writing and technical questions to productivity and planning tasks.
  • Simplified the Welcome Screen UI.
    • Problem: The action buttons at the bottom of the WelcomeScreen (New Chat, Open Library) were redundant, as these functions are readily available in the main ChatWindow.
    • Solution: The entire bottom button bar has been removed, resulting in a cleaner, more focused UI that prioritizes recent projects and conversation starters.

[Beta v.0.5.8] - 2025-10-31 (Professional Markdown Rendering & Font Customization)

This release introduces a complete overhaul of the text rendering system, replacing the limited custom parser with a professional, standards-compliant Markdown engine. A new Font Control panel has been added, giving users granular control over the typography of the entire canvas for the first time.

Architectural Refactor

  • Replaced Custom Text Parsing with a Standard Markdown-to-HTML Pipeline.
    • Problem: The previous system used a rudimentary parser for a few custom tags (e.g., [h1]), which was inflexible and did not support common Markdown syntax like multiple heading levels, blockquotes, or lists.
    • Solution: The rendering logic in ChatNode has been completely refactored. The TextBlock and custom parsing functions have been removed. The node now utilizes the standard markdown library to convert raw text into HTML, which is then rendered by a QTextDocument. A default CSS stylesheet is applied to the document, ensuring all HTML elements (<h1>, <p>, <ul>, etc.) are styled professionally and consistently.

Added

  • Implemented a Global Font Control System.
    • Feature: A new "Font" panel is now available under the "Controls" menu. This UI provides real-time control over the font family, base font size, and text color for all ChatNode and DocumentNode items on the canvas.
    • Implementation: A FontControl widget was created with signals for each setting. The ChatScene now manages the global font state and contains new setter methods (setFontFamily, setFontSize, setFontColor). These methods, when triggered by the UI, call a new _update_all_node_fonts function that iterates through all relevant nodes and instructs them to re-render with the new styles.

Changed

  • Node Architecture Updated to Support Dynamic Styling.
    • Problem: Nodes were previously unaware of global style changes and would not update after being created.
    • Solution: The ChatNode and DocumentNode classes now feature an update_font_settings method, which rebuilds the node's stylesheet and recalculates its geometry. Furthermore, the itemChange method was overridden to detect when a node is added to the scene, immediately applying the scene's current font settings and ensuring style consistency for newly created nodes.

Fixed

  • Resolved Critical Rendering Bugs Related to Recent Changes.
    • Problem: A regression caused user-sent messages to appear as blank nodes. Additionally, a QPainter state error was logged due to improper rendering in the new DocumentNode.
    • Solution: The logic in graphite_app.py was corrected to ensure that simple text messages are passed to the ChatNode constructor as a raw string, fixing the blank node issue. The DocumentNode.paint method was corrected to use document.drawContents(), which properly manages the painter's state and resolves the rendering warning.

[Beta v.0.5.7] - 2025-10-31 (Ollama Multimodal Support)

This release extends multimodal (text and image) input support to the local Ollama provider, enabling models like qwen3-vl:8b to process visual information. This brings feature parity with the Gemini API provider for a core interaction capability.

Architectural Refactor

  • Decoupled Message Formatting from API Calls for Ollama.
    • Problem: The api_provider.chat function directly passed its messages argument to the ollama.chat call, which only worked for text-based messages. It lacked the logic to handle the application's internal format for multimodal content (a list of dictionaries for text and image parts).
    • Solution: A new message preparation layer has been introduced specifically for the Ollama provider. Before making the API call, the chat function now passes the messages list to a new _prepare_ollama_messages helper function. This function is responsible for transforming the internal message structure into the {'content': '...', 'images': [...]} format required by the ollama-python library, cleanly separating data transformation from the API interaction logic.

Added

  • Implemented a Dedicated Message Formatter for Ollama Multimodal Payloads.
    • Feature: The new _prepare_ollama_messages function in api_provider.py now correctly processes mixed-content messages. It iterates through the content parts, aggregates all text into a single string for the content key, and compiles all image byte data into a list for the images key.
    • Benefit: This enables seamless support for any multimodal Ollama model (e.g., llava, qwen3-vl:8b) without requiring model-specific logic. The system now automatically handles image data whenever it's present in a user's message, regardless of the selected Ollama model.

[Beta v.0.5.6] - 2025-10-30

This release delivers the first fully functional plugin, "System Prompt," which allows for dynamic, per-conversation customization of the AI agent's behavior. This milestone validates the new plugin architecture and introduces a powerful new layer of user control.

Architectural Refactor

  • Integrated Node Context into AI Agent Logic for Dynamic System Prompts.
    • Problem: The core ChatWorker was stateless and unaware of the canvas, using a single, hard-coded system prompt for all interactions.
    • Solution: The ChatWorker and ChatWorkerThread have been refactored to accept the current_node as context. Before generating a response, the worker now traverses the node's hierarchy to find its root and checks for a connected SystemPromptConnectionItem. If found, it uses the content of the attached Note as the system prompt for that specific API call, effectively overriding the default behavior for that entire conversation branch.

Added

  • Implemented the "System Prompt" Plugin.
    • Feature: Users can now add a special "System Prompt" node to any conversation branch via the "Plugins" menu. This node, a specially styled Note item, allows the user to write custom instructions that override the default AI persona for that specific branch.
    • Implementation: A new SystemPromptConnectionItem class was created to visually and logically link a Note to a ChatNode. The plugin logic in PluginPortal handles the creation of these items. The core AI agent logic in graphite_agents.py was then updated to detect and utilize these connections, creating a fully integrated and context-aware system.

Changed

  • Redesigned the System Prompt Connector for Professional Visual Feedback.
    • Problem: The initial version of the SystemPromptConnectionItem was a visually jarring, static dashed line that did not update when nodes were moved.
    • Solution: The connector has been completely redesigned. It is now a smooth, S-shaped Bezier curve that dynamically updates its path when connected nodes are moved. A QVariantAnimation was added to create a subtle, continuous pulsing glow effect, visually signifying the flow of instructions from the prompt to the conversation, providing an elegant and intuitive user experience.

Fixed

  • Resolved Multiple Critical Crashes Related to the New Plugin System.
    • Problem: A TypeError occurred because QVariantAnimation was incorrectly parented to a QGraphicsItem. After fixing this, a RuntimeError would occur because the animation was not being stopped when the connection item was deleted, leading it to call methods on a destroyed object.
    • Solution: The animation's constructor was corrected to be parentless. More importantly, the itemChange method in SystemPromptConnectionItem was overridden to detect when the item is being removed from the scene. It now explicitly calls .stop() on the animation, properly managing its lifecycle and preventing any further memory-related crashes.
  • Fixed a Bug Where System Prompt Connectors Would Not Update When Nodes Moved.
    • Problem: The scene's update logic was not aware of the new SystemPromptConnectionItem type, causing the connectors to remain static when their attached nodes were moved.
    • Solution: The ChatScene.update_connections method was updated to iterate over and update system_prompt_connections. Additionally, the Note.itemChange method was modified to notify the scene of position changes, ensuring all attached connection types are correctly redrawn.

[Beta v.0.5.6] - 2025-10-30 (Canvas Interactivity and Alignment Overhaul)

This update introduces a suite of powerful canvas manipulation features, including grid snapping, smart alignment guides, and orthogonal connection routing. These tools provide users with granular control over node layout and improve the organization of complex graphs.

Architectural Refactor

  • Centralized Snapping and Alignment Logic into ChatScene.
    • Problem: Snapping behavior was previously implemented inconsistently within individual QGraphicsItem classes (Note, ChartItem), leading to code duplication and making it impossible to toggle globally.
    • Solution: All snapping and alignment logic has been removed from individual items and consolidated into a single, authoritative snap_position method within ChatScene. Movable items now delegate their position changes to this method, which intelligently applies grid snapping and smart guide alignment based on the user's settings.

Added

  • Implemented "Snap to Grid" Functionality.
    • Feature: A new "Snap to Grid" checkbox in the "Controls" panel allows users to toggle grid snapping for all movable items. When enabled, dragging an item will cause it to snap to the nearest grid intersection.
  • Introduced "Smart Guides" for Dynamic Alignment.
    • Feature: When the "Smart Guides" checkbox is enabled, moving an item will now display temporary alignment lines. These guides appear when the item's edges or center align with other items on the canvas, enabling precise and intuitive layout adjustments.
  • Added "Orthogonal Connections" Routing Option.
    • Feature: A new "Orthogonal Connections" checkbox in the "Controls" panel switches the main ConnectionItem rendering style. When enabled, connections are drawn as right-angled lines instead of curves, offering a more structured, schematic-like visual appearance.

Changed

  • Expanded the "Controls" Panel with New Options.
    • UI: The GridControl widget has been redesigned to include a new "Alignment & Routing" section, which houses the checkboxes for Snap to Grid, Smart Guides, and Orthogonal Connections.
    • Behavior: The "Controls" panel is now hidden by default on application startup to provide a cleaner initial workspace. The corresponding toolbar button's state is correctly set to False on launch.

Fixed

  • Resolved a Long-Standing Bug Causing a "Stuck" Panning Cursor.
    • Problem: The panning cursor (a closed hand) would occasionally fail to revert to the default arrow cursor if the middle mouse button was released outside the application window.
    • Solution: The mouseMoveEvent in ChatView now includes a state-correction check. It verifies the actual mouse button state against the application's internal panning flag and forcibly resets the cursor if a discrepancy is detected, ensuring the UI state remains synchronized with user actions.

[Beta v.0.5.6] - 2025-10-30 (Axiom Demo Mode and Rate Limiting)

This update introduces "Axiom" mode, a pre-configured, rate-limited demonstration of the Gemini API. It allows all users, regardless of license status, to immediately test the application's cloud-based AI capabilities without needing their own API key.

Architectural Refactor

  • Expanded the Licensing System to Manage Usage-Based Rate Limits.
    • Problem: The LicenseManager was only designed to track perpetual states like trial periods and license validity. It had no mechanism for tracking transient, usage-based metrics.
    • Solution: The LicenseManager's persistent state file (session.dat) has been updated to include an axiom_usage object. This object tracks the number of API calls (count) and the start of a rolling 4-hour window (window_start). New methods (can_use_axiom, record_axiom_usage, get_axiom_reset_time_str) were added to manage this data, ensuring that rate limits are correctly enforced and reset.

Added

  • Introduced "Axiom" Mode for Instant API Access.
    • Feature: A new "Axiom" option has been added to the mode selection dropdown. This mode utilizes a hard-coded developer API key for Gemini's gemini-flash-latest model.
    • Implementation: The core api_provider was modified to recognize the "Axiom" provider type. When selected, it initializes the Gemini client with the developer key and routes all chat requests to the pre-configured model, bypassing the need for user-provided settings.
  • Implemented a Non-Modal Notification Banner for UI Feedback.
    • Feature: A custom NotificationBanner widget now provides unobtrusive feedback, such as rate-limit warnings. It animates up from the bottom of the window and automatically dismisses after a set duration.
    • Implementation: The send_message and regenerate_node methods in ChatWindow now check license_manager.can_use_axiom() before proceeding. If the limit is reached, the new banner is displayed with a message indicating when the limit will reset, preventing a disruptive QMessageBox from appearing.

Changed

  • Separated User License Status from API Mode Functionality.
    • Clarification: The Axiom mode's rate limit of 3 messages per 4 hours applies universally to all users. A user with a paid license who requires unlimited API access is expected to use the "API Endpoint" mode and provide their own key.
    • Behavior: The "Settings" button in the toolbar is now disabled when Axiom mode is active, reinforcing that it is a pre-configured demo with no user-editable options.

[Beta v.0.5.5] - 2025-10-30

This release introduces a foundational plugin system and refines the main toolbar's visual design for a cleaner, more professional user experience. These changes create a scalable architecture for future features while improving the application's overall aesthetic.

Architectural Refactor

  • Established a Decoupled Plugin Architecture with a Central PluginPortal.
    • Problem: The application lacked a dedicated, scalable system for adding new tools or features, which would lead to code coupling and maintenance issues.
    • Solution: A new graphite_plugin_portal.py module was created, housing a PluginPortal class. This class is responsible for discovering, managing, and executing all plugins. It acts as a clean architectural boundary, allowing new features to be added as self-contained "plugins" without modifying the core application logic. The main window instantiates the portal, providing a controlled context for plugins to interact with the application.

Added

  • Added a "Plugins" Dropdown Menu to the Main Toolbar.
    • Feature: A new "Plugins" menu now appears on the main toolbar, providing a centralized and user-accessible entry point for all integrated tools and extensions.
    • Implementation: The setup_toolbar method in graphite_app.py was updated to include a QComboBox for plugins. This dropdown is dynamically populated with a list of available plugins retrieved from the PluginPortal. Selecting an item triggers the execution of the corresponding plugin and resets the menu, creating an intuitive action-oriented experience.

Changed

  • Refined Toolbar UI for a Cleaner, More Professional Aesthetic.
    • Problem: The main toolbar buttons used solid background colors, which appeared dated and visually busy. Furthermore, the newly added "Plugins" menu was initially implemented as a QToolButton, creating a visual inconsistency with the adjacent QComboBox used for mode selection.
    • Solution: The stylesheets in graphite_app.py and graphite_styles.py were updated to give toolbar buttons a transparent background by default. Color is now used exclusively to provide feedback on hover, creating a minimalist and modern appearance. The "Plugins" menu was re-implemented as a QComboBox to perfectly match the "Mode" selector, ensuring a visually cohesive and professional toolbar design.

[Beta v.0.5.4] - 2025-10-30

This release overhauls the canvas grid system, transforming it from a static background pattern into a dynamic, professional, and fully customizable visual tool. The new grid adapts to the user's zoom level and offers multiple styles for a personalized workspace.

Added

  • Added Comprehensive Grid Customization Options.
    • Feature: Users can now fully personalize the canvas grid. The GridControl widget has been expanded to include new options for changing the grid's visual style (Dots, Lines, or Cross) and its color, in addition to the existing size and opacity controls.
    • Implementation: The GridControl widget in graphite_widgets.py was updated with new UI buttons and state variables (grid_style, grid_color). The drawBackground method in ChatView now reads these properties to render the grid accordingly.

Changed

  • Overhauled Grid Rendering to be Dynamic and Zoom-Aware.
    • Problem: The previous grid was a simple, static dotted line pattern that did not adapt to the user's zoom level. This resulted in visual clutter when zoomed out and a lack of detail when zoomed in, creating an unprofessional appearance.
    • Solution: The drawBackground method in ChatView has been completely rewritten. It now renders a multi-level grid with distinct "major" and "minor" lines. These lines intelligently appear and disappear at different zoom thresholds (LOD_MAJOR, LOD_MINOR), and their thickness scales appropriately. This provides a clean, professional-grade drafting experience that is always visually suitable for the current level of detail.

[Beta v.0.5.3] - 2025-10-30

This is a major stability and usability release that restores critical functionality, overhauls key UI components, and refactors core systems for improved modularity. The "Navigation Pins" panel has been completely re-architected into a true floating overlay, and the "Create Frame" feature has been robustly re-implemented.

Architectural Refactor

  • Re-architected the "Navigation Pins" Panel as a True Floating Overlay.
    • Problem: The PinOverlay was previously embedded directly into the main window's layout, permanently consuming screen real estate and creating an intrusive user experience. Its internal collapse logic was flawed and buggy.
    • Solution: The PinOverlay has been completely re-architected. It is now a child of the ChatView, making it a true floating overlay that sits on top of the canvas. Its visibility is now controlled by a dedicated "Pins" button in the main toolbar, providing a global and reliable toggle. All internal collapse/expand logic has been removed in favor of this superior architecture.
  • Centralized Command Palette Functionality into a Dedicated Module.
    • Problem: The logic for the command system was split between graphite_core.py (for CommandManager) and graphite_dialogs.py (for CommandPaletteDialog), hindering maintainability.
    • Solution: Both classes have been moved into a new, dedicated graphite_command_palette.py module. This encapsulation improves modularity and simplifies future development of the command system.

Added

  • Re-enabled "Create Frame" with a New Shortcut (Ctrl+G) and Command Palette Integration.
    • Feature: Users can now once again create frames around selected nodes. This core organizational feature is accessible via the new Ctrl+G shortcut and is discoverable in the Command Palette (Ctrl+K) as "Create Frame From Selection."
    • Implementation: The feature was re-implemented using a global QShortcut, which bypasses any potential event conflicts. The command was also registered with the CommandManager, with a corrected condition that makes it available whenever one or more nodes are selected.

Changed

  • Redesigned and Resized the "Navigation Pins" Panel for Professionalism and Usability.
    • Problem: The panel's visual design was inconsistent, too small to be functional, and lacked a conventional close button.
    • Solution: The panel's styling has been meticulously updated to match the elegant, floating design of the CommandPalette. Its default size has been significantly increased, and a dedicated "Close" button has been added to its header. This button correctly interacts with the main toolbar toggle via a signal-and-slot mechanism, ensuring a conventional and intuitive user experience.

Fixed

  • Fixed a series of critical bugs that made the "Navigation Pins" panel unusable.
    • Problem: The panel's internal collapse button would disappear, making it impossible to re-expand. After being re-architected, the new external close button would then cause a fatal AttributeError crash.
    • Solution: The entire flawed collapse mechanism was removed. The crash was resolved by implementing a proper signal-and-slot connection between the panel's "Close" button and the main window, fully decoupling the components and ensuring robust operation.
  • Fixed a critical regression where the "Create Frame" feature was completely inaccessible.
    • Problem: A shortcut conflict (Ctrl+F being reassigned to "Find") and an incorrect command palette condition made it impossible to create frames.
    • Solution: The conflicting event handler was removed, a new, unambiguous shortcut (Ctrl+G) was assigned via QShortcut, and the command's availability condition was corrected, fully restoring the feature.
  • Fixed a visual bug where CodeNode connections would not update when moving a parent Frame.
    • Problem: When a Frame was moved or resized, the dashed lines connecting CodeNodes would remain frozen in their original positions.
    • Solution: The Frame.mouseMoveEvent method was updated to correctly iterate through and update all connection types (connections and content_connections), ensuring all lines are redrawn properly during transformations.
  • Fixed a fatal ImportError crash on startup.
    • Problem: The refactoring of the Command Palette into its own module was incomplete, as the main application was still trying to import classes from their old locations.
    • Solution: All import statements in graphite_app.py were updated to correctly reference the new graphite_command_palette.py module, resolving the crash.

[Beta v.0.5.1] - 2025-10-30

This release improves the user's ability to customize their workspace by adding a feature to toggle the visibility of on-canvas controls. It also resolves a critical UI layout bug that affected the application's initial appearance.

Added

  • Added the Ability to Show/Hide On-Canvas View Controls.
    • Feature: Users can now hide or show the on-canvas widgets for adjusting grid settings and drag sensitivity. This allows for a cleaner, less cluttered workspace when these controls are not needed.
    • Implementation: A new checkable "Controls" button has been added to the main toolbar. This button is connected to a new toggle_overlays_visibility() method in the ChatView class, which manages the visibility of the GridControl and drag sensitivity widgets. The layout logic was also updated to ensure other overlays (like the search bar) correctly reposition themselves when the controls are hidden.

Fixed

  • Fixed a critical UI bug where view control widgets were incorrectly positioned at the top-left on startup.
    • Problem: On initial application launch, the GridControl and drag sensitivity widgets would appear stacked at the (0,0) coordinate of the view instead of their correct top-right position. The layout would only correct itself after user interaction.
    • Solution: The root cause was identified as a layout timing issue. The initial positioning logic was being called before the ChatView had received its final geometry from the main window. The fix involved overriding the showEvent method in ChatView. This ensures that the initial positioning of the overlays is now performed only once, at the moment the view is first displayed and guaranteed to have a valid, stable size, resolving the visual bug completely.

[Beta v.0.5.0] - 2025-10-30

This release introduces a centralized "New Chat" command, improving accessibility and standardizing session management. This update also adds dynamic window titles for better user context and completes a robust refactoring of the session clearing logic.

Added

  • Added a Universal "New Chat" Command and Shortcut (Ctrl+T).
    • Feature: Users can now start a new chat session instantly from anywhere in the application, either by pressing the Ctrl+T keyboard shortcut or by searching for "New Chat" in the command palette (Ctrl+K).
    • Implementation: The logic for creating a new chat has been centralized into a new new_chat() method within the main ChatWindow class. This method is now registered with the CommandManager and linked to a new QShortcut, making it a globally accessible action.

Changed

  • The Main Window Title is now Dynamic and Displays the Current Chat Name.
    • Problem: The window title was static and did not provide context about the currently loaded chat session.
    • Solution: A new update_title_bar() method has been implemented in ChatWindow. This method dynamically constructs the window title by combining the application name with the title of the current chat session (if one is loaded) and the license status. This method is now called whenever a new chat is created or an existing one is loaded, providing immediate and clear context to the user.

Architectural Refactor

  • Centralized and Hardened the "New Chat" Session Clearing Logic.
    • Problem: The original logic for starting a new chat was located within the ChatLibraryDialog and was incomplete. It would clear the main ChatScene but failed to reset other critical state variables and UI elements, such as the current_node reference, message input placeholder, and various lists within the scene (code_nodes, pins, etc.).
    • Solution: All session clearing logic has been consolidated into the new ChatWindow.new_chat() method. This method now performs a comprehensive reset of the application state, including explicitly clearing all item lists within the ChatScene, resetting the current_node reference in the main window, and updating the UI to its default state, ensuring a clean and reliable transition between sessions.

[Beta v.0.4.9] - 2025-10-29

This release addresses critical bugs in the "Regenerate Response" feature and introduces a new, context-aware loading animation that significantly improves the user experience during AI operations.

Added

  • Added a Contextual, Node-Specific Loading Animation.
    • Feature: The previous full-screen, text-based loading overlay has been replaced with a visually appealing, animated spinner that appears directly next to the node awaiting a response. This provides clear, non-disruptive feedback, indicating exactly which part of the conversation is being processed.
    • Implementation: A new LoadingAnimation class, inheriting from QGraphicsObject, was created in graphite_widgets.py. This class uses QPropertyAnimation to render a smooth, multi-arc spinning animation. The main ChatWindow logic was refactored to instantiate this item on the ChatScene and position it adjacent to the source node whenever a background AI task (e.g., sending a message, regenerating, creating a chart) is initiated.

Fixed

  • Fixed a critical logic error where "Regenerate Response" would fail due to missing context.
    • Problem: The regeneration feature was incorrectly providing the model with the conversation history of the node being replaced, which lacked the essential preceding user query. This caused the model to have zero context, resulting in irrelevant or nonsensical regenerated responses.
    • Solution: The logic in ChatWindow.regenerate_node() has been corrected. It now correctly and robustly fetches the conversation_history from the parent node of the node being regenerated. This ensures the model always receives the full and accurate conversational context, including the original query it needs to answer again.
  • Fixed a fundamental architectural bug where regenerating a response would break its connection to the conversation branch.
    • Problem: The previous implementation would delete the original node and create a new one, visually and contextually severing it from its place in the conversation graph.
    • Solution: The regeneration logic has been completely re-architected. Instead of deleting and recreating the node, the handle_regenerated_response method now updates the existing ChatNode in-place. A new update_content method was added to the ChatNode class to handle the replacement of its text, history, and associated CodeNodes, fully preserving its position and connections within the graph.
  • Fixed a fatal TypeError crash caused by an incorrect class inheritance in the new LoadingAnimation.
    • Problem: The LoadingAnimation was initially created by inheriting from QGraphicsItem, which is not a QObject subclass and therefore cannot be animated with QPropertyAnimation, causing the application to crash.
    • Solution: The LoadingAnimation class was corrected to inherit from QGraphicsObject, which is the proper Qt class for graphics items that require support for signals, slots, and properties, resolving the crash.
  • Fixed a NameError crash in graphite_widgets.py due to a missing import.
    • Problem: The LoadingAnimation class used QRectF without importing it, causing a crash whenever it was instantiated.
    • Solution: The missing QRectF class has been added to the import statement from PySide6.QtCore, resolving the error.

[Beta v.0.4.8] - 2025-10-29

This release introduces a major new feature for handling and displaying code, significantly improving the user experience for developers and technical users. AI-generated responses containing code blocks are now automatically parsed and rendered in a dedicated, syntax-highlighted CodeNode, visually separating them from conversational text.

Added

  • Added Automatic Code Block Detection and Syntax Highlighting.
    • Feature: The application can now automatically detect markdown-style code blocks (e.g., ```python...```) in AI responses. Each detected block is rendered in a new, specialized CodeNode with full syntax highlighting, powered by the pygments library. This makes code significantly easier to read, understand, and copy.
    • Implementation:
      • A new CodeNode class was created in graphite_node.py, which uses a QTextDocument to render HTML generated by pygments, providing rich, styled text.
      • The handle_response method in graphite_app.py was updated with a regex-based parser to intelligently split incoming AI responses into separate text and code segments.
      • A new ContentConnectionItem was added to graphite_items.py to create a distinct visual link (a dashed line) between a parent ChatNode and its child CodeNode, clarifying their relationship.
      • The ChatSessionManager was enhanced to serialize and deserialize the new CodeNodes and their connections, ensuring they are saved and loaded correctly with the chat graph.

Architectural Refactor

  • Integrated pygments for Robust Syntax Highlighting.
    • Problem: Displaying code as plain text is difficult to read and unprofessional. A robust, extensible solution for code rendering was needed.
    • Solution: The pygments library has been integrated as a core dependency. A new CodeHighlighter utility class was added to graphite_node.py to abstract the highlighting logic. This class dynamically generates CSS and HTML from Python code, supporting a wide range of languages and providing a high-quality, professional rendering experience within the new CodeNode. The system is designed to fall back gracefully to plain text if a language is not specified or recognized.

[Beta v.0.4.7] - 2025-10-29

This release introduces the Command Palette, a major new usability feature that provides fast, keyboard-driven access to nearly all application functions. This update also includes a key architectural refactoring of item deletion logic, centralizing it to support the new command system and improve maintainability.

Added

  • Added the Command Palette for Quick, Keyboard-Driven Actions (Ctrl+K).
    • Feature: Users can now press Ctrl+K to open a searchable command palette, similar to those found in modern code editors. This provides instant, text-based access to a wide range of actions, such as "Collapse All Nodes," "Delete Selected Items," "Generate Bar Chart," and "Fit All to View," dramatically speeding up user workflow.
    • Implementation: The feature is powered by a new CommandManager class (graphite_core.py) responsible for registering commands, their aliases, and context-sensitive availability (e.g., "Delete Selected" is only available when items are selected). A new CommandPaletteDialog (graphite_dialogs.py) provides the search UI, and the main ChatWindow now registers all core application functions as commands.

Architectural Refactor

  • Refactored and Centralized Item Deletion Logic.
    • Problem: Previously, the logic for deleting different item types was fragmented across the codebase. The complex logic for deleting a ChatNode (which involves re-parenting its children) was located exclusively within its context menu, making it non-reusable for a global "Delete Selected" command.
    • Solution: All deletion logic has been centralized within the ChatScene class. The ChatNode deletion algorithm was moved into a new delete_chat_node method. The primary deleteSelectedItems method was enhanced to iterate through all selected items and call the correct deletion function for each type (ChatNode, Frame, Note, etc.). This refactoring was essential for implementing the unified "Delete Selected Items" command in the new Command Palette.

[Beta v.0.4.6] - 2025-10-29

This release introduces a powerful new usability feature for focusing on specific conversation paths and completes a significant architectural refactoring to improve modularity and resolve critical import errors.

Added

  • Added "Hide Other Branches" Feature to Focus on Specific Conversations.
    • Feature: Users can now right-click any node and select "Hide Other Branches" from the context menu. This action visually dims and de-emphasizes all nodes that are not part of the selected node's direct lineage (i.e., its ancestors and descendants). This allows users to instantly focus on a single, coherent line of thought within a complex, branching graph.
    • Implementation: The feature is managed by a new state variable and a toggle_branch_visibility() method within the ChatScene class. When activated, the method traces the full path of the selected branch and sets an is_dimmed flag on all other nodes. The rendering logic in ChatNode was updated to draw a semi-transparent overlay when this flag is active. The context menu dynamically updates to "Show All Branches," allowing the user to easily restore the view.

Architectural Refactor

  • Decomposed the monolithic graphite_items.py module for improved modularity.
    • Problem: The graphite_items.py file was responsible for both general-purpose canvas items (like Frame, Note, Pin) and the highly complex, multi-component ChatNode. This violated the Single Responsibility Principle and made the codebase harder to navigate and maintain.
    • Solution: All classes directly related to the chat node functionality have been extracted into a new, dedicated graphite_node.py file. This includes ChatNode, TextBlock, ImageBlock, ScrollBar, and ChatNodeContextMenu. This refactoring clarifies the separation of concerns, with graphite_items.py now serving as a library for generic canvas elements and graphite_node.py encapsulating all chat node logic.

Fixed

  • Fixed a fatal application crash (ImportError) caused by a circular dependency.
    • Problem: The architectural refactoring inadvertently created a circular import loop where graphite_node.py imported graphite_items.py, which in turn imported graphite_node.py, causing the application to crash on startup.
    • Solution: The unnecessary import of ChatNode from graphite_items.py was identified and removed. The classes within graphite_items.py do not need compile-time knowledge of ChatNode, as they operate on instances passed at runtime. Removing this import successfully broke the dependency cycle and restored application stability.

[Beta v.0.4.5] - 2025-10-29

This release addresses several significant visual and architectural flaws within the ChatNode component that were introduced in the previous version. The primary focus was on creating a robust and permanent solution to the layout conflicts between the text content, the scrollbar, and the collapse/expand button, ensuring a clean and professional UI under all conditions.

Fixed

  • Fixed a critical UI rendering bug where the collapse/expand button would overlap the text content.
    • Problem: Previous attempts to fix the layout resulted in a state where, if a node's content was not long enough to require a scrollbar, the collapse button would be drawn directly on top of the text field.
    • Solution: The rendering and layout architecture of the ChatNode has been fundamentally corrected. A permanent, reserved space ("gutter") is now established on the right side of every node. The text layout logic was updated to never enter this gutter, guaranteeing that its content can never overlap with UI controls. The button's positioning logic was then simplified to reliably place it within this safe, reserved area, resolving the conflict in all states.
  • Fixed a major regression where the scrollbar would overlap the collapse button.
    • Problem: An incorrect fix for the text overlap issue reintroduced the original bug where the scrollbar and collapse button would render on top of each other, making both components difficult to use.
    • Solution: The paint method was corrected to implement a strict, state-dependent positioning rule. It now explicitly checks if the scrollbar is visible. If it is, the button is placed to the left of the scrollbar; otherwise, it is placed at the far-right edge of the node. This dual-state logic ensures the two components can never occupy the same space.
  • Fixed a fatal application crash (QPainter::end: Painter ended with 2 saved states) and disappearing nodes.
    • Problem: An incorrect attempt to fix the rendering order led to a critical painter state imbalance, where painter.save() was called without a corresponding painter.restore(). This corrupted the Qt rendering pipeline, causing the application to crash and ChatNode items to fail to render entirely.
    • Solution: The paint method has been corrected to use a properly balanced painter.save()/painter.restore() block. This block now safely encapsulates the clipping and drawing of the text content, ensuring the painter state is always correctly managed and preventing any rendering crashes or visual corruption.

[Beta v.0.4.4] - 2025-10-28

This release enhances canvas usability by introducing a node collapse feature, allowing users to manage complex conversation graphs more effectively. It also includes fixes for visual artifacts that appeared as a result of the new functionality.

Added

  • Added Node Collapse/Expand Functionality.
    • Feature: Users can now minimize nodes to a compact state, reducing visual clutter and making it easier to navigate large, branching conversations. This is a crucial tool for focusing on specific thought threads while hiding less relevant ones.
    • Implementation: The ChatNode class now manages a is_collapsed state. The feature is accessible via two intuitive methods: a new "Collapse/Expand" option in the right-click context menu, and a hover-activated icon that appears in the top-right corner of the node for quick, direct interaction. When a node's state is changed, all associated connections and parent frames automatically adjust to the new geometry.
  • Added Persistence for Node Collapse State.
    • Feature: The collapsed or expanded state of every node is now saved with the chat session and is fully restored when the session is loaded.
    • Implementation: The ChatSessionManager has been updated to serialize the is_collapsed boolean for each node into the database and deserialize it upon loading, ensuring a consistent and predictable layout across sessions.

Fixed

  • Fixed a critical UI bug where the scrollbar remained visible on collapsed nodes.
    • Problem: When a node with scrollable content was collapsed, its scrollbar was not being hidden, leaving a detached and visually disruptive UI element on the canvas.
    • Solution: The logic in the ChatNode._update_geometry_for_state() method has been corrected to explicitly set the ScrollBar's visibility to False whenever the node enters a collapsed state, completely resolving the visual artifact.

[Beta v.0.4.3] - 2025-10-28

This is a minor release focused on improving the core visual aesthetic of the application's chat canvas, moving from a flat design to one with more perceived depth and professionalism.

Changed

  • Enhanced the visual design of ChatNode items for a more professional aesthetic.
    • Problem: The previous design used solid, flat colors (green and blue) for the node backgrounds. While functional, this created a visually simplistic and less polished look.
    • Solution: The node's rendering logic in the ChatNode.paint() method has been updated. The solid color fill has been replaced with a subtle gray gradient, giving the nodes a sense of depth. The node's origin (user or AI) is now indicated by a colored outline (green for user, blue for AI) rather than the entire background, resulting in a cleaner and more professional appearance.

[Beta v.0.4.2] - 2025-10-27

This release completes the major UI overhaul by standardizing all window frames across the application, resulting in a more professional and cohesive user experience. The focus was on eliminating custom, non-native windowing solutions in favor of robust, OS-level implementations.

Changed

  • Unified the Main Window and all Dialogs to use Native OS Window Frames.
    • Problem: The main application window and several key dialogs (Library, Help, About, Activation) were using a custom, frameless implementation that required significant boilerplate code to replicate basic window functions. This created a visual and functional disconnect from standard dialogs and lacked the robustness of native window management.
    • Solution: All custom frameless window implementations have been removed and replaced with standard, native window frames. The CustomTitleBar class is now obsolete, and all windows now leverage the host operating system's window manager for a consistent look, feel, and behavior (including features like window snapping and native shadows).
  • Improved User Help Dialog Content.
    • Problem: The descriptions in the "Help" dialog were overly brief and often failed to explain how or why a feature should be used, limiting their value for new users.
    • Solution: All help text has been rewritten to be more detailed, descriptive, and action-oriented. The new content provides clear, step-by-step instructions, explains core application concepts (like "Contextual Replies"), and includes keyboard shortcuts to improve feature discovery and user onboarding.

Fixed

  • Fixed a critical bug where the native close ("x") button was disabled on all refactored windows.
    • Details: The process of removing the custom frameless hints inadvertently dropped the WindowCloseButtonHint flag, causing the window manager to disable the close button. This flag has been explicitly re-added to the main window and all refactored dialogs, restoring essential functionality.
  • Fixed an architectural flaw by relocating the main window icon logic.
    • Details: The application's primary icon was being incorrectly set from within the now-obsolete CustomTitleBar class. This logic has been moved to the main ChatWindow's __init__ method, where it properly belongs.

[Beta v.0.4.1] - 2025-10-27

This release is a continuation of the major architectural refactoring initiated in the previous version. The focus was to dismantle the large graphite_graphics.py file, further improving modularity and clarifying the separation between UI components.

Architectural Refactor

  • Decomposed the monolithic graphite_graphics.py module.
    • Problem: Following the initial UI refactor, the graphite_graphics.py module remained overly large, containing both the individual graphical items (ChatNode, Frame, Note) and the container classes that manage them (ChatScene, ChatView). This co-location of distinct responsibilities hindered clarity and maintainability.
    • Solution: The single file has been broken down into two new, more focused modules, establishing a clearer hierarchy between the view and its contents:
      • graphite_items.py: This module now exclusively contains all QGraphicsItem subclasses. These classes represent the individual, interactive elements on the canvas (ChatNode, ConnectionItem, Frame, Note, ChartItem, NavigationPin, etc.).
      • graphite_view.py: This module houses the container classes (ChatScene and ChatView), which are responsible for managing, displaying, and orchestrating interactions with the graphical items.

Fixed

  • Fixed a critical ImportError crash caused by a circular dependency.
    • Details: The refactoring process inadvertently created a circular import loop: graphite_widgets imported graphite_items, which imported graphite_dialogs, which in turn imported graphite_widgets, causing the application to crash on startup. The issue was resolved by restoring a "dummy class" forward declaration for NavigationPin within graphite_widgets.py, successfully breaking the import cycle.

[Beta v.0.4.0] - 2025-10-27

This release introduces a major architectural refactoring of the user interface layer. The primary goal was to dismantle the monolithic graphite_ui.py file to improve modularity, resolve circular dependency issues, and enhance long-term maintainability.

Architectural Refactor

  • Decomposed the monolithic UI module.
    • Problem: The graphite_ui.py file had grown to include over 25 distinct classes, mixing responsibilities such as styling, core widgets, dialogs, and complex graphics scene items. This made the code difficult to navigate, debug, and maintain.
    • Solution: The single file has been broken down into four new, single-responsibility modules:
      • graphite_styles.py: Centralizes the StyleSheet class and color constants.
      • graphite_widgets.py: Contains reusable QWidget subclasses like CustomTitleBar, LoadingOverlay, and PinOverlay.
      • graphite_dialogs.py: Consolidates all QDialog-based classes.
      • graphite_graphics.py: Contains all core QGraphics... components, including custom items, the ChatScene, and the ChatView.

Fixed

  • Fixed multiple critical ImportError crashes that arose during the refactoring process.
    • Details: Resolved errors caused by incorrect import paths for Qt classes. QAction was moved from QtWidgets to its correct module, QtGui. The class QGraphicsPathStroker was corrected to its proper name, QPainterPathStroker, fixing both the import and its usage within the ConnectionItem class.
  • Fixed a TypeError crash related to the Frame animation.
    • Details: The valueChanged signal of the QVariantAnimation used for the frame's selection outline was incorrectly connected to the QGraphicsItem.update method, passing an unexpected argument. This was resolved by using a lambda function to ensure the method is called without arguments, stopping the crash loop.

[Beta v.0.3.0] - 2025-10-27

This release transitions the application from a purely functional prototype to a distributable product by introducing a robust licensing and user agreement framework. The primary focus is on ensuring a professional first-run experience, protecting the software with a trial period, and providing clear developer attribution.

Added

  • Added a 5-Day Trial and Licensing System.
    • Feature: The application now operates in a fully-featured demo mode for 5 days from the first launch. After the trial period expires, the user must enter a valid license key to continue using the software.
    • Implementation: A new graphite_licensing.py module has been created to manage all licensing logic. It creates a persistent state file (~/.graphite/session.dat) to securely track the first launch date, EULA acceptance, and activation status. The main application startup sequence in graphite_app.py has been modified to enforce these checks before the main window is launched.
  • Added a Mandatory End-User License Agreement (EULA).
    • Feature: On the very first launch, users are now presented with a modal EULA dialog. The application will not run unless the user scrolls to the bottom and explicitly agrees to the terms, which include a disclaimer of warranty and a liability clause for generated content.
    • Implementation: A new EULADialog was created in graphite_ui.py with logic to ensure full review of the text. The LicenseManager tracks the acceptance state, preventing the app from running until the EULA is accepted.
  • Added an "About" Dialog and Developer Credits.
    • Feature: A new "About" dialog is now accessible from the main toolbar, providing users with application version info, developer credits (name, contact), and a direct link to the project's GitHub repository. It also clearly displays the current license status (Trial, Licensed, or Expired).
    • Implementation: An AboutDialog class was added to graphite_ui.py and integrated into the ChatWindow toolbar.
  • Added an In-App Activation Dialog.
    • Feature: Users can now activate their software from within the application using a dedicated "Activate" dialog, which appears automatically when the trial expires or can be accessed from the toolbar.
    • Implementation: The ActivationDialog class in graphite_ui.py provides an interface for key entry and validation against the logic in graphite_licensing.py.

Changed

  • The Main Window Title is now dynamic and reflects the license status. The title bar will display "Graphite (Trial - X days remaining)" during the trial period and "Graphite (Licensed)" after successful activation, providing clear and persistent feedback to the user.
  • The main toolbar has been updated to include buttons for the new "About" and "Activate" dialogs, making these features easily accessible.

Fixed

  • Fixed a bug in the EULA dialog where the "Agree" button would remain disabled if the agreement text was too short to require scrolling. The logic was corrected to enable the button immediately if the content is fully visible upon opening, ensuring a smooth user experience regardless of screen resolution or content length.

[Beta v.0.2.2] - 2024-05-25

This release introduces support for any OpenAI-compatible API endpoint as an alternative to a local Ollama instance. It also includes a significant user experience overhaul for model and provider selection, resolving critical design flaws and improving usability.

Added

  • Added support for OpenAI-Compatible API Endpoints.
    • Feature: Users can now switch from using a local Ollama instance to any remote API service that is compatible with the OpenAI API specification (e.g., OpenAI, Groq, OpenRouter, or self-hosted solutions like LiteLLM). (Credits for first conceptual buildout/iteration of implimentations - https://github.com/1818TusculumSt)
    • Implementation: A new api_provider.py module was created to act as a router, abstracting all LLM calls and directing them to either Ollama or the configured API endpoint based on the user's selection. All agent classes (ChatAgent, KeyTakeawayAgent, etc.) were refactored to use this new provider instead of calling ollama directly.
  • Added Per-Task Model Configuration for API Mode.
    • Feature: When using an API provider, users can configure different models for different tasks (Title Generation, Chat/Analysis, and Chart Data Extraction) to optimize for cost, speed, and capability.
    • Implementation: An APISettingsDialog was created, allowing users to enter their API credentials, load a list of available models from the endpoint, and assign a specific model to each task category.

Changed

  • Overhauled the Model and Provider Selection UX.
    • Problem: The previous UI design for model selection was confusing, with separate and sometimes hidden buttons for different providers. This created a frustrating and non-discoverable user experience.
    • Solution: The toolbar has been redesigned with a clear, two-part system:
      1. A "Mode" dropdown to explicitly select the provider (Ollama (Local) or API Endpoint).
      2. A single, consistently visible "Settings" button. This button is now context-aware and will open the appropriate configuration dialog (ModelSelectionDialog for Ollama or APISettingsDialog for an API) based on the currently selected mode. This resolves all ambiguity and makes the feature intuitive to use.

Fixed

  • Fixed a critical UI bug where the API settings button was permanently invisible.
    • Problem: A logic error in the toolbar setup (self.api_settings_btn.setVisible(False)) caused the button to configure the API to be hidden, making the entire feature inaccessible.
    • Solution: The erroneous line was removed, and the toolbar was refactored to use the new unified "Settings" button, ensuring the correct dialog is always accessible.
  • Fixed an architectural violation where UI components were defined outside of graphite_ui.py.
    • Problem: The APISettingsDialog was incorrectly defined within the main application file (graphite_app.py), breaking the project's modular structure.
    • Solution: The APISettingsDialog class has been moved to its proper location within graphite_ui.py, restoring the architectural integrity and separation of concerns.

[Beta v.0.2.1] - 2024-05-25

This release focuses on critical stability and functionality fixes, primarily addressing issues within the API provider integration and the core UI rendering system.

Fixed

  • Fixed a critical application crash when loading models from the Google Gemini API.
    • Problem: The application would crash with a TypeError when fetching the model list from Gemini. A deep-dive analysis revealed this was due to a fundamental incompatibility between the installed google-generativeai library and the current data structure of the API's response. The previous design, which relied on dynamic model discovery, proved to be too brittle for this provider.
    • Solution: The architecture for the Gemini provider has been completely refactored. The brittle dynamic discovery process has been removed and replaced with a static, hard-coded list of known-stable Gemini models. The API Settings UI now intelligently adapts, hiding non-functional controls (e.g., "Load Models") for the Gemini provider and populating the model list instantly and reliably.
  • Fixed a critical logic error preventing chat messages from being sent to Gemini models.
    • Problem: After successfully configuring a Gemini model, all chat attempts would fail with an "Error: message cannot be blank."
    • Solution: The root cause was identified in the api_provider.chat() function, where a pop() operation was incorrectly removing the user's current message from the conversation history before the payload was sent to the API. This line has been removed, ensuring the complete and correct conversation context is now sent with every request.
  • Fixed a fatal application crash on startup due to incorrect UI class definition order.
    • Problem: A regression from a previous refactor caused the application to crash on launch with an ImportError and underlying NameError exceptions. Classes within graphite_ui.py (e.g., ColorPickerDialog, ConnectionItem) were being referenced before they were defined, halting the module loading process.
    • Solution: The class definitions within graphite_ui.py have been meticulously reordered to ensure a correct, top-to-bottom dependency resolution. All classes are now defined before they are instantiated or referenced, resolving the startup crash.
  • Fixed a fatal UI rendering crash related to the ChartItem class.
    • Problem: The application would enter a crash loop during the UI paint event, raising an AttributeError for a non-existent QPainter.RenderHint (HighQualityAntialiasing).
    • Solution: The erroneous line has been removed from the ChartItem.paint() method. Rendering quality is preserved by other existing and correct render hints (SmoothPixmapTransform), and the crash is fully resolved.

Changed

  • Updated the static model list for the Google Gemini provider.
    • The hard-coded list of Gemini models was updated to include the latest stable releases available through the public API, including the gemini-2.5-pro and gemini-2.5-flash series, ensuring users have access to current and powerful models.

[Beta v.0.2.0] - 2024-05-23

Architectural Refactor

  • This update introduces a major architectural refactoring to improve the project's structure, maintainability, and scalability. The application has been transitioned from a single, monolithic script into a modular, multi-file structure with a clear separation of concerns. The primary goal of this refactor was to decouple the User Interface, Core Logic, and AI Agent services from one another.
  • The new project structure is as follows:
    • graphite_app.py: Serves as the main application entry point. It contains the primary ChatWindow class and is responsible for initializing and launching the application.
    • graphite_ui.py: Consolidates all classes related to the User Interface layer. This includes all Qt widgets, dialogs, custom graphics items for the scene (ChatNode, ConnectionItem, Frame, etc.), and view components (ChatView, ChatScene).
    • graphite_core.py: Manages the application's core logic and data persistence. It contains the ChatDatabase class for all SQLite operations and the ChatSessionManager for handling the serialization and deserialization of chat sessions.
    • graphite_agents.py: Isolates all logic related to AI model interaction. This module contains the base ChatAgent as well as specialized tool agents (KeyTakeawayAgent, ExplainerAgent, ChartDataAgent) and their corresponding QThread workers for asynchronous processing.
    • graphite_config.py: A centralized location for application-wide configuration constants, such as task identifiers and default model names.
    • api_provider.py: A dedicated module to abstract away the differences between various AI providers (Ollama, OpenAI-compatible, Google Gemini), presenting a unified interface to the rest of the application.