mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-21 05:02:14 +00:00
Rewrite CHANGELOG.md with migration guides
- Session Tree: brief description, reference session.md - Hooks Migration: type renames, event changes, API changes - Custom Tools Migration: type renames, execute signature, context object - SDK Migration: type changes, branching API, exports - RPC Migration: entryId, AgentMessage, compaction events - Structured Compaction: output format, file tracking - Interactive Mode: /tree, labels, themes, settings - Keep Fixed section with external contributions
This commit is contained in:
parent
17ed3fa605
commit
b72cf47409
1 changed files with 138 additions and 88 deletions
|
|
@ -2,103 +2,153 @@
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Breaking Changes
|
This release introduces session trees for in-place branching, major API changes to hooks and custom tools, and structured compaction with file tracking.
|
||||||
|
|
||||||
- **Session tree structure (v2)**: Sessions now store entries as a tree with `id`/`parentId` fields, enabling in-place branching without creating new files. Existing v1 sessions are auto-migrated on load.
|
### Session Tree
|
||||||
- **SessionManager API**:
|
|
||||||
- `saveXXX()` renamed to `appendXXX()` (e.g., `appendMessage`, `appendCompaction`)
|
Sessions now use a tree structure with `id`/`parentId` fields. This enables in-place branching: navigate to any previous point with `/tree`, continue from there, and switch between branches while preserving all history in a single file.
|
||||||
- `branchInPlace()` renamed to `branch()`
|
|
||||||
- `reset()` renamed to `newSession()`
|
**Existing sessions are automatically migrated** (v1 → v2) on first load. No manual action required.
|
||||||
- `createBranchedSessionFromEntries(entries, index)` replaced with `createBranchedSession(leafId)`
|
|
||||||
- `saveCompaction(entry)` replaced with `appendCompaction(summary, firstKeptEntryId, tokensBefore)`
|
New entry types: `BranchSummaryEntry` (context from abandoned branches), `CustomEntry` (hook state), `CustomMessageEntry` (hook-injected messages), `LabelEntry` (bookmarks).
|
||||||
- `getEntries()` now excludes the session header (use `getHeader()` separately)
|
|
||||||
- New methods: `getTree()`, `getPath()`, `getLeafUuid()`, `getLeafEntry()`, `getEntry()`, `branchWithSummary()`
|
See [docs/session.md](docs/session.md) for the file format and `SessionManager` API.
|
||||||
- New `appendCustomEntry(customType, data)` for hooks to store custom data (not in LLM context)
|
|
||||||
- New `appendCustomMessageEntry(customType, content, display, details?)` for hooks to inject messages into LLM context
|
### Hooks Migration
|
||||||
- **Compaction API**:
|
|
||||||
- `CompactionEntry<T>` and `CompactionResult<T>` are now generic with optional `details?: T` for hook-specific data
|
The hooks API has been restructured with more granular events and better session access.
|
||||||
- `compact()` now returns `CompactionResult` (`{ summary, firstKeptEntryId, tokensBefore, details? }`) instead of `CompactionEntry`
|
|
||||||
- `appendCompaction()` now accepts optional `details` parameter
|
**Type renames:**
|
||||||
- `CompactionEntry.firstKeptEntryIndex` replaced with `firstKeptEntryId`
|
- `HookEventContext` → `HookContext`
|
||||||
- `prepareCompaction(pathEntries, settings)` now takes path entries (from `getPath()`) and settings only
|
- `HookCommandContext` removed (use `HookContext` for command handlers)
|
||||||
- `CompactionPreparation` restructured: removed `cutPoint`, `messagesToKeep`, `boundaryStart`; added `turnPrefixMessages`, `isSplitTurn`, `previousSummary`, `fileOps`, `settings`
|
|
||||||
- `compact(preparation, model, apiKey, customInstructions?, signal?)` now takes preparation and execution context separately
|
**Event changes:**
|
||||||
- **Hook types**:
|
- The monolithic `session` event is now split into granular events: `session_start`, `session_before_switch`, `session_switch`, `session_before_new`, `session_new`, `session_before_branch`, `session_branch`, `session_before_compact`, `session_compact`, `session_before_tree`, `session_tree`, `session_shutdown`
|
||||||
- `HookEventContext` renamed to `HookContext`
|
- New `before_agent_start` event: inject messages before the agent loop starts
|
||||||
- `HookContext` now has `sessionManager`, `modelRegistry`, and `model` (current model, may be undefined)
|
- New `context` event: modify messages non-destructively before each LLM call
|
||||||
- `HookCommandContext` removed - `RegisteredCommand.handler` now takes `(args: string, ctx: HookContext)`
|
- Session entries are no longer passed in events. Use `ctx.sessionManager.getEntries()` or `ctx.sessionManager.getBranch()` instead
|
||||||
- `before_compact` event: removed `previousCompactions` and `model`, added `branchEntries: SessionEntry[]` (hooks extract what they need)
|
|
||||||
- `before_tree` event: removed `model` (use `ctx.model` instead)
|
**API changes:**
|
||||||
- `before_switch` event now has `targetSessionFile`, `switch` event has `previousSessionFile`
|
- `pi.send(text, attachments?)` → `pi.sendMessage(message, triggerTurn?)` (creates `CustomMessageEntry`)
|
||||||
- Removed `resolveApiKey` (use `modelRegistry.getApiKey(model)`)
|
- New `pi.appendEntry(customType, data?)` for hook state persistence (not in LLM context)
|
||||||
- Hooks can return `compaction.details` to store custom data (e.g., ArtifactIndex for structured compaction)
|
- New `pi.registerCommand(name, options)` for custom slash commands
|
||||||
- **Hook API**:
|
- New `pi.registerMessageRenderer(customType, renderer)` for custom TUI rendering
|
||||||
- `pi.send(text, attachments?)` replaced with `pi.sendMessage(message, triggerTurn?)` which creates `CustomMessageEntry` instead of user messages
|
- New `ctx.ui.custom(component)` for full TUI component rendering with keyboard focus
|
||||||
- New `pi.appendEntry(customType, data?)` to persist hook state (does NOT participate in LLM context)
|
- `ctx.exec()` moved to `pi.exec()`
|
||||||
- New `pi.registerCommand(name, options)` to register custom slash commands
|
- `ctx.sessionFile` → `ctx.sessionManager.getSessionFile()`
|
||||||
- New `pi.registerMessageRenderer(customType, renderer)` to register custom renderers for hook messages
|
- New `ctx.modelRegistry` and `ctx.model` for API key resolution
|
||||||
- New `pi.exec(command, args, options?)` to execute shell commands (moved from `HookEventContext`/`HookCommandContext`)
|
|
||||||
- `HookMessageRenderer` type: `(message: HookMessage, options, theme) => Component | null`
|
**Removed:**
|
||||||
- Renderers return inner content; the TUI wraps it in a styled Box
|
- `hookTimeout` setting (hooks no longer have timeouts; use Ctrl+C to abort)
|
||||||
- New types: `HookMessage<T>`, `RegisteredCommand`, `HookContext`
|
- `resolveApiKey` parameter (use `ctx.modelRegistry.getApiKey(model)`)
|
||||||
- Handler types renamed: `SendHandler` → `SendMessageHandler`, new `AppendEntryHandler`
|
|
||||||
- Removed `hookTimeout` setting - hooks no longer have execution timeouts (use Ctrl+C to abort hung hooks)
|
See [docs/hooks.md](docs/hooks.md) and [examples/hooks/](examples/hooks/) for the current API.
|
||||||
- **SessionManager**:
|
|
||||||
- `getSessionFile()` now returns `string | undefined` (undefined for in-memory sessions)
|
### Custom Tools Migration
|
||||||
- **Themes**: Custom themes must add `selectedBg`, `customMessageBg`, `customMessageText`, `customMessageLabel` color tokens (50 total)
|
|
||||||
- **Custom tools API**:
|
The custom tools API has been restructured to mirror the hooks pattern with a context object.
|
||||||
- `CustomAgentTool` renamed to `CustomTool`
|
|
||||||
- `ToolAPI` renamed to `CustomToolAPI`
|
**Type renames:**
|
||||||
- `ToolContext` renamed to `CustomToolContext`
|
- `CustomAgentTool` → `CustomTool`
|
||||||
- `ToolSessionEvent` renamed to `CustomToolSessionEvent`
|
- `ToolAPI` → `CustomToolAPI`
|
||||||
- `execute()` signature changed: now takes `(toolCallId, params, onUpdate, ctx: CustomToolContext, signal?)`
|
- `ToolContext` → `CustomToolContext`
|
||||||
- `onSession()` signature changed: now takes `(event: CustomToolSessionEvent, ctx: CustomToolContext)`
|
- `ToolSessionEvent` → `CustomToolSessionEvent`
|
||||||
- `CustomToolSessionEvent` simplified: only has `reason` and `previousSessionFile` (use `ctx.sessionManager.getBranch()` to get entries)
|
|
||||||
- `CustomToolContext` provides `sessionManager: ReadonlySessionManager`, `modelRegistry`, and `model`
|
**Execute signature changed:**
|
||||||
- `dispose()` method removed - use `onSession` with `reason: "shutdown"` for cleanup
|
```typescript
|
||||||
- `CustomToolFactory` return type changed to `CustomTool<any, any>` for type compatibility
|
// Before (v0.30.2)
|
||||||
- **AgentSession.branch()**: Now takes `entryId: string` instead of `entryIndex: number`. `SessionBeforeBranchEvent.entryId` replaces `entryIndex`. `getUserMessagesForBranching()` returns `{ entryId, text }` instead of `{ entryIndex, text }`.
|
execute(toolCallId, params, signal, onUpdate)
|
||||||
- **Renamed exports**:
|
|
||||||
- `messageTransformer` → `convertToLlm`
|
// After
|
||||||
- `SessionContext` alias `LoadedSession` removed (use `SessionContext` directly)
|
execute(toolCallId, params, onUpdate, ctx, signal?)
|
||||||
- **Removed exports**:
|
```
|
||||||
- `createSummaryMessage()` - replaced by internal compaction logic
|
|
||||||
- `SUMMARY_PREFIX`, `SUMMARY_SUFFIX` - no longer used
|
The new `ctx: CustomToolContext` provides `sessionManager`, `modelRegistry`, and `model`.
|
||||||
- `Attachment` type - use `ImageContent` from `@mariozechner/pi-ai` instead
|
|
||||||
- **New exports**:
|
**Session event changes:**
|
||||||
- `BranchSummaryEntry`, `CustomEntry`, `CustomMessageEntry`, `LabelEntry` - new session entry types
|
- `CustomToolSessionEvent` now only has `reason` and `previousSessionFile`
|
||||||
- `SessionEntryBase`, `FileEntry` - base types for session entries
|
- Session entries are no longer in the event. Use `ctx.sessionManager.getBranch()` to reconstruct state
|
||||||
- `CURRENT_SESSION_VERSION`, `migrateSessionEntries` - session migration utilities
|
- New `reason: "tree"` for `/tree` navigation, `reason: "shutdown"` for cleanup
|
||||||
- `BranchPreparation`, `BranchSummaryResult`, `CollectEntriesResult`, `GenerateBranchSummaryOptions` - branch summarization types
|
- `dispose()` method removed. Use `onSession` with `reason: "shutdown"` for cleanup
|
||||||
- `FileOperations`, `collectEntriesForBranchSummary`, `prepareBranchEntries`, `generateBranchSummary` - branch summarization utilities
|
|
||||||
- `CompactionPreparation`, `CompactionDetails` - compaction preparation types
|
See [docs/custom-tools.md](docs/custom-tools.md) and [examples/custom-tools/](examples/custom-tools/) for the current API.
|
||||||
- `ReadonlySessionManager` - read-only session manager interface for hooks
|
|
||||||
- `HookMessage`, `HookContext`, `HookMessageRenderOptions` - hook types
|
### SDK Migration
|
||||||
- `isHookMessage`, `createHookMessage` - hook message utilities
|
|
||||||
|
**Type changes:**
|
||||||
|
- `CustomAgentTool` → `CustomTool`
|
||||||
|
- `AppMessage` → `AgentMessage`
|
||||||
|
- `sessionFile` returns `string | undefined` (was `string | null`)
|
||||||
|
- `model` returns `Model | undefined` (was `Model | null`)
|
||||||
|
|
||||||
|
**Branching API:**
|
||||||
|
- `branch(entryIndex: number)` → `branch(entryId: string)`
|
||||||
|
- `getUserMessagesForBranching()` returns `{ entryId, text }` instead of `{ entryIndex, text }`
|
||||||
|
- `reset()` and `switchSession()` now return `Promise<boolean>` (false if cancelled by hook)
|
||||||
|
- New `navigateTree(targetId, options?)` for in-place tree navigation
|
||||||
|
|
||||||
|
**Hook integration:**
|
||||||
|
- New `sendHookMessage(message, triggerTurn?)` for hook message injection
|
||||||
|
|
||||||
|
**Renamed exports:**
|
||||||
|
- `messageTransformer` → `convertToLlm`
|
||||||
|
- `SessionContext` alias `LoadedSession` removed
|
||||||
|
|
||||||
|
See [docs/sdk.md](docs/sdk.md) and [examples/sdk/](examples/sdk/) for the current API.
|
||||||
|
|
||||||
|
### RPC Migration
|
||||||
|
|
||||||
|
**Branching commands:**
|
||||||
|
- `branch` command: `entryIndex` → `entryId`
|
||||||
|
- `get_branch_messages` response: `entryIndex` → `entryId`
|
||||||
|
|
||||||
|
**Type changes:**
|
||||||
|
- Messages are now `AgentMessage` (was `AppMessage`)
|
||||||
|
|
||||||
|
**Compaction events:**
|
||||||
|
- `auto_compaction_start` now includes `reason` field (`"threshold"` or `"overflow"`)
|
||||||
|
- `auto_compaction_end` now includes `willRetry` field
|
||||||
|
- `compact` response includes full `CompactionResult` (`summary`, `firstKeptEntryId`, `tokensBefore`, `details`)
|
||||||
|
|
||||||
|
See [docs/rpc.md](docs/rpc.md) for the current protocol.
|
||||||
|
|
||||||
|
### Structured Compaction
|
||||||
|
|
||||||
|
Compaction and branch summarization now use a structured output format:
|
||||||
|
- Clear sections: Goal, Progress, Key Information, File Operations
|
||||||
|
- File tracking: `readFiles` and `modifiedFiles` arrays in `details`, accumulated across compactions
|
||||||
|
- Conversations are serialized to text before summarization to prevent the model from "continuing" them
|
||||||
|
|
||||||
|
The `before_compact` and `before_tree` hook events allow custom compaction implementations. See [docs/compaction.md](docs/compaction.md).
|
||||||
|
|
||||||
|
### Interactive Mode
|
||||||
|
|
||||||
|
**`/tree` command:**
|
||||||
|
- Navigate the full session tree in-place
|
||||||
|
- Search by typing, page with ←/→
|
||||||
|
- Filter modes (Ctrl+O): default → no-tools → user-only → labeled-only → all
|
||||||
|
- Press `l` to label entries as bookmarks
|
||||||
|
- Selecting a branch generates a summary and switches context
|
||||||
|
|
||||||
|
**Entry labels:**
|
||||||
|
- Bookmark any entry via `/tree` → select → `l`
|
||||||
|
- Labels appear in tree view and persist as `LabelEntry`
|
||||||
|
|
||||||
|
**Theme additions:**
|
||||||
|
- `selectedBg`: background for selected items
|
||||||
|
- `customMessageBg`, `customMessageText`, `customMessageLabel`: hook message styling
|
||||||
|
|
||||||
|
**Settings:**
|
||||||
|
- `enabledModels`: whitelist models in `settings.json` (same format as `--models` CLI)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **`/tree` command**: Navigate the session tree in-place. Shows full tree structure with labels, supports search (type to filter), page navigation (←/→), and filter modes (Ctrl+O cycles: default → no-tools → user-only → labeled-only → all, Shift+Ctrl+O cycles backwards). Selecting a branch generates a summary and switches context. Press `l` to label entries.
|
- **Snake game example hook**: Demonstrates `ui.custom()`, `registerCommand()`, and session persistence. See [examples/hooks/snake.ts](examples/hooks/snake.ts).
|
||||||
- **`context` hook event**: Fires before each LLM call, allowing hooks to non-destructively modify messages. Returns `{ messages }` to override. Useful for dynamic context pruning without modifying session history.
|
|
||||||
- **`before_agent_start` hook event**: Fires once when user submits a prompt, before `agent_start`. Hooks can return `{ message }` to inject a `CustomMessageEntry` that gets persisted and sent to the LLM.
|
|
||||||
- **`ui.custom()` for hooks**: Show arbitrary TUI components with keyboard focus. Call `done()` when finished: `ctx.ui.custom(component, done)`.
|
|
||||||
- **Branch summarization**: When switching branches via `/tree`, generates a summary of the abandoned branch including file operations (read/modified files). Summaries are stored as `BranchSummaryEntry` with cumulative file tracking in `details`.
|
|
||||||
- **Structured compaction**: Both compaction and branch summarization now use structured output format with clear sections (Goal, Progress, Key Information, File Operations). Conversations are serialized to text before summarization to prevent the model from "continuing" conversations.
|
|
||||||
- **File tracking in summaries**: Compaction and branch summaries now track `readFiles` and `modifiedFiles` arrays in the `details` field, accumulated across multiple compactions/summaries. This provides cumulative file operation history.
|
|
||||||
- **`selectedBg` theme color**: Background color for selected/active lines in tree selector and other components.
|
|
||||||
- **Entry labels**: Label any session entry with `/tree` → select entry → press `l`. Labels appear in tree view and are persisted as `LabelEntry` in the session. Use `labeled-only` filter mode to show only labeled entries.
|
|
||||||
- **`enabledModels` setting**: Configure whitelisted models in `settings.json` (same format as `--models` CLI flag). CLI `--models` takes precedence over the setting.
|
|
||||||
- **Snake game example hook**: Added `examples/hooks/snake.ts` demonstrating `ui.custom()`, `registerCommand()`, and session persistence.
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Entry IDs**: Session entries now use short 8-character hex IDs instead of full UUIDs
|
- **Entry IDs**: Session entries now use short 8-character hex IDs instead of full UUIDs
|
||||||
- **API key priority**: `ANTHROPIC_OAUTH_TOKEN` now takes precedence over `ANTHROPIC_API_KEY`
|
- **API key priority**: `ANTHROPIC_OAUTH_TOKEN` now takes precedence over `ANTHROPIC_API_KEY`
|
||||||
- **New entry types**: `BranchSummaryEntry` for branch context, `CustomEntry<T>` for hook state persistence, `CustomMessageEntry<T>` for hook-injected context messages, `LabelEntry` for user-defined bookmarks
|
|
||||||
- **TUI**: `CustomMessageEntry` renders with purple styling (customMessageBg, customMessageText, customMessageLabel theme colors). Entries with `display: false` are hidden.
|
|
||||||
- **AgentSession**: New `sendHookMessage(message, triggerTurn?)` method for hooks to inject messages. Handles queuing during streaming, direct append when idle, and optional turn triggering.
|
|
||||||
- **HookMessage**: New message type with `role: "hookMessage"` for hook-injected messages in agent events. Use `isHookMessage(msg)` type guard to identify them. These are converted to user messages for LLM context via `messageTransformer`.
|
|
||||||
- **Agent.prompt()**: Now accepts `AppMessage` directly (in addition to `string, attachments?`) for custom message types like `HookMessage`.
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue