feat(electrobun): file management — CodeMirror editor, PDF viewer, CSV table, real file I/O
- CodeEditor: CodeMirror 6 with Catppuccin theme, 15+ languages, Ctrl+S save, dirty tracking, save-on-blur - PdfViewer: pdfjs-dist canvas rendering, zoom 0.5-3x, HiDPI, lazy page load - CsvTable: RFC 4180 parser, delimiter auto-detect, sortable columns, sticky header - FileBrowser: real filesystem via files.list/read/write RPC, lazy dir loading, file type routing (code→editor, pdf→viewer, csv→table, images→display) - 10MB size gate, binary detection, base64 encoding for non-text files
This commit is contained in:
parent
29a3370e79
commit
252fca70df
22 changed files with 8116 additions and 227 deletions
|
|
@ -90,6 +90,36 @@ export type PtyRPCRequests = {
|
|||
response: { ok: boolean };
|
||||
};
|
||||
|
||||
// ── File I/O RPC ──────────────────────────────────────────────────────────
|
||||
|
||||
/** List directory children (files + subdirs). Returns sorted entries. */
|
||||
"files.list": {
|
||||
params: { path: string };
|
||||
response: {
|
||||
entries: Array<{
|
||||
name: string;
|
||||
type: "file" | "dir";
|
||||
size: number;
|
||||
}>;
|
||||
error?: string;
|
||||
};
|
||||
};
|
||||
/** Read a file's content. Returns text for text files, base64 for binary. */
|
||||
"files.read": {
|
||||
params: { path: string };
|
||||
response: {
|
||||
content?: string;
|
||||
encoding: "utf8" | "base64";
|
||||
size: number;
|
||||
error?: string;
|
||||
};
|
||||
};
|
||||
/** Write text content to a file. */
|
||||
"files.write": {
|
||||
params: { path: string; content: string };
|
||||
response: { ok: boolean; error?: string };
|
||||
};
|
||||
|
||||
// ── Groups RPC ─────────────────────────────────────────────────────────────
|
||||
|
||||
/** Return all project groups. */
|
||||
|
|
@ -190,6 +220,268 @@ export type PtyRPCRequests = {
|
|||
}>;
|
||||
};
|
||||
};
|
||||
|
||||
// ── Session persistence RPC ────────────────────────────────────────────
|
||||
|
||||
/** Save/update a session record. */
|
||||
"session.save": {
|
||||
params: {
|
||||
projectId: string; sessionId: string; provider: string;
|
||||
status: string; costUsd: number; inputTokens: number;
|
||||
outputTokens: number; model: string; error?: string;
|
||||
createdAt: number; updatedAt: number;
|
||||
};
|
||||
response: { ok: boolean };
|
||||
};
|
||||
/** Load the most recent session for a project. */
|
||||
"session.load": {
|
||||
params: { projectId: string };
|
||||
response: {
|
||||
session: {
|
||||
projectId: string; sessionId: string; provider: string;
|
||||
status: string; costUsd: number; inputTokens: number;
|
||||
outputTokens: number; model: string; error?: string;
|
||||
createdAt: number; updatedAt: number;
|
||||
} | null;
|
||||
};
|
||||
};
|
||||
/** List sessions for a project (max 20). */
|
||||
"session.list": {
|
||||
params: { projectId: string };
|
||||
response: {
|
||||
sessions: Array<{
|
||||
projectId: string; sessionId: string; provider: string;
|
||||
status: string; costUsd: number; inputTokens: number;
|
||||
outputTokens: number; model: string; error?: string;
|
||||
createdAt: number; updatedAt: number;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Save agent messages (batch). */
|
||||
"session.messages.save": {
|
||||
params: {
|
||||
messages: Array<{
|
||||
sessionId: string; msgId: string; role: string; content: string;
|
||||
toolName?: string; toolInput?: string; timestamp: number;
|
||||
costUsd?: number; inputTokens?: number; outputTokens?: number;
|
||||
}>;
|
||||
};
|
||||
response: { ok: boolean };
|
||||
};
|
||||
/** Load all messages for a session. */
|
||||
"session.messages.load": {
|
||||
params: { sessionId: string };
|
||||
response: {
|
||||
messages: Array<{
|
||||
sessionId: string; msgId: string; role: string; content: string;
|
||||
toolName?: string; toolInput?: string; timestamp: number;
|
||||
costUsd: number; inputTokens: number; outputTokens: number;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
|
||||
// ── btmsg RPC ──────────────────────────────────────────────────────────
|
||||
|
||||
/** Register an agent in btmsg. */
|
||||
"btmsg.registerAgent": {
|
||||
params: {
|
||||
id: string; name: string; role: string;
|
||||
groupId: string; tier: number; model?: string;
|
||||
};
|
||||
response: { ok: boolean };
|
||||
};
|
||||
/** List agents for a group. */
|
||||
"btmsg.getAgents": {
|
||||
params: { groupId: string };
|
||||
response: {
|
||||
agents: Array<{
|
||||
id: string; name: string; role: string; groupId: string;
|
||||
tier: number; model: string | null; status: string; unreadCount: number;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Send a direct message between agents. */
|
||||
"btmsg.sendMessage": {
|
||||
params: { fromAgent: string; toAgent: string; content: string };
|
||||
response: { ok: boolean; messageId?: string; error?: string };
|
||||
};
|
||||
/** Get message history between two agents. */
|
||||
"btmsg.listMessages": {
|
||||
params: { agentId: string; otherId: string; limit?: number };
|
||||
response: {
|
||||
messages: Array<{
|
||||
id: string; fromAgent: string; toAgent: string; content: string;
|
||||
read: boolean; replyTo: string | null; createdAt: string;
|
||||
senderName: string | null; senderRole: string | null;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Mark messages as read. */
|
||||
"btmsg.markRead": {
|
||||
params: { agentId: string; messageIds: string[] };
|
||||
response: { ok: boolean };
|
||||
};
|
||||
/** List channels for a group. */
|
||||
"btmsg.listChannels": {
|
||||
params: { groupId: string };
|
||||
response: {
|
||||
channels: Array<{
|
||||
id: string; name: string; groupId: string; createdBy: string;
|
||||
memberCount: number; createdAt: string;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Create a channel. */
|
||||
"btmsg.createChannel": {
|
||||
params: { name: string; groupId: string; createdBy: string };
|
||||
response: { ok: boolean; channelId?: string };
|
||||
};
|
||||
/** Get channel messages. */
|
||||
"btmsg.getChannelMessages": {
|
||||
params: { channelId: string; limit?: number };
|
||||
response: {
|
||||
messages: Array<{
|
||||
id: string; channelId: string; fromAgent: string; content: string;
|
||||
createdAt: string; senderName: string; senderRole: string;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Send a channel message. */
|
||||
"btmsg.sendChannelMessage": {
|
||||
params: { channelId: string; fromAgent: string; content: string };
|
||||
response: { ok: boolean; messageId?: string };
|
||||
};
|
||||
/** Record agent heartbeat. */
|
||||
"btmsg.heartbeat": {
|
||||
params: { agentId: string };
|
||||
response: { ok: boolean };
|
||||
};
|
||||
/** Get dead letter queue entries. */
|
||||
"btmsg.getDeadLetters": {
|
||||
params: { limit?: number };
|
||||
response: {
|
||||
letters: Array<{
|
||||
id: number; fromAgent: string; toAgent: string;
|
||||
content: string; error: string; createdAt: string;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Log an audit event. */
|
||||
"btmsg.logAudit": {
|
||||
params: { agentId: string; eventType: string; detail: string };
|
||||
response: { ok: boolean };
|
||||
};
|
||||
/** Get audit log. */
|
||||
"btmsg.getAuditLog": {
|
||||
params: { limit?: number };
|
||||
response: {
|
||||
entries: Array<{
|
||||
id: number; agentId: string; eventType: string;
|
||||
detail: string; createdAt: string;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
|
||||
// ── bttask RPC ─────────────────────────────────────────────────────────
|
||||
|
||||
/** List tasks for a group. */
|
||||
"bttask.listTasks": {
|
||||
params: { groupId: string };
|
||||
response: {
|
||||
tasks: Array<{
|
||||
id: string; title: string; description: string; status: string;
|
||||
priority: string; assignedTo: string | null; createdBy: string;
|
||||
groupId: string; parentTaskId: string | null; sortOrder: number;
|
||||
createdAt: string; updatedAt: string; version: number;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Create a task. */
|
||||
"bttask.createTask": {
|
||||
params: {
|
||||
title: string; description: string; priority: string;
|
||||
groupId: string; createdBy: string; assignedTo?: string;
|
||||
};
|
||||
response: { ok: boolean; taskId?: string; error?: string };
|
||||
};
|
||||
/** Update task status with optimistic locking. */
|
||||
"bttask.updateTaskStatus": {
|
||||
params: { taskId: string; status: string; expectedVersion: number };
|
||||
response: { ok: boolean; newVersion?: number; error?: string };
|
||||
};
|
||||
/** Delete a task. */
|
||||
"bttask.deleteTask": {
|
||||
params: { taskId: string };
|
||||
response: { ok: boolean };
|
||||
};
|
||||
/** Add a comment to a task. */
|
||||
"bttask.addComment": {
|
||||
params: { taskId: string; agentId: string; content: string };
|
||||
response: { ok: boolean; commentId?: string };
|
||||
};
|
||||
/** List comments for a task. */
|
||||
"bttask.listComments": {
|
||||
params: { taskId: string };
|
||||
response: {
|
||||
comments: Array<{
|
||||
id: string; taskId: string; agentId: string;
|
||||
content: string; createdAt: string;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Count tasks in 'review' status. */
|
||||
"bttask.reviewQueueCount": {
|
||||
params: { groupId: string };
|
||||
response: { count: number };
|
||||
};
|
||||
|
||||
// ── Search RPC ──────────────────────────────────────────────────────────
|
||||
|
||||
/** Full-text search across messages, tasks, and btmsg. */
|
||||
"search.query": {
|
||||
params: { query: string; limit?: number };
|
||||
response: {
|
||||
results: Array<{
|
||||
resultType: string;
|
||||
id: string;
|
||||
title: string;
|
||||
snippet: string;
|
||||
score: number;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Index a message for search. */
|
||||
"search.indexMessage": {
|
||||
params: { sessionId: string; role: string; content: string };
|
||||
response: { ok: boolean };
|
||||
};
|
||||
/** Rebuild the entire search index. */
|
||||
"search.rebuild": {
|
||||
params: Record<string, never>;
|
||||
response: { ok: boolean };
|
||||
};
|
||||
|
||||
// ── Plugin RPC ──────────────────────────────────────────────────────────
|
||||
|
||||
/** Discover plugins from ~/.config/agor/plugins/. */
|
||||
"plugin.discover": {
|
||||
params: Record<string, never>;
|
||||
response: {
|
||||
plugins: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
version: string;
|
||||
description: string;
|
||||
main: string;
|
||||
permissions: string[];
|
||||
}>;
|
||||
};
|
||||
};
|
||||
/** Read a plugin file (path-traversal-safe). */
|
||||
"plugin.readFile": {
|
||||
params: { pluginId: string; filePath: string };
|
||||
response: { ok: boolean; content: string; error?: string };
|
||||
};
|
||||
};
|
||||
|
||||
// ── Messages (Bun → WebView, fire-and-forget) ────────────────────────────────
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue