Files
openchamber/packages/ui/src/lib/messages/messageText.ts
T
Bohdan Triapitsyn 799a202e99 feat(plans): save assistant messages as editable project plans with improve/implement flows
Add Save-as-plan action on assistant messages that writes a markdown plan
into the project plans directory and suggests a title from the text. Plan
view opens a specific saved plan via targetPath, supports inline edits, and
can kick off improve or implement flows in a new or worktree session.

Ship the matching hidden magic prompts (plan.todo/improve/implement) so the
instructions applied by these flows are visible and editable in the Magic
Prompts page.

Remove the plan editor font override, CodeMirror now uses the app font stack.
2026-04-18 13:47:05 +03:00

32 lines
1.1 KiB
TypeScript

import type { Part } from '@opencode-ai/sdk/v2';
type TextLikePart = Part & { text?: string; content?: string };
export const flattenAssistantTextParts = (parts: Part[]): string => {
const textParts = parts
.filter((part): part is TextLikePart => part?.type === 'text')
.map((part) => (part.text || part.content || '').trim())
.filter((text) => text.length > 0);
const combined = textParts.join('\n');
return combined.replace(/\n\s*\n+/g, '\n');
};
export const suggestPlanTitleFromText = (text: string): string => {
const normalized = text
.replace(/\r\n?/g, '\n')
.split('\n')
.map((line) => line.trim())
.find((line) => line.length > 0) || 'Plan';
const cleaned = normalized
.replace(/^#+\s*/, '')
.replace(/^[-*+]\s+/, '')
.replace(/^\d+\.\s+/, '');
const sentenceMatch = cleaned.match(/(.+?[.!?])(?:\s|$)/);
const firstSentence = sentenceMatch?.[1] || cleaned;
const compact = firstSentence.replace(/\s+/g, ' ').trim();
return compact.length > 160 ? compact.slice(0, 160).trim() : compact || 'Plan';
};