dirge-agent 0.2.1

Minimalistic coding agent written in Rust, optimized for memory footprint and performance
# Session-tree control example (P4d)
#
# Demonstrates the harness/* APIs that mutate the session tree from
# Janet code. Mirrors pi's ctx.setLabel / ctx.fork / ctx.navigateTree /
# ctx.newSession / ctx.switchSession.
#
# All five APIs are queued; the host drains and applies them between
# UI events. No return value — verify side effects via /tree.
#
# Usage:
#   /label <text>     — bookmark the most recent entry on the current
#                        branch. Pass no text to clear it.
#   /fresh            — persist the current session and start a new
#                        one in place. Keeps the model/provider.

# Register the hook so dirge actually dispatches it. Bare names in
# this vector get auto-aliased to `<stem>-<hook>` (so this resolves
# to `session_tree-on-message-update`) — dirge's hook surface uses
# `on-message-update`, not `on-message`. The earlier version of this
# plugin declared `(def hooks [])` and defined `on-message`, so the
# function was loaded but never fired, leaving /label permanently
# stuck on "no entry yet".
(def hooks ["on-message-update"])

# Track the most-recent entry-id we've seen across on-message-update
# hooks so /label can attach to it without the user typing a uuid.
(var last-entry-id nil)

(defn on-message-update [ctx]
  # Plugin receives the in-progress turn id via ctx; we stash it
  # so the label command has something to target. The dirge hook
  # surface ships `:index` (turn ordinal) and `:partial`; if a
  # future host bumps the context to include `:id`, this picks it
  # up automatically.
  (when-let [id (or (get ctx :id) (get ctx :index))]
    (set last-entry-id (string id))))

(defn label-handler [args]
  (cond
    (nil? last-entry-id)
      "no entry yet — send a message first"
    (= (length args) 0)
      (do
        (harness/set-label last-entry-id nil)
        "cleared label")
    (do
      (harness/set-label last-entry-id args)
      (string "labeled \"" args "\""))))

(defn fresh-handler [_args]
  # newSession preserves the model + provider; the host wipes
  # messages, tree, and store, then reloads the chat view.
  (harness/new-session)
  "starting fresh session")

(harness/register-command "label" "label-handler")
(harness/register-command "fresh" "fresh-handler")