mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-20 12:04:35 +00:00
Use exhaustive switch on message.role throughout coding-agent
- addMessageToChat: exhaustive switch for all AgentMessage roles - renderSessionContext: delegates to addMessageToChat, special handling for assistant tool calls and tool results - export-html formatMessage: exhaustive switch for all AgentMessage roles - Removed isHookMessage, isBashExecutionMessage type guards in favor of role checks - Fixed imports and removed unused getLatestCompactionEntry
This commit is contained in:
parent
ecef601d19
commit
b921298af7
11 changed files with 442 additions and 376 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import type { ImageContent, TextContent } from "@mariozechner/pi-ai";
|
||||
import type { ImageContent, Message, TextContent } from "@mariozechner/pi-ai";
|
||||
import { randomUUID } from "crypto";
|
||||
import {
|
||||
appendFileSync,
|
||||
|
|
@ -15,6 +15,13 @@ import {
|
|||
} from "fs";
|
||||
import { join, resolve } from "path";
|
||||
import { getAgentDir as getDefaultAgentDir } from "../config.js";
|
||||
import {
|
||||
type BashExecutionMessage,
|
||||
createBranchSummaryMessage,
|
||||
createCompactionSummaryMessage,
|
||||
createHookMessage,
|
||||
type HookMessage,
|
||||
} from "./messages.js";
|
||||
|
||||
export const CURRENT_SESSION_VERSION = 2;
|
||||
|
||||
|
|
@ -59,9 +66,12 @@ export interface CompactionEntry<T = unknown> extends SessionEntryBase {
|
|||
details?: T;
|
||||
}
|
||||
|
||||
export interface BranchSummaryEntry extends SessionEntryBase {
|
||||
export interface BranchSummaryEntry<T = unknown> extends SessionEntryBase {
|
||||
type: "branch_summary";
|
||||
fromId: string;
|
||||
summary: string;
|
||||
/** Hook-specific data (not sent to LLM) */
|
||||
details?: T;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -145,35 +155,6 @@ export interface SessionInfo {
|
|||
allMessagesText: string;
|
||||
}
|
||||
|
||||
export const SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
|
||||
|
||||
<summary>
|
||||
`;
|
||||
|
||||
export const SUMMARY_SUFFIX = `
|
||||
</summary>`;
|
||||
|
||||
/** Exported for compaction.test.ts */
|
||||
export function createSummaryMessage(summary: string, timestamp: string): AgentMessage {
|
||||
return {
|
||||
role: "user",
|
||||
content: SUMMARY_PREFIX + summary + SUMMARY_SUFFIX,
|
||||
timestamp: new Date(timestamp).getTime(),
|
||||
};
|
||||
}
|
||||
|
||||
/** Convert CustomMessageEntry to AgentMessage format */
|
||||
function createCustomMessage(entry: CustomMessageEntry): AgentMessage {
|
||||
return {
|
||||
role: "hookMessage",
|
||||
customType: entry.customType,
|
||||
content: entry.content,
|
||||
display: entry.display,
|
||||
details: entry.details,
|
||||
timestamp: new Date(entry.timestamp).getTime(),
|
||||
} as AgentMessage;
|
||||
}
|
||||
|
||||
/** Generate a unique short ID (8 hex chars, collision-checked) */
|
||||
function generateId(byId: { has(id: string): boolean }): string {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
|
|
@ -328,9 +309,21 @@ export function buildSessionContext(
|
|||
// 3. Emit messages after compaction
|
||||
const messages: AgentMessage[] = [];
|
||||
|
||||
const appendMessage = (entry: SessionEntry) => {
|
||||
if (entry.type === "message") {
|
||||
messages.push(entry.message);
|
||||
} else if (entry.type === "custom_message") {
|
||||
messages.push(
|
||||
createHookMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp),
|
||||
);
|
||||
} else if (entry.type === "branch_summary" && entry.summary) {
|
||||
messages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));
|
||||
}
|
||||
};
|
||||
|
||||
if (compaction) {
|
||||
// Emit summary first
|
||||
messages.push(createSummaryMessage(compaction.summary, compaction.timestamp));
|
||||
messages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));
|
||||
|
||||
// Find compaction index in path
|
||||
const compactionIdx = path.findIndex((e) => e.type === "compaction" && e.id === compaction.id);
|
||||
|
|
@ -343,37 +336,19 @@ export function buildSessionContext(
|
|||
foundFirstKept = true;
|
||||
}
|
||||
if (foundFirstKept) {
|
||||
if (entry.type === "message") {
|
||||
messages.push(entry.message);
|
||||
} else if (entry.type === "custom_message") {
|
||||
messages.push(createCustomMessage(entry));
|
||||
} else if (entry.type === "branch_summary") {
|
||||
messages.push(createSummaryMessage(entry.summary, entry.timestamp));
|
||||
}
|
||||
appendMessage(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Emit messages after compaction
|
||||
for (let i = compactionIdx + 1; i < path.length; i++) {
|
||||
const entry = path[i];
|
||||
if (entry.type === "message") {
|
||||
messages.push(entry.message);
|
||||
} else if (entry.type === "custom_message") {
|
||||
messages.push(createCustomMessage(entry));
|
||||
} else if (entry.type === "branch_summary") {
|
||||
messages.push(createSummaryMessage(entry.summary, entry.timestamp));
|
||||
}
|
||||
appendMessage(entry);
|
||||
}
|
||||
} else {
|
||||
// No compaction - emit all messages, handle branch summaries and custom messages
|
||||
for (const entry of path) {
|
||||
if (entry.type === "message") {
|
||||
messages.push(entry.message);
|
||||
} else if (entry.type === "custom_message") {
|
||||
messages.push(createCustomMessage(entry));
|
||||
} else if (entry.type === "branch_summary") {
|
||||
messages.push(createSummaryMessage(entry.summary, entry.timestamp));
|
||||
}
|
||||
appendMessage(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -597,8 +572,13 @@ export class SessionManager {
|
|||
this._persist(entry);
|
||||
}
|
||||
|
||||
/** Append a message as child of current leaf, then advance leaf. Returns entry id. */
|
||||
appendMessage(message: AgentMessage): string {
|
||||
/** Append a message as child of current leaf, then advance leaf. Returns entry id.
|
||||
* Does not allow writing CompactionSummaryMessage and BranchSummaryMessage directly.
|
||||
* Reason: we want these to be top-level entries in the session, not message session entries,
|
||||
* so it is easier to find them.
|
||||
* These need to be appended via appendCompaction() and appendBranchSummary() methods.
|
||||
*/
|
||||
appendMessage(message: Message | HookMessage | BashExecutionMessage): string {
|
||||
const entry: SessionMessageEntry = {
|
||||
type: "message",
|
||||
id: generateId(this.byId),
|
||||
|
|
@ -851,6 +831,7 @@ export class SessionManager {
|
|||
id: generateId(this.byId),
|
||||
parentId: branchFromId,
|
||||
timestamp: new Date().toISOString(),
|
||||
fromId: branchFromId,
|
||||
summary,
|
||||
};
|
||||
this._appendEntry(entry);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue