refactor(messaging): project inter-agent messages into pi session transcript
Inter-agent messages previously entered the recipient's context as a separate prompt block (recentMessages), rebuilt every turn. This double- charged tokens and kept messages outside pi's native AgentMessage stream. Now at prepareRun: pull the recipient's unread inbox, project each AgentMessageRecord into a pi user-role AgentMessage, persist to SqliteSessionStore, and mark delivered. The recipient reads messages as natural conversation turns in the transcript. - db: listAgentInboxUnread + markAgentInboxDelivered (transactional) - agent-runtime/inbox-projection.ts: AgentMessageRecord -> pi AgentMessage - runtime-bridge.prepareRun: inject + deliver before loadMessages - prompt-builder: delete recentMessages context block + buildMessagesSection - message-normalize: drop unused normalizeMessagesForPrompt - delete prompt-builder/attachment-resolver.ts (orphan after section removal) Send path (api-server/routes-messages, ipc, UI) unchanged — inbox table remains the UI source. Transactional delivery marking prevents duplicate injection across runs. Failed append -> no mark -> retry on next run.
This commit is contained in:
1 parent
5547c29491
commit
b50716d4e8
11 files changed
+254
-175
No files matched your search
@@ -1,19 +1,18 @@
|
||||
/**
|
||||
* Message Normalization Layer
|
||||
*
|
||||
* Normalizes messages and comments before they are injected into agent prompts.
|
||||
* Normalizes comments before they are injected into agent prompts.
|
||||
* Prevents malformed, empty, or excessively long content from degrading
|
||||
* model output quality. Inspired by Reference/src/utils/messages.ts.
|
||||
*
|
||||
* Applied at the prompt-builder boundary — the last point before content
|
||||
* enters the model's context window.
|
||||
*
|
||||
* Inter-agent messages no longer flow through a prompt block; they are
|
||||
* projected directly into the recipient's pi session transcript. See
|
||||
* `agent-runtime/inbox-projection.ts`.
|
||||
*/
|
||||
|
||||
import type { AgentMessageRecord } from "@shared/types";
|
||||
|
||||
/** Maximum body length for a single message in prompt context. */
|
||||
const MAX_MESSAGE_BODY_LENGTH = 800;
|
||||
|
||||
/** Maximum comment body length in prompt context. */
|
||||
const MAX_COMMENT_BODY_LENGTH = 500;
|
||||
|
||||
@@ -36,48 +35,6 @@ function truncate(text: string, maxLen: number): string {
|
||||
return text.slice(0, maxLen - 1) + "…";
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize agent messages before prompt injection.
|
||||
* - Removes empty-body messages
|
||||
* - Cleans control characters
|
||||
* - Truncates overly long bodies
|
||||
* - Deduplicates consecutive identical messages from the same sender
|
||||
*/
|
||||
export function normalizeMessagesForPrompt(
|
||||
messages: AgentMessageRecord[],
|
||||
limit: number = 15,
|
||||
): AgentMessageRecord[] {
|
||||
const result: AgentMessageRecord[] = [];
|
||||
let prevKey = "";
|
||||
|
||||
for (const msg of messages) {
|
||||
const cleaned = cleanText(msg.body);
|
||||
if (cleaned.length === 0) continue;
|
||||
|
||||
// Deduplicate consecutive identical messages from the same sender
|
||||
const key = `${msg.fromAgentId}:${cleaned}`;
|
||||
if (key === prevKey) continue;
|
||||
prevKey = key;
|
||||
|
||||
result.push({
|
||||
...msg,
|
||||
body: truncate(cleaned, MAX_MESSAGE_BODY_LENGTH),
|
||||
subject: msg.subject ? truncate(cleanText(msg.subject), 120) : msg.subject,
|
||||
});
|
||||
|
||||
if (result.length >= limit) break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Transcript Repair — for session handoff / resume scenarios
|
||||
// Inspired by Reference/src/utils/messages.ts tool pairing logic.
|
||||
// Applied when session state is restored, not at every message send.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
export interface CommentRecord {
|
||||
taskId: string;
|
||||
taskTitle: string;
|
||||
|
||||
Reference in new issue
Block a user