- Add state-graph.ts: typed state machine for inference lifecycle - Add supervisor.ts: agent supervisor pattern for multi-agent coordination - Add export-formatter.ts: structured export formatting - Add manage_memory.ts: memory CRUD tool for agent persistence - Add get_wiki_article.ts: codecontext wiki article retrieval - Extend memory/index.ts: 3-tier memory (context/daily/core) - Extend MCP client: mcp-config.ts env-var substitution - Update schema.sql: agent_sessions, tasks, pending_changes extensions - Update API types: MessageMetadata, ErrorReason, AgentSessionConfig - Update routes: chats, messages, sessions — column renames and agent_session_id - Update inference: error handler, payload builder, stream phase, turn orchestrator
94 lines
2.0 KiB
TypeScript
94 lines
2.0 KiB
TypeScript
import type { Chat, Message } from '../types/api.js';
|
|
|
|
interface ExportMessage {
|
|
role: string;
|
|
content: string;
|
|
model: string | null;
|
|
created_at: string;
|
|
tokens_used: number | null;
|
|
status: string;
|
|
kind: string;
|
|
tool_calls: Record<string, unknown>[] | null;
|
|
}
|
|
|
|
interface ExportJson {
|
|
chat: {
|
|
id: string;
|
|
name: string | null;
|
|
model: string | null;
|
|
created_at: string;
|
|
};
|
|
messages: ExportMessage[];
|
|
}
|
|
|
|
export function formatJson(
|
|
chat: Chat,
|
|
messages: Message[],
|
|
model: string | null,
|
|
): string {
|
|
const data: ExportJson = {
|
|
chat: {
|
|
id: chat.id,
|
|
name: chat.name,
|
|
model,
|
|
created_at: chat.created_at,
|
|
},
|
|
messages: messages.map((m) => ({
|
|
role: m.role,
|
|
content: m.content,
|
|
model: m.model ?? null,
|
|
created_at: m.created_at,
|
|
tokens_used: m.tokens_used,
|
|
status: m.status,
|
|
kind: m.kind,
|
|
tool_calls: m.tool_calls as Record<string, unknown>[] | null,
|
|
})),
|
|
};
|
|
return JSON.stringify(data, null, 2);
|
|
}
|
|
|
|
export function formatMarkdown(
|
|
chat: Chat,
|
|
messages: Message[],
|
|
model: string | null,
|
|
): string {
|
|
const parts: string[] = [];
|
|
parts.push(`# ${chat.name ?? 'Untitled Chat'}`);
|
|
parts.push(`Model: ${model ?? 'unknown'}`);
|
|
parts.push('');
|
|
parts.push('---');
|
|
parts.push('');
|
|
|
|
for (const msg of messages) {
|
|
// Skip system/sentinel messages for a cleaner transcript
|
|
if (msg.role === 'system') continue;
|
|
|
|
const label =
|
|
msg.role === 'user'
|
|
? 'User'
|
|
: msg.role === 'assistant'
|
|
? 'Assistant'
|
|
: 'Tool';
|
|
parts.push(`## ${label}`);
|
|
parts.push('');
|
|
|
|
if (msg.content) {
|
|
parts.push(msg.content);
|
|
parts.push('');
|
|
}
|
|
|
|
if (msg.tool_calls && msg.tool_calls.length > 0) {
|
|
for (const tc of msg.tool_calls) {
|
|
parts.push(`> \`${tc.name}\``);
|
|
parts.push('');
|
|
parts.push('```json');
|
|
parts.push(JSON.stringify(tc.args, null, 2));
|
|
parts.push('```');
|
|
parts.push('');
|
|
}
|
|
}
|
|
}
|
|
|
|
return parts.join('\n');
|
|
}
|