[hAIk]: (add frontend bridge files for all backend sub-apps) (fix: collapse multi-param async thunk payloads into single objects)

This commit is contained in:
haikdc
2026-04-18 02:35:08 -07:00
parent 2a898f3f08
commit e4f400962f
9 changed files with 1209 additions and 49 deletions
+67 -49
View File
@@ -65,11 +65,14 @@ export const LAUNCH_AGENT = createAsyncThunk(
const update_system_prompt_endpoint: string = `${AGENTS_API}/update_system_prompt`;
async function update_system_prompt_function(sessionId: string, systemPrompt: string): Promise<string> {
async function update_system_prompt_function(payload: {
sessionId: string;
systemPrompt: string;
}): Promise<string> {
const res = await fetch(update_system_prompt_endpoint, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ session_id: sessionId, system_prompt: systemPrompt }),
body: JSON.stringify({ session_id: payload.sessionId, system_prompt: payload.systemPrompt }),
});
const data = await res.json();
return data.ok as string;
@@ -105,34 +108,34 @@ export const DELETE_SESSION = createAsyncThunk(
const send_message_endpoint: string = `${AGENTS_API}/send_message`;
async function send_message_function(
sessionId: string,
prompt: string,
mode: string,
model: string,
provider: string,
images: string[],
contextPaths: string[],
forcedTools: string[],
attachedSkills: string[],
hidden: boolean,
selectedBrowserIds: string[]
): Promise<AgentSession> {
async function send_message_function(payload: {
sessionId: string;
prompt: string;
mode: string;
model: string;
provider: string;
images: string[];
contextPaths: string[];
forcedTools: string[];
attachedSkills: string[];
hidden: boolean;
selectedBrowserIds: string[];
}): Promise<AgentSession> {
const res = await fetch(send_message_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
session_id: sessionId,
prompt: prompt,
mode: mode,
model: model,
provider: provider,
images: images,
context_paths: contextPaths,
forced_tools: forcedTools,
attached_skills: attachedSkills,
hidden: hidden,
selected_browser_ids: selectedBrowserIds,
session_id: payload.sessionId,
prompt: payload.prompt,
mode: payload.mode,
model: payload.model,
provider: payload.provider,
images: payload.images,
context_paths: payload.contextPaths,
forced_tools: payload.forcedTools,
attached_skills: payload.attachedSkills,
hidden: payload.hidden,
selected_browser_ids: payload.selectedBrowserIds,
}),
});
const data = await res.json();
@@ -163,24 +166,24 @@ export const STOP_AGENT = createAsyncThunk(
const handle_approval_endpoint: string = `${AGENTS_API}/handle_approval`;
async function handle_approval_function(
requestId: string,
behavior: 'allow' | 'deny',
message?: string,
updatedInput?: Record<string, unknown>
): Promise<{ requestId: string; behavior: 'allow' | 'deny' }> {
async function handle_approval_function(payload: {
requestId: string;
behavior: 'allow' | 'deny';
message?: string;
updatedInput?: Record<string, unknown>;
}): Promise<{ requestId: string; behavior: 'allow' | 'deny' }> {
const res = await fetch(handle_approval_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
request_id: requestId,
behavior: behavior,
message: message,
updated_input: updatedInput,
request_id: payload.requestId,
behavior: payload.behavior,
message: payload.message,
updated_input: payload.updatedInput,
}),
});
if (!res.ok) throw new Error(`Approval request failed (${res.status})`);
return { requestId, behavior };
return { requestId: payload.requestId, behavior: payload.behavior };
}
export const HANDLE_APPROVAL = createAsyncThunk(
handle_approval_endpoint,
@@ -197,14 +200,18 @@ export const HANDLE_APPROVAL = createAsyncThunk(
const edit_message_endpoint: string = `${AGENTS_API}/edit_message`;
async function edit_message_function(sessionId: string, messageId: string, content: string): Promise<AgentSession> {
async function edit_message_function(payload: {
sessionId: string;
messageId: string;
content: string;
}): Promise<AgentSession> {
const res = await fetch(edit_message_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
session_id: sessionId,
message_id: messageId,
content: content,
session_id: payload.sessionId,
message_id: payload.messageId,
content: payload.content,
}),
});
const data = await res.json();
@@ -217,11 +224,14 @@ export const EDIT_MESSAGE = createAsyncThunk(
const switch_branch_endpoint: string = `${AGENTS_API}/switch_branch`;
async function switch_branch_function(sessionId: string, branchId: string): Promise<AgentSession> {
async function switch_branch_function(payload: {
sessionId: string;
branchId: string;
}): Promise<AgentSession> {
const res = await fetch(switch_branch_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ session_id: sessionId, branch_id: branchId }),
body: JSON.stringify({ session_id: payload.sessionId, branch_id: payload.branchId }),
});
const data = await res.json();
return data.session as AgentSession;
@@ -274,14 +284,18 @@ export const RESUME_SESSION = createAsyncThunk(
const duplicate_session_endpoint: string = `${AGENTS_API}/duplicate_session`;
async function duplicate_session_function(sessionId: string, dashboardId: string, upToMessageId: string): Promise<AgentSession> {
async function duplicate_session_function(payload: {
sessionId: string;
dashboardId: string;
upToMessageId: string;
}): Promise<AgentSession> {
const res = await fetch(duplicate_session_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
session_id: sessionId,
dashboard_id: dashboardId,
up_to_message_id: upToMessageId,
session_id: payload.sessionId,
dashboard_id: payload.dashboardId,
up_to_message_id: payload.upToMessageId,
}),
});
const data = await res.json();
@@ -295,11 +309,15 @@ export const DUPLICATE_SESSION = createAsyncThunk(
const get_history_endpoint: string = `${AGENTS_API}/get_history`;
async function get_history_function(q: string, limit: number, offset: number): Promise<HistorySession[]> {
async function get_history_function(payload: {
q: string;
limit: number;
offset: number;
}): Promise<HistorySession[]> {
const res = await fetch(get_history_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ q, limit, offset }),
body: JSON.stringify({ q: payload.q, limit: payload.limit, offset: payload.offset }),
});
const data = await res.json();
return data.sessions as HistorySession[];
@@ -0,0 +1,240 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { API_BASE } from '@/shared/backend/base_routes';
const APP_BUILDER_API: string = `${API_BASE}/app_builder`;
// ---------------------------------------------------------------------------
// File serving
// ---------------------------------------------------------------------------
const serve_app_source_file_endpoint: string = `${APP_BUILDER_API}/app/source_dir`;
async function serve_app_source_file_function(appId: string, filepath: string): Promise<string> {
const res = await fetch(`${APP_BUILDER_API}/app/${appId}/source_dir/${filepath}`, {
method: 'GET',
});
const text = await res.text();
return text;
}
export const SERVE_APP_SOURCE_FILE = createAsyncThunk(
serve_app_source_file_endpoint,
serve_app_source_file_function,
);
const serve_app_file_endpoint: string = `${APP_BUILDER_API}/serve`;
async function serve_app_file_function(appId: string, filepath: string): Promise<string> {
const res = await fetch(`${APP_BUILDER_API}/${appId}/serve/${filepath}`, {
method: 'GET',
});
const text = await res.text();
return text;
}
export const SERVE_APP_FILE = createAsyncThunk(
serve_app_file_endpoint,
serve_app_file_function,
);
// ---------------------------------------------------------------------------
// Workspace management
// ---------------------------------------------------------------------------
const read_app_endpoint: string = `${APP_BUILDER_API}/app`;
async function read_app_function(appId: string): Promise<{ files: Record<string, string>; meta: Record<string, unknown> | null }> {
const res = await fetch(`${APP_BUILDER_API}/app/${appId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { files: Record<string, string>; meta: Record<string, unknown> | null };
}
export const READ_APP = createAsyncThunk(
read_app_endpoint,
read_app_function,
);
const seed_app_endpoint: string = `${APP_BUILDER_API}/app/seed`;
async function seed_app_function(body: {
app_id: string;
files?: Record<string, string> | null;
meta?: Record<string, unknown> | null;
}): Promise<{ path: string }> {
const res = await fetch(seed_app_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
return data as { path: string };
}
export const SEED_APP = createAsyncThunk(
seed_app_endpoint,
seed_app_function,
);
const write_app_file_endpoint: string = `${APP_BUILDER_API}/app/file`;
async function write_app_file_function(appId: string, filepath: string, content: string): Promise<{ ok: boolean }> {
const res = await fetch(`${APP_BUILDER_API}/app/${appId}/file/${filepath}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content }),
});
const data = await res.json();
return data as { ok: boolean };
}
export const WRITE_APP_FILE = createAsyncThunk(
write_app_file_endpoint,
write_app_file_function,
);
const delete_app_file_endpoint: string = `${APP_BUILDER_API}/app/file/delete`;
async function delete_app_file_function(appId: string, filepath: string): Promise<{ ok: boolean }> {
const res = await fetch(`${APP_BUILDER_API}/app/${appId}/file/${filepath}`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean };
}
export const DELETE_APP_FILE = createAsyncThunk(
delete_app_file_endpoint,
delete_app_file_function,
);
// ---------------------------------------------------------------------------
// App CRUD
// ---------------------------------------------------------------------------
const list_apps_endpoint: string = `${APP_BUILDER_API}/list`;
async function list_apps_function(): Promise<{ apps: Record<string, unknown>[] }> {
const res = await fetch(list_apps_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { apps: Record<string, unknown>[] };
}
export const LIST_APPS = createAsyncThunk(
list_apps_endpoint,
list_apps_function,
);
const get_app_endpoint: string = `${APP_BUILDER_API}/get`;
async function get_app_function(appId: string): Promise<Record<string, unknown>> {
const res = await fetch(`${APP_BUILDER_API}/${appId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const GET_APP = createAsyncThunk(
get_app_endpoint,
get_app_function,
);
const create_app_endpoint: string = `${APP_BUILDER_API}/create`;
async function create_app_function(body: {
name: string;
description?: string;
icon?: string;
files?: Record<string, string> | null;
thumbnail?: string | null;
}): Promise<{ ok: boolean; app: Record<string, unknown> }> {
const res = await fetch(create_app_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
return data as { ok: boolean; app: Record<string, unknown> };
}
export const CREATE_APP = createAsyncThunk(
create_app_endpoint,
create_app_function,
);
const update_app_endpoint: string = `${APP_BUILDER_API}/update`;
async function update_app_function(
appId: string,
updates: {
name?: string;
description?: string;
icon?: string;
thumbnail?: string | null;
},
): Promise<{ ok: boolean; app: Record<string, unknown> }> {
const res = await fetch(`${APP_BUILDER_API}/${appId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates),
});
const data = await res.json();
return data as { ok: boolean; app: Record<string, unknown> };
}
export const UPDATE_APP = createAsyncThunk(
update_app_endpoint,
update_app_function,
);
const delete_app_endpoint: string = `${APP_BUILDER_API}/delete`;
async function delete_app_function(appId: string): Promise<{ ok: boolean }> {
const res = await fetch(`${APP_BUILDER_API}/${appId}`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean };
}
export const DELETE_APP = createAsyncThunk(
delete_app_endpoint,
delete_app_function,
);
// ---------------------------------------------------------------------------
// Execution
// ---------------------------------------------------------------------------
const execute_app_endpoint: string = `${APP_BUILDER_API}/execute`;
async function execute_app_function(appId: string): Promise<{
app_id: string;
app_name: string;
frontend_code: string;
backend_result: Record<string, unknown> | null;
stdout: string | null;
stderr: string | null;
error: string | null;
}> {
const res = await fetch(execute_app_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ app_id: appId }),
});
const data = await res.json();
return data as {
app_id: string;
app_name: string;
frontend_code: string;
backend_result: Record<string, unknown> | null;
stdout: string | null;
stderr: string | null;
error: string | null;
};
}
export const EXECUTE_APP = createAsyncThunk(
execute_app_endpoint,
execute_app_function,
);
@@ -0,0 +1,121 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { API_BASE } from '@/shared/backend/base_routes';
const DASHBOARDS_API: string = `${API_BASE}/dashboards`;
// ---------------------------------------------------------------------------
// Dashboard CRUD
// ---------------------------------------------------------------------------
const list_dashboards_endpoint: string = `${DASHBOARDS_API}/list`;
async function list_dashboards_function(): Promise<Record<string, unknown>[]> {
const res = await fetch(list_dashboards_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data.dashboards as Record<string, unknown>[];
}
export const LIST_DASHBOARDS = createAsyncThunk(
list_dashboards_endpoint,
list_dashboards_function,
);
const create_dashboard_endpoint: string = `${DASHBOARDS_API}/create`;
async function create_dashboard_function(name: string = 'Untitled Dashboard'): Promise<Record<string, unknown>> {
const res = await fetch(create_dashboard_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name }),
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const CREATE_DASHBOARD = createAsyncThunk(
create_dashboard_endpoint,
create_dashboard_function,
);
const generate_dashboard_name_endpoint: string = `${DASHBOARDS_API}/generate-name`;
async function generate_dashboard_name_function(dashboardId: string): Promise<{ name: string; auto_named: boolean }> {
const res = await fetch(`${DASHBOARDS_API}/${dashboardId}/generate-name`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { name: string; auto_named: boolean };
}
export const GENERATE_DASHBOARD_NAME = createAsyncThunk(
generate_dashboard_name_endpoint,
generate_dashboard_name_function,
);
const get_dashboard_endpoint: string = `${DASHBOARDS_API}/get`;
async function get_dashboard_function(dashboardId: string): Promise<Record<string, unknown>> {
const res = await fetch(`${DASHBOARDS_API}/${dashboardId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const GET_DASHBOARD = createAsyncThunk(
get_dashboard_endpoint,
get_dashboard_function,
);
const update_dashboard_endpoint: string = `${DASHBOARDS_API}/update`;
async function update_dashboard_function(args: {
dashboardId: string;
name?: string;
layout?: Record<string, unknown>;
thumbnail?: string;
}): Promise<Record<string, unknown>> {
const { dashboardId, ...updates } = args;
const res = await fetch(`${DASHBOARDS_API}/${dashboardId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates),
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const UPDATE_DASHBOARD = createAsyncThunk(
update_dashboard_endpoint,
update_dashboard_function,
);
const delete_dashboard_endpoint: string = `${DASHBOARDS_API}/delete`;
async function delete_dashboard_function(dashboardId: string): Promise<{ ok: boolean }> {
const res = await fetch(`${DASHBOARDS_API}/${dashboardId}`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean };
}
export const DELETE_DASHBOARD = createAsyncThunk(
delete_dashboard_endpoint,
delete_dashboard_function,
);
const duplicate_dashboard_endpoint: string = `${DASHBOARDS_API}/duplicate`;
async function duplicate_dashboard_function(dashboardId: string): Promise<Record<string, unknown>> {
const res = await fetch(`${DASHBOARDS_API}/${dashboardId}/duplicate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const DUPLICATE_DASHBOARD = createAsyncThunk(
duplicate_dashboard_endpoint,
duplicate_dashboard_function,
);
@@ -0,0 +1,22 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { API_BASE } from '@/shared/backend/base_routes';
const HEALTH_API: string = `${API_BASE}/health`;
// ---------------------------------------------------------------------------
// Health Check
// ---------------------------------------------------------------------------
const check_health_endpoint: string = `${HEALTH_API}/check`;
async function check_health_function(): Promise<string> {
const res = await fetch(check_health_endpoint, {
method: 'GET',
});
const text = await res.text();
return text;
}
export const CHECK_HEALTH = createAsyncThunk(
check_health_endpoint,
check_health_function,
);
+136
View File
@@ -0,0 +1,136 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { API_BASE } from '@/shared/backend/base_routes';
const MODES_API: string = `${API_BASE}/modes`;
// ---------------------------------------------------------------------------
// Mode CRUD
// ---------------------------------------------------------------------------
const list_modes_endpoint: string = `${MODES_API}/list`;
async function list_modes_function(): Promise<{ modes: Record<string, unknown>[]; builtin_defaults: Record<string, Record<string, unknown>> }> {
const res = await fetch(list_modes_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { modes: Record<string, unknown>[]; builtin_defaults: Record<string, Record<string, unknown>> };
}
export const LIST_MODES = createAsyncThunk(
list_modes_endpoint,
list_modes_function,
);
const get_mode_endpoint: string = `${MODES_API}/get`;
async function get_mode_function(modeId: string): Promise<Record<string, unknown>> {
const res = await fetch(`${MODES_API}/${modeId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const GET_MODE = createAsyncThunk(
get_mode_endpoint,
get_mode_function,
);
const create_mode_endpoint: string = `${MODES_API}/create`;
async function create_mode_function(body: {
name: string;
description?: string;
system_prompt?: string | null;
tools?: string[] | null;
default_next_mode?: string | null;
icon?: string;
color?: string;
default_folder?: string | null;
}): Promise<{ ok: boolean; mode: Record<string, unknown> }> {
const res = await fetch(create_mode_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
return data as { ok: boolean; mode: Record<string, unknown> };
}
export const CREATE_MODE = createAsyncThunk(
create_mode_endpoint,
create_mode_function,
);
const update_mode_endpoint: string = `${MODES_API}/update`;
async function update_mode_function(args: {
modeId: string;
name?: string;
description?: string;
system_prompt?: string | null;
tools?: string[] | null;
default_next_mode?: string | null;
icon?: string;
color?: string;
default_folder?: string | null;
}): Promise<{ ok: boolean; mode: Record<string, unknown> }> {
const { modeId, ...updates } = args;
const res = await fetch(`${MODES_API}/${modeId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates),
});
const data = await res.json();
return data as { ok: boolean; mode: Record<string, unknown> };
}
export const UPDATE_MODE = createAsyncThunk(
update_mode_endpoint,
update_mode_function,
);
const reset_mode_endpoint: string = `${MODES_API}/reset`;
async function reset_mode_function(modeId: string): Promise<{ ok: boolean; mode: Record<string, unknown> }> {
const res = await fetch(`${MODES_API}/${modeId}/reset`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean; mode: Record<string, unknown> };
}
export const RESET_MODE = createAsyncThunk(
reset_mode_endpoint,
reset_mode_function,
);
const delete_mode_endpoint: string = `${MODES_API}/delete`;
async function delete_mode_function(modeId: string): Promise<{ ok: boolean }> {
const res = await fetch(`${MODES_API}/${modeId}`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean };
}
export const DELETE_MODE = createAsyncThunk(
delete_mode_endpoint,
delete_mode_function,
);
const get_mode_by_id_endpoint: string = `${MODES_API}/get_mode_by_id`;
async function get_mode_by_id_function(modeId: string): Promise<Record<string, unknown> | null> {
const res = await fetch(get_mode_by_id_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ mode_id: modeId }),
});
const data = await res.json();
return data as Record<string, unknown> | null;
}
export const GET_MODE_BY_ID = createAsyncThunk(
get_mode_by_id_endpoint,
get_mode_by_id_function,
);
@@ -0,0 +1,69 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { API_BASE } from '@/shared/backend/base_routes';
const SETTINGS_API: string = `${API_BASE}/settings`;
// ---------------------------------------------------------------------------
// Settings
// ---------------------------------------------------------------------------
const get_settings_endpoint: string = SETTINGS_API;
async function get_settings_function(): Promise<Record<string, unknown>> {
const res = await fetch(get_settings_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const GET_SETTINGS = createAsyncThunk(
get_settings_endpoint,
get_settings_function,
);
const update_settings_endpoint: string = SETTINGS_API;
async function update_settings_function(body: {
default_system_prompt?: string;
default_folder?: string | null;
default_model?: string;
default_mode?: string;
default_max_turns?: number | null;
anthropic_api_key?: string | null;
zoom_sensitivity?: number;
theme?: string;
new_agent_shortcut?: string;
browser_homepage?: string;
auto_select_mode_on_new_agent?: boolean;
expand_new_chats_in_dashboard?: boolean;
auto_reveal_sub_agents?: boolean;
dev_mode?: boolean;
}): Promise<{ ok: boolean; settings: Record<string, unknown> }> {
const res = await fetch(update_settings_endpoint, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
return data as { ok: boolean; settings: Record<string, unknown> };
}
export const UPDATE_SETTINGS = createAsyncThunk(
update_settings_endpoint,
update_settings_function,
);
const reset_system_prompt_endpoint: string = `${SETTINGS_API}/reset-system-prompt`;
async function reset_system_prompt_function(): Promise<{ ok: boolean; settings: Record<string, unknown> }> {
const res = await fetch(reset_system_prompt_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean; settings: Record<string, unknown> };
}
export const RESET_SYSTEM_PROMPT = createAsyncThunk(
reset_system_prompt_endpoint,
reset_system_prompt_function,
);
+194
View File
@@ -0,0 +1,194 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { API_BASE } from '@/shared/backend/base_routes';
const SKILLS_API: string = `${API_BASE}/skills`;
// ---------------------------------------------------------------------------
// Local skill CRUD
// ---------------------------------------------------------------------------
const list_skills_endpoint: string = `${SKILLS_API}/list`;
async function list_skills_function(): Promise<Record<string, unknown>[]> {
const res = await fetch(list_skills_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data.skills as Record<string, unknown>[];
}
export const LIST_SKILLS = createAsyncThunk(
list_skills_endpoint,
list_skills_function,
);
const read_skill_workspace_endpoint: string = `${SKILLS_API}/workspace`;
async function read_skill_workspace_function(workspaceId: string): Promise<{ skill_content: string | null; meta: Record<string, unknown> | null; frontmatter: Record<string, unknown> }> {
const res = await fetch(`${SKILLS_API}/workspace/${workspaceId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { skill_content: string | null; meta: Record<string, unknown> | null; frontmatter: Record<string, unknown> };
}
export const READ_SKILL_WORKSPACE = createAsyncThunk(
read_skill_workspace_endpoint,
read_skill_workspace_function,
);
const seed_skill_workspace_endpoint: string = `${SKILLS_API}/workspace/seed`;
async function seed_skill_workspace_function(body: {
workspace_id: string;
skill_content?: string | null;
meta?: Record<string, unknown> | null;
}): Promise<{ path: string }> {
const res = await fetch(seed_skill_workspace_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
return data as { path: string };
}
export const SEED_SKILL_WORKSPACE = createAsyncThunk(
seed_skill_workspace_endpoint,
seed_skill_workspace_function,
);
const get_skill_endpoint: string = `${SKILLS_API}/detail`;
async function get_skill_function(skillId: string): Promise<Record<string, unknown>> {
const res = await fetch(`${SKILLS_API}/detail/${skillId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const GET_SKILL = createAsyncThunk(
get_skill_endpoint,
get_skill_function,
);
const create_skill_endpoint: string = `${SKILLS_API}/create`;
async function create_skill_function(body: {
name: string;
description?: string;
content: string;
command?: string;
}): Promise<{ ok: boolean; skill: Record<string, unknown> }> {
const res = await fetch(create_skill_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
return data as { ok: boolean; skill: Record<string, unknown> };
}
export const CREATE_SKILL = createAsyncThunk(
create_skill_endpoint,
create_skill_function,
);
const update_skill_endpoint: string = `${SKILLS_API}/update`;
async function update_skill_function(args: {
skillId: string;
name?: string;
description?: string;
content?: string;
command?: string;
}): Promise<{ ok: boolean; skill: Record<string, unknown> }> {
const { skillId, ...updates } = args;
const res = await fetch(`${SKILLS_API}/${skillId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates),
});
const data = await res.json();
return data as { ok: boolean; skill: Record<string, unknown> };
}
export const UPDATE_SKILL = createAsyncThunk(
update_skill_endpoint,
update_skill_function,
);
const delete_skill_endpoint: string = `${SKILLS_API}/delete`;
async function delete_skill_function(skillId: string): Promise<{ ok: boolean }> {
const res = await fetch(`${SKILLS_API}/${skillId}`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean };
}
export const DELETE_SKILL = createAsyncThunk(
delete_skill_endpoint,
delete_skill_function,
);
// ---------------------------------------------------------------------------
// Registry
// ---------------------------------------------------------------------------
const registry_stats_endpoint: string = `${SKILLS_API}/registry/stats`;
async function registry_stats_function(): Promise<{ total: number; categories: Record<string, number>; lastUpdated: string | null }> {
const res = await fetch(registry_stats_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { total: number; categories: Record<string, number>; lastUpdated: string | null };
}
export const REGISTRY_STATS = createAsyncThunk(
registry_stats_endpoint,
registry_stats_function,
);
const registry_search_endpoint: string = `${SKILLS_API}/registry/search`;
async function registry_search_function(params: {
q?: string;
limit?: number;
offset?: number;
sort?: string;
category?: string;
}): Promise<{ skills: Record<string, unknown>[]; total: number; offset: number; limit: number }> {
const query = new URLSearchParams();
if (params.q) query.set('q', params.q);
if (params.limit !== undefined) query.set('limit', String(params.limit));
if (params.offset !== undefined) query.set('offset', String(params.offset));
if (params.sort) query.set('sort', params.sort);
if (params.category) query.set('category', params.category);
const res = await fetch(`${registry_search_endpoint}?${query.toString()}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { skills: Record<string, unknown>[]; total: number; offset: number; limit: number };
}
export const REGISTRY_SEARCH = createAsyncThunk(
registry_search_endpoint,
registry_search_function,
);
const registry_detail_endpoint: string = `${SKILLS_API}/registry/detail`;
async function registry_detail_function(skillName: string): Promise<{ skill: Record<string, unknown> }> {
const res = await fetch(`${SKILLS_API}/registry/detail/${skillName}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { skill: Record<string, unknown> };
}
export const REGISTRY_DETAIL = createAsyncThunk(
registry_detail_endpoint,
registry_detail_function,
);
@@ -0,0 +1,113 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { API_BASE } from '@/shared/backend/base_routes';
const SUBSCRIPTIONS_API: string = `${API_BASE}/subscriptions`;
// ---------------------------------------------------------------------------
// Subscription management
// ---------------------------------------------------------------------------
const subscriptions_status_endpoint: string = `${SUBSCRIPTIONS_API}/status`;
async function subscriptions_status_function(): Promise<{ running: boolean; providers: unknown[]; models: unknown[] }> {
const res = await fetch(subscriptions_status_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { running: boolean; providers: unknown[]; models: unknown[] };
}
export const SUBSCRIPTIONS_STATUS = createAsyncThunk(
subscriptions_status_endpoint,
subscriptions_status_function,
);
const subscriptions_connect_endpoint: string = `${SUBSCRIPTIONS_API}/connect`;
async function subscriptions_connect_function(provider: string): Promise<Record<string, unknown>> {
const res = await fetch(subscriptions_connect_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ provider }),
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const SUBSCRIPTIONS_CONNECT = createAsyncThunk(
subscriptions_connect_endpoint,
subscriptions_connect_function,
);
const subscriptions_poll_endpoint: string = `${SUBSCRIPTIONS_API}/poll`;
async function subscriptions_poll_function(body: {
provider: string;
device_code: string;
code_verifier?: string;
extra_data?: Record<string, unknown>;
}): Promise<Record<string, unknown>> {
const res = await fetch(subscriptions_poll_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const SUBSCRIPTIONS_POLL = createAsyncThunk(
subscriptions_poll_endpoint,
subscriptions_poll_function,
);
const subscriptions_disconnect_endpoint: string = `${SUBSCRIPTIONS_API}/disconnect`;
async function subscriptions_disconnect_function(provider: string): Promise<{ ok: boolean; error?: string }> {
const res = await fetch(subscriptions_disconnect_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ provider }),
});
const data = await res.json();
return data as { ok: boolean; error?: string };
}
export const SUBSCRIPTIONS_DISCONNECT = createAsyncThunk(
subscriptions_disconnect_endpoint,
subscriptions_disconnect_function,
);
const subscriptions_pending_endpoint: string = `${SUBSCRIPTIONS_API}/pending`;
async function subscriptions_pending_function(state: string): Promise<{ provider: string; code_verifier: string; redirect_uri: string }> {
const res = await fetch(`${SUBSCRIPTIONS_API}/pending/${state}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { provider: string; code_verifier: string; redirect_uri: string };
}
export const SUBSCRIPTIONS_PENDING = createAsyncThunk(
subscriptions_pending_endpoint,
subscriptions_pending_function,
);
const subscriptions_callback_endpoint: string = `${SUBSCRIPTIONS_API}/callback`;
async function subscriptions_callback_function(params: {
code?: string;
state?: string;
error?: string;
}): Promise<string> {
const query = new URLSearchParams();
if (params.code) query.set('code', params.code);
if (params.state) query.set('state', params.state);
if (params.error) query.set('error', params.error);
const res = await fetch(`${subscriptions_callback_endpoint}?${query.toString()}`, {
method: 'GET',
});
const html = await res.text();
return html;
}
export const SUBSCRIPTIONS_CALLBACK = createAsyncThunk(
subscriptions_callback_endpoint,
subscriptions_callback_function,
);
+247
View File
@@ -0,0 +1,247 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { API_BASE } from '@/shared/backend/base_routes';
const TOOLS_API: string = `${API_BASE}/tools`;
// ---------------------------------------------------------------------------
// Builtin tools
// ---------------------------------------------------------------------------
const list_builtin_tools_endpoint: string = `${TOOLS_API}/builtin`;
async function list_builtin_tools_function(): Promise<{ tools: Record<string, unknown>[] }> {
const res = await fetch(list_builtin_tools_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { tools: Record<string, unknown>[] };
}
export const LIST_BUILTIN_TOOLS = createAsyncThunk(
list_builtin_tools_endpoint,
list_builtin_tools_function,
);
const get_builtin_permissions_endpoint: string = `${TOOLS_API}/builtin/permissions`;
async function get_builtin_permissions_function(): Promise<{ permissions: Record<string, string> }> {
const res = await fetch(get_builtin_permissions_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { permissions: Record<string, string> };
}
export const GET_BUILTIN_PERMISSIONS = createAsyncThunk(
get_builtin_permissions_endpoint,
get_builtin_permissions_function,
);
const update_builtin_permissions_endpoint: string = `${TOOLS_API}/builtin/permissions`;
async function update_builtin_permissions_function(permissions: Record<string, string>): Promise<{ permissions: Record<string, string> }> {
const res = await fetch(update_builtin_permissions_endpoint, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ permissions }),
});
const data = await res.json();
return data as { permissions: Record<string, string> };
}
export const UPDATE_BUILTIN_PERMISSIONS = createAsyncThunk(
update_builtin_permissions_endpoint,
update_builtin_permissions_function,
);
// ---------------------------------------------------------------------------
// User-installed tool CRUD
// ---------------------------------------------------------------------------
const list_tools_endpoint: string = `${TOOLS_API}/list`;
async function list_tools_function(): Promise<{ tools: Record<string, unknown>[] }> {
const res = await fetch(list_tools_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { tools: Record<string, unknown>[] };
}
export const LIST_TOOLS = createAsyncThunk(
list_tools_endpoint,
list_tools_function,
);
const create_tool_endpoint: string = `${TOOLS_API}/create`;
async function create_tool_function(body: {
name: string;
description?: string;
command?: string;
mcp_config?: Record<string, unknown>;
credentials?: Record<string, string>;
auth_type?: string;
auth_status?: string;
oauth_provider?: string | null;
}): Promise<{ ok: boolean; tool: Record<string, unknown> }> {
const res = await fetch(create_tool_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
return data as { ok: boolean; tool: Record<string, unknown> };
}
export const CREATE_TOOL = createAsyncThunk(
create_tool_endpoint,
create_tool_function,
);
const get_tool_endpoint: string = `${TOOLS_API}/get`;
async function get_tool_function(toolId: string): Promise<Record<string, unknown>> {
const res = await fetch(`${TOOLS_API}/${toolId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as Record<string, unknown>;
}
export const GET_TOOL = createAsyncThunk(
get_tool_endpoint,
get_tool_function,
);
const update_tool_endpoint: string = `${TOOLS_API}/update`;
async function update_tool_function(args: {
toolId: string;
name?: string;
description?: string;
command?: string;
mcp_config?: Record<string, unknown>;
credentials?: Record<string, string>;
auth_type?: string;
auth_status?: string;
oauth_provider?: string | null;
oauth_tokens?: Record<string, unknown>;
tool_permissions?: Record<string, string>;
connected_account_email?: string | null;
enabled?: boolean;
}): Promise<{ ok: boolean; tool: Record<string, unknown> }> {
const { toolId, ...updates } = args;
const res = await fetch(`${TOOLS_API}/${toolId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates),
});
const data = await res.json();
return data as { ok: boolean; tool: Record<string, unknown> };
}
export const UPDATE_TOOL = createAsyncThunk(
update_tool_endpoint,
update_tool_function,
);
const delete_tool_endpoint: string = `${TOOLS_API}/delete`;
async function delete_tool_function(toolId: string): Promise<{ ok: boolean }> {
const res = await fetch(`${TOOLS_API}/${toolId}`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean };
}
export const DELETE_TOOL = createAsyncThunk(
delete_tool_endpoint,
delete_tool_function,
);
// ---------------------------------------------------------------------------
// Discovery
// ---------------------------------------------------------------------------
const discover_tool_endpoint: string = `${TOOLS_API}/discover`;
async function discover_tool_function(toolId: string): Promise<{ ok: boolean; tool: Record<string, unknown> }> {
const res = await fetch(`${TOOLS_API}/${toolId}/discover`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean; tool: Record<string, unknown> };
}
export const DISCOVER_TOOL = createAsyncThunk(
discover_tool_endpoint,
discover_tool_function,
);
const load_user_toolkit_endpoint: string = `${TOOLS_API}/load_user_toolkit`;
async function load_user_toolkit_function(): Promise<Record<string, unknown> | null> {
const res = await fetch(load_user_toolkit_endpoint, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as Record<string, unknown> | null;
}
export const LOAD_USER_TOOLKIT = createAsyncThunk(
load_user_toolkit_endpoint,
load_user_toolkit_function,
);
// ---------------------------------------------------------------------------
// OAuth
// ---------------------------------------------------------------------------
const oauth_callback_endpoint: string = `${TOOLS_API}/oauth/callback`;
async function oauth_callback_function(params: { code: string; state?: string }): Promise<string> {
const query = new URLSearchParams();
query.set('code', params.code);
if (params.state) query.set('state', params.state);
const res = await fetch(`${oauth_callback_endpoint}?${query.toString()}`, {
method: 'GET',
});
const html = await res.text();
return html;
}
export const OAUTH_CALLBACK = createAsyncThunk(
oauth_callback_endpoint,
oauth_callback_function,
);
const oauth_start_endpoint: string = `${TOOLS_API}/oauth/start`;
async function oauth_start_function(toolId: string): Promise<{ auth_url: string }> {
const res = await fetch(`${TOOLS_API}/${toolId}/oauth/start`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { auth_url: string };
}
export const OAUTH_START = createAsyncThunk(
oauth_start_endpoint,
oauth_start_function,
);
const oauth_disconnect_endpoint: string = `${TOOLS_API}/oauth/disconnect`;
async function oauth_disconnect_function(toolId: string): Promise<{ ok: boolean; tool: Record<string, unknown> }> {
const res = await fetch(`${TOOLS_API}/${toolId}/oauth/disconnect`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
return data as { ok: boolean; tool: Record<string, unknown> };
}
export const OAUTH_DISCONNECT = createAsyncThunk(
oauth_disconnect_endpoint,
oauth_disconnect_function,
);