feat: add sproutclaw webui
This commit is contained in:
@@ -25,6 +25,7 @@ import { type Theme, theme } from "../interactive/theme/theme.js";
|
||||
import { attachJsonlLineReader, serializeJsonLine } from "./jsonl.js";
|
||||
import type {
|
||||
RpcCommand,
|
||||
RpcExtensionInfo,
|
||||
RpcExtensionUIRequest,
|
||||
RpcExtensionUIResponse,
|
||||
RpcResponse,
|
||||
@@ -442,10 +443,18 @@ export async function runRpcMode(runtimeHost: AgentSessionRuntime): Promise<neve
|
||||
autoCompactionEnabled: session.autoCompactionEnabled,
|
||||
messageCount: session.messages.length,
|
||||
pendingMessageCount: session.pendingMessageCount,
|
||||
turnIndex: session.turnIndex,
|
||||
stats: session.getSessionStats(),
|
||||
};
|
||||
return success(id, "get_state", state);
|
||||
}
|
||||
|
||||
case "reload": {
|
||||
await session.reload();
|
||||
await rebindSession();
|
||||
return success(id, "reload");
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Model
|
||||
// =================================================================
|
||||
@@ -561,7 +570,7 @@ export async function runRpcMode(runtimeHost: AgentSessionRuntime): Promise<neve
|
||||
}
|
||||
|
||||
case "switch_session": {
|
||||
const result = await runtimeHost.switchSession(command.sessionPath);
|
||||
const result = await runtimeHost.switchSession(command.sessionPath, { cwdOverride: command.cwdOverride });
|
||||
if (!result.cancelled) {
|
||||
await rebindSession();
|
||||
}
|
||||
@@ -652,6 +661,26 @@ export async function runRpcMode(runtimeHost: AgentSessionRuntime): Promise<neve
|
||||
return success(id, "get_commands", { commands });
|
||||
}
|
||||
|
||||
case "get_extensions": {
|
||||
const extensionsResult = session.resourceLoader.getExtensions();
|
||||
const extensions: RpcExtensionInfo[] = extensionsResult.extensions.map((extension) => {
|
||||
const name = extension.path.split(/[\\/]/).filter(Boolean).pop() || extension.path;
|
||||
return {
|
||||
name,
|
||||
path: extension.path,
|
||||
resolvedPath: extension.resolvedPath,
|
||||
sourceInfo: extension.sourceInfo,
|
||||
commands: Array.from(extension.commands.keys()).sort(),
|
||||
tools: Array.from(extension.tools.keys()).sort(),
|
||||
flags: Array.from(extension.flags.keys()).sort(),
|
||||
shortcuts: Array.from(extension.shortcuts.keys()).map(String).sort(),
|
||||
handlers: Array.from(extension.handlers.keys()).sort(),
|
||||
};
|
||||
});
|
||||
|
||||
return success(id, "get_extensions", { extensions, errors: extensionsResult.errors });
|
||||
}
|
||||
|
||||
default: {
|
||||
const unknownCommand = command as { type: string };
|
||||
return error(undefined, unknownCommand.type, `Unknown command: ${unknownCommand.type}`);
|
||||
|
||||
@@ -26,6 +26,7 @@ export type RpcCommand =
|
||||
|
||||
// State
|
||||
| { id?: string; type: "get_state" }
|
||||
| { id?: string; type: "reload" }
|
||||
|
||||
// Model
|
||||
| { id?: string; type: "set_model"; provider: string; modelId: string }
|
||||
@@ -55,7 +56,7 @@ export type RpcCommand =
|
||||
// Session
|
||||
| { id?: string; type: "get_session_stats" }
|
||||
| { id?: string; type: "export_html"; outputPath?: string }
|
||||
| { id?: string; type: "switch_session"; sessionPath: string }
|
||||
| { id?: string; type: "switch_session"; sessionPath: string; cwdOverride?: string }
|
||||
| { id?: string; type: "fork"; entryId: string }
|
||||
| { id?: string; type: "clone" }
|
||||
| { id?: string; type: "get_fork_messages" }
|
||||
@@ -66,7 +67,8 @@ export type RpcCommand =
|
||||
| { id?: string; type: "get_messages" }
|
||||
|
||||
// Commands (available for invocation via prompt)
|
||||
| { id?: string; type: "get_commands" };
|
||||
| { id?: string; type: "get_commands" }
|
||||
| { id?: string; type: "get_extensions" };
|
||||
|
||||
// ============================================================================
|
||||
// RPC Slash Command (for get_commands response)
|
||||
@@ -84,6 +86,19 @@ export interface RpcSlashCommand {
|
||||
sourceInfo: SourceInfo;
|
||||
}
|
||||
|
||||
/** A loaded extension with basic inventory metadata */
|
||||
export interface RpcExtensionInfo {
|
||||
name: string;
|
||||
path: string;
|
||||
resolvedPath: string;
|
||||
sourceInfo: SourceInfo;
|
||||
commands: string[];
|
||||
tools: string[];
|
||||
flags: string[];
|
||||
shortcuts: string[];
|
||||
handlers: string[];
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// RPC State
|
||||
// ============================================================================
|
||||
@@ -101,6 +116,9 @@ export interface RpcSessionState {
|
||||
autoCompactionEnabled: boolean;
|
||||
messageCount: number;
|
||||
pendingMessageCount: number;
|
||||
/** Mirrors {@link AgentSession.turnIndex} (ticks every turn_end, resets agent_start). */
|
||||
turnIndex: number;
|
||||
stats: SessionStats;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -118,6 +136,7 @@ export type RpcResponse =
|
||||
|
||||
// State
|
||||
| { id?: string; type: "response"; command: "get_state"; success: true; data: RpcSessionState }
|
||||
| { id?: string; type: "response"; command: "reload"; success: true }
|
||||
|
||||
// Model
|
||||
| {
|
||||
@@ -201,6 +220,13 @@ export type RpcResponse =
|
||||
success: true;
|
||||
data: { commands: RpcSlashCommand[] };
|
||||
}
|
||||
| {
|
||||
id?: string;
|
||||
type: "response";
|
||||
command: "get_extensions";
|
||||
success: true;
|
||||
data: { extensions: RpcExtensionInfo[]; errors: Array<{ path: string; error: string }> };
|
||||
}
|
||||
|
||||
// Error response (any command can fail)
|
||||
| { id?: string; type: "response"; command: string; success: false; error: string };
|
||||
|
||||
Reference in New Issue
Block a user