Split flat docs/ into user-docs/ (guides, config, troubleshooting) and dev/ (ADRs, architecture, extension guides, proposals). Updated docs/README.md index to reflect new paths.
55 lines
1.4 KiB
Markdown
55 lines
1.4 KiB
Markdown
# 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.
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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: ... }
|
|
}
|
|
}
|
|
});
|
|
```
|
|
|
|
---
|