singularity-forge/docs-internal/extending-pi/13-state-management-persistence.md
Lex Christopherson d20d5e8fb5 docs: add Mintlify documentation site and move internal docs
Add a proper public-facing documentation site using Mintlify with 19 MDX
pages covering getting started, auto mode, commands, configuration, and
all user-facing features. Move internal/SDK documentation (Pi SDK, TUI,
context & hooks, research notes, ADRs) to docs-internal/ since they
should not be part of the public documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:54:41 -06:00

1.4 KiB

State Management & Persistence

Pattern: State in Tool Result Details

The recommended approach for stateful tools. State lives in details so it works correctly with branching/forking.

export default function (pi: ExtensionAPI) {
  let items: string[] = [];

  // Reconstruct from session on load
  pi.on("session_start", async (_event, ctx) => {
    items = [];
    for (const entry of ctx.sessionManager.getBranch()) {
      if (entry.type === "message" && entry.message.role === "toolResult") {
        if (entry.message.toolName === "my_tool") {
          items = entry.message.details?.items ?? [];
        }
      }
    }
  });

  pi.registerTool({
    name: "my_tool",
    // ...
    async execute(toolCallId, params, signal, onUpdate, ctx) {
      items.push(params.text);
      return {
        content: [{ type: "text", text: "Added" }],
        details: { items: [...items] },  // ← Snapshot state here
      };
    },
  });
}

Pattern: Extension-Private State (appendEntry)

For state that doesn't participate in LLM context but needs to survive restarts:

pi.appendEntry("my-state", { count: 42, lastRun: Date.now() });

// Restore on reload
pi.on("session_start", async (_event, ctx) => {
  for (const entry of ctx.sessionManager.getEntries()) {
    if (entry.type === "custom" && entry.customType === "my-state") {
      const data = entry.data;  // { count: 42, lastRun: ... }
    }
  }
});