How the 99 Plugin's Request History System Tracks Previous Operations
The 99 Neovim plugin maintains a comprehensive audit trail of every AI request through a centralized state object that stores operations in ordered arrays and hash maps, enabling fast lookup by unique trace IDs and persistent tracking of status from initiation to completion.
ThePrimeagen's 99 plugin implements a robust request history system that records every interaction with AI providers. This system enables users to review past operations, navigate to previous request locations, and manage the lifecycle of AI-generated content. By maintaining structured state across multiple data structures in lua/99/init.lua, the plugin ensures that no operation is lost and every request remains queryable by its unique identifier.
Core State Architecture for Request History
The _99_State Object and History Fields
The request history system centers on the _99_State object defined in lua/99/init.lua. When the plugin initializes, create_99_state() instantiates several critical fields that form the backbone of the tracking system:
--- @field __request_history _99.RequestEntry[]
--- @field __request_by_id table<number, _99.RequestEntry>
...
local function create_99_state()
return {
...
__request_history = {},
__request_by_id = {},
__tutorials = {},
__searches = {},
...
}
end
These fields serve distinct purposes within the request history system:
__request_history: An ordered array of_99.RequestEntryobjects representing every request chronologically, including both in-flight and completed operations.__request_by_id: A hash map enabling O(1) lookup of any request entry by its unique trace identifier (xid).__tutorialsand__searches: Specialized collections that cache successful tutorial and search results for rapid retrieval and display.
How Operations Are Tracked
Initiating Requests with track_request
When a user triggers an AI operation—whether a search, tutorial, or visual command—the plugin constructs a RequestContext (defined in lua/99/request-context.lua) and immediately registers it with the history system via _99_State:track_request(context).
function _99_State:track_request(context)
assert(context.operation, "must have an operation defined to track the request")
local point = context.range and context.range.start or Point:from_cursor()
local entry = {
context = context,
status = "requesting",
point = point,
started_at = time.now(),
operation_data = nil,
}
table.insert(self.__request_history, entry) -- append to the ordered list
self.__request_by_id[context.xid] = entry -- map id → entry
return entry
end
This method performs three critical actions:
- Captures metadata including the cursor position (
point) and timestamp (started_at) to support later navigation and timing analysis. - Sets the initial status to
"requesting", marking the entry as in-flight. - Indexes the entry in both the chronological array and the ID-based hash map using the context's unique
xid.
Completing Requests with finish_request
When the AI provider returns a response—success or failure—the plugin invokes _99_State:finish_request(context, status) to finalize the history entry.
function _99_State:finish_request(context, status)
local id = context.xid
local entry = self.__request_by_id[id]
if not entry then return end
entry.status = status -- e.g. "success" or "error"
local data = entry.operation_data
if entry.status == "success" and data then
if data.type == "tutorial" then
table.insert(self.__tutorials, data)
elseif data.type == "search" then
table.insert(self.__searches, data)
end
end
end
This method updates the entry's status and, for successful operations, migrates the data to specialized collections. Tutorial results populate __tutorials, while search results populate __searches, enabling rapid access to historical AI outputs without traversing the entire request history.
Querying and Managing Request History
Counting and Clearing Previous Requests
The request history system provides utility methods for inventory management. The _99_State:previous_request_count() method iterates through __request_history to tally completed operations:
function _99_State:previous_request_count()
local count = 0
for _, entry in ipairs(self.__request_history) do
if entry.status ~= "requesting" then count = count + 1 end
end
return count
end
To reclaim memory and declutter the interface, _99_State:clear_previous_requests() purges all completed entries while preserving in-flight operations:
function _99_State:clear_previous_requests()
local keep = {}
for _, entry in ipairs(self.__request_history) do
if entry.status == "requesting" then
table.insert(keep, entry)
else
self.__request_by_id[entry.context.xid] = nil
end
end
self.__request_history = keep
self.__searches = {}
self.__tutorials = {}
end
Exporting to Quickfix List
For interactive navigation, the plugin exposes previous_requests_to_qfix(), which transforms the entire request history into Vim's quickfix list:
function _99.previous_requests_to_qfix()
local items = {}
for _, entry in ipairs(_99_state.__request_history) do
table.insert(items, request_entry_to_qfix_item(entry))
end
vim.fn.setqflist({}, "r", { title = "99 Requests", items = items })
vim.cmd("copen")
end
This enables users to browse historical AI requests alongside their original buffer locations, leveraging Neovim's native navigation infrastructure.
Practical Examples
Example 1: Running a Search and Inspecting History
Trigger an AI search and subsequently review the request history through the quickfix interface:
-- Initiate a search operation (automatically tracked)
require("99").search({ additional_prompt = "How does Lua table.concat work?" })
-- After the AI responds, open the quickfix list to see all historical requests
require("99").previous_requests_to_qfix()
The search function internally invokes track_request, appending the operation to __request_history. Upon completion, finish_request updates the entry status, making it visible to previous_requests_to_qfix.
Example 2: Manually Accessing the History Table
For custom UI integrations, access the raw history state directly:
local _99 = require("99")
local state = _99.__get_state() -- internal accessor
local all = state.__request_history -- raw array of request entries
for i, entry in ipairs(all) do
print(string.format(
"#%d – %s – %s – %s",
i,
entry.context.operation or "<none>",
entry.status,
vim.inspect(entry.point)
))
end
This iterates through the chronological request history, displaying each operation's type, current status, and original cursor position.
Example 3: Clearing Completed History
Manage memory and clutter by purging finished operations while preserving in-flight requests:
require("99").clear_previous_requests() -- removes all entries whose status ≠ "requesting"
print("Remaining in‑flight requests:", require("99").__get_state():active_request_count())
This demonstrates the cleanup workflow, ensuring that only active "requesting" entries remain in __request_history.
Summary
- The 99 plugin implements a dual-structure request history system using
__request_history(ordered array) and__request_by_id(hash map) to track every AI operation. - Tracking lifecycle:
track_requestcreates entries with"requesting"status, whilefinish_requestupdates status and migrates successful tutorial/search data to dedicated collections. - Fast lookup: The unique
xid(trace ID) fromRequestContextserves as the primary key for O(1) access to any historical entry. - User interface: The system exposes
previous_requests_to_qfix()for quickfix navigation,previous_request_count()for inventory, andclear_previous_requests()for memory management. - Source location: All history logic resides in
lua/99/init.lua, with context creation handled inlua/99/request-context.lua.
Frequently Asked Questions
How does the 99 plugin store request history in memory?
The plugin stores request history in two complementary Lua tables within the _99_State object: __request_history maintains chronological order for iteration, while __request_by_id provides constant-time lookup using the request's unique xid identifier. This dual-structure approach enables both sequential access for UI display and instant retrieval for status updates when AI responses arrive.
What information is captured for each request entry?
Each request entry stores the original RequestContext (including operation type and buffer coordinates), a status field tracking the lifecycle from "requesting" to "success" or "error", the cursor point for navigation, and a started_at timestamp. For completed operations, successful tutorial and search results are additionally cached in separate __tutorials and __searches collections for rapid retrieval.
How can I view or clear my request history in Neovim?
To view history, call require("99").previous_requests_to_qfix() to populate the quickfix list with all historical requests and their original buffer locations. To clear completed operations while preserving in-flight requests, invoke require("99").clear_previous_requests(), which purges finished entries from __request_history and empties the __tutorials and __searches collections.
Where is the request history logic implemented in the source code?
The core request history system is implemented in lua/99/init.lua, which defines the _99_State object containing track_request, finish_request, and management utilities like previous_request_count and clear_previous_requests. The RequestContext objects that feed into this system are constructed in lua/99/request-context.lua, while operation-specific handlers in lua/99/ops/*.lua invoke the tracking methods at the appropriate lifecycle stages.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →