Files
Michael Ramos 2a5528693f Add Ask AI to plan and annotate reviews (#763)
* Add Ask AI to plan and annotate reviews

- mount shared AI runtime on plan, annotate, review, and Pi servers

- add shared document chat UI and comment-popover Ask AI entry point

- default providers from detected agent origin and document first-run announcement

- reuse shared code-review AI hook and document setup/docs

* Address Ask AI review followups

Stabilize AI chat session resets and callbacks, preserve per-origin provider defaults, share AI chat formatting utilities, and avoid blocking startup on model discovery.

* Fix AI permission details and Pi CLI lookup

Show formatted tool input in document AI permission cards and make Pi AI provider CLI detection work on Windows.

* Fix Pi model discovery in AI capabilities

Keep AI runtime startup non-blocking while making the capabilities endpoint await pending Pi/OpenCode model discovery before returning provider metadata.
2026-05-21 01:32:17 -07:00

34 lines
1.1 KiB
TypeScript

import { createElement, type ReactNode } from 'react';
import { marked } from 'marked';
import DOMPurify from 'dompurify';
export function renderChatMarkdown(text: string): ReactNode {
const html = marked.parse(text, { async: false, breaks: true }) as string;
const clean = DOMPurify.sanitize(html, {
ALLOWED_TAGS: [
'p', 'br', 'strong', 'em', 'code', 'pre', 'ul', 'ol', 'li',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'a', 'blockquote',
],
ALLOWED_ATTR: ['href', 'rel', 'class'],
});
return createElement('div', {
className: 'ai-markdown',
dangerouslySetInnerHTML: { __html: clean },
});
}
export function formatRelativeTime(ts: number): string {
const seconds = Math.max(0, Math.floor((Date.now() - ts) / 1000));
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (seconds < 60) return 'now';
if (minutes < 60) return `${minutes}m`;
if (hours < 24) return `${hours}h`;
if (days < 7) return `${days}d`;
return new Date(ts).toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
}