chore(frontend): reduce redundancies
This commit is contained in:
1 parent
dac5d201cd
commit
75dac1e459
8 files changed
+65
-97
No files matched your search
@@ -157,6 +157,14 @@ export function sendAction(action, body = {}, callback = null) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
export async function act (action, body, { alert = null, cache = null } = {}) {
|
||||
const res = await sendAction(action, body);
|
||||
if (res.error) { ui.alert(`Error: ${res.error}`); return null; }
|
||||
if (cache) invalidateCache(cache);
|
||||
if (alert) ui.alert(alert);
|
||||
return res;
|
||||
}
|
||||
|
||||
export function ping() {
|
||||
if (socket && socket.readyState === WebSocket.OPEN) {
|
||||
const data = JSON.stringify({ path: 'ping' });
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Global utility functions related with UI functionality
|
||||
|
||||
import { ref } from 'vue';
|
||||
import router from './router'
|
||||
|
||||
export function goto (path) {
|
||||
@@ -33,6 +34,15 @@ export function contextMenu (entries) {
|
||||
});
|
||||
}
|
||||
|
||||
// Helper object to manage track toggable ui elements
|
||||
export function useToggleSet () {
|
||||
const state = ref({});
|
||||
return {
|
||||
has(key) { return Boolean(state.value[key]); },
|
||||
toggle(key) { state.value[key] = !state.value[key]; },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// === Events === //
|
||||
|
||||
|
||||
@@ -148,45 +148,35 @@
|
||||
|
||||
// === Configuration === //
|
||||
|
||||
function updateIdentifier() {
|
||||
async function updateIdentifier() {
|
||||
const value = prompt(`Enter a new identifier for ${agent.value.name}`);
|
||||
if (value) {
|
||||
backend.sendAction("update-agent", {
|
||||
let res = await backend.act("update-agent", {
|
||||
// agentId is necessary here
|
||||
agentId: agent.value.id,
|
||||
// used as value instead of identifier
|
||||
agentname: value,
|
||||
}).then(res => {
|
||||
ui.alert(res.error ?
|
||||
'Error updating agent identifier' :
|
||||
'Agent identifier updated'
|
||||
);
|
||||
if (!res.error) {
|
||||
agent.value.agentname = value;
|
||||
backend.invalidateCache({agents: true});
|
||||
}
|
||||
}, {
|
||||
cache: {agents: true},
|
||||
alert: 'Agent identifier updated'
|
||||
});
|
||||
if (!res.error) agent.value.agentname = value;
|
||||
} else {
|
||||
ui.alert("Cancelled identifier update");
|
||||
}
|
||||
}
|
||||
|
||||
function updateName() {
|
||||
async function updateName() {
|
||||
const value = prompt(`Enter a new name for ${agent.value.name}`);
|
||||
if (value) {
|
||||
backend.sendAction("update-agent", {
|
||||
let res = await backend.sendAction("update-agent", {
|
||||
agentname: agent.value.agentname,
|
||||
name: value,
|
||||
}).then(res => {
|
||||
ui.alert(res.error ?
|
||||
'Error updating agent name' :
|
||||
'Agent name updated'
|
||||
);
|
||||
if (!res.error) {
|
||||
agent.value.name = value;
|
||||
backend.invalidateCache({agents: true});
|
||||
}
|
||||
}, {
|
||||
alert: 'Agent name updated',
|
||||
cache: {agents: true},
|
||||
});
|
||||
if (!res.error) agent.value.name = value;
|
||||
} else {
|
||||
ui.alert("Cancelled name update");
|
||||
}
|
||||
@@ -215,19 +205,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
let res = await backend.sendAction("update-agent", {
|
||||
await backend.act("update-agent", {
|
||||
agentname: agent.value.agentname,
|
||||
data: dataObject,
|
||||
}, {
|
||||
alert: 'Agent updated',
|
||||
cache: {agents: true},
|
||||
});
|
||||
|
||||
ui.alert(res.error ?
|
||||
'Error updating agent' :
|
||||
'Agent updated'
|
||||
);
|
||||
|
||||
if (!res.error) {
|
||||
backend.invalidateCache({agents: true});
|
||||
}
|
||||
}
|
||||
|
||||
async function saveAddingTool() {
|
||||
@@ -292,8 +276,8 @@
|
||||
<span class="label">Enable Instruction/Input</span>
|
||||
<input type="checkbox" v-model="promptInstructionEnabled" />
|
||||
</div>
|
||||
<textarea v-if="promptInstructionEnabled" v-model="promptInstruction" class="config-input" @keydown="promptKeyDown($event, 1)" />
|
||||
<textarea v-model="promptInput" class="config-input" ref="promptInputElem" @keydown="promptKeyDown($event, 2)" />
|
||||
<textarea v-if="promptInstructionEnabled" v-model="promptInstruction" class="config-input" @keydown.ctrl.enter.prevent="promptInputElem.focus" />
|
||||
<textarea v-model="promptInput" class="config-input" ref="promptInputElem" @keydown.ctrl.enter.prevent="sendPrompt" />
|
||||
<div>
|
||||
<button @click="sendPrompt()">Send Prompt</button>
|
||||
</div>
|
||||
|
||||
@@ -39,14 +39,13 @@
|
||||
payload.temporary = true;
|
||||
}
|
||||
|
||||
let response = await backend.sendAction("create-agent", payload);
|
||||
let response = await backend.act("create-agent", payload, {
|
||||
alert: `Created Agent "${payload.name}"`,
|
||||
cache: {agents: true},
|
||||
});
|
||||
|
||||
if (response.error) {
|
||||
ui.alert(`Could not create agent\n${response.error}`);
|
||||
} else {
|
||||
ui.alert(`Created Agent "${payload.name}"`);
|
||||
if (!response.error) {
|
||||
backend.invalidateCache({agents: true});
|
||||
ui.goto(`/agent/${payload.agentname}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
} = session;
|
||||
|
||||
// UI state coupled to the document itself
|
||||
const expandedLogs = ref({}); // Message ids of logs currently expanded
|
||||
|
||||
// Message ids of logs currently expanded
|
||||
const expandedLogs = ui.useToggleSet();
|
||||
const inputFieldElem = ref(null);
|
||||
const chatContainerElem = ref(null);
|
||||
|
||||
@@ -109,10 +111,6 @@
|
||||
|
||||
// === UI Helper Functions === //
|
||||
|
||||
function toggleLogExpand (message) {
|
||||
expandedLogs.value[message.id] = !expandedLogs.value[message.id];
|
||||
}
|
||||
|
||||
async function chatEntryContextMenu (message, logMeta) {
|
||||
let entries = [
|
||||
{value: 'pin', title: "Pin message"},
|
||||
@@ -143,7 +141,7 @@
|
||||
break;
|
||||
}
|
||||
case 'toggle-log': {
|
||||
toggleLogExpand(message);
|
||||
expandedLogs.toggle(message.id);
|
||||
break;
|
||||
}
|
||||
case 'delete': {
|
||||
@@ -178,13 +176,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
function inputKeyDown (event) {
|
||||
if (event.key == "Enter" && event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
sendMessage();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -203,10 +194,10 @@
|
||||
:key="msg.id ?? ('thread-' + msg.threadId)"
|
||||
:message="msg"
|
||||
@open-menu="chatEntryContextMenu"
|
||||
@open-thread="session.activateThread"
|
||||
@open-thread="session.activateThread($event)"
|
||||
|
||||
:log-expanded="expandedLogs[msg.id]"
|
||||
@toggle-log="toggleLogExpand(msg)"
|
||||
:log-expanded="expandedLogs.has(msg.id)"
|
||||
@toggle-log="expandedLogs.toggle(msg.id)"
|
||||
|
||||
:cancellable="messageRunMap[msg.id]"
|
||||
@cancel="session.cancelMessageRun(msg.id)"
|
||||
@@ -218,7 +209,7 @@
|
||||
{{editInfo}}
|
||||
</div>
|
||||
|
||||
<div class="input-field" ref="inputFieldElem" @keydown="inputKeyDown($event)" contenteditable></div>
|
||||
<div class="input-field" ref="inputFieldElem" @keydown.ctrl.enter.prevent="sendMessage" contenteditable></div>
|
||||
|
||||
<div class="input-row">
|
||||
<button @click="session.startNewThread()">
|
||||
|
||||
@@ -25,13 +25,14 @@
|
||||
payload.temporary = true;
|
||||
}
|
||||
|
||||
let response = await backend.sendAction("create-chat", payload);
|
||||
let response = await backend.act("create-chat", payload, {
|
||||
alert: `Created Chat "${title.value}"`,
|
||||
cache: {chats: true},
|
||||
});
|
||||
|
||||
if (response.error) {
|
||||
ui.alert(`Could not create chat\n${response.error}`);
|
||||
} else {
|
||||
ui.alert(`Created Chat "${title.value}"`);
|
||||
backend.invalidateCache({chats: true});
|
||||
ui.goto(`/chat/${response.chatId}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import * as ui from '../ui';
|
||||
|
||||
const models = ref([]);
|
||||
const expandedModelId = ref(new Set());
|
||||
const expandedModelId = ui.useToggleSet();
|
||||
const createExpanded = ref(false);
|
||||
const newKeyValue = ref(false);
|
||||
|
||||
@@ -22,14 +22,6 @@
|
||||
models.value = res.models.map(entry => ({editing: {}, ...entry}));
|
||||
});
|
||||
|
||||
const toggleModel = (id) => {
|
||||
if (expandedModelId.value.has(id)) {
|
||||
expandedModelId.value.delete(id);
|
||||
} else {
|
||||
expandedModelId.value.add(id);
|
||||
}
|
||||
};
|
||||
|
||||
async function createModel () {
|
||||
let current = Object.assign({editing: {}}, editModel.value);
|
||||
|
||||
@@ -114,7 +106,7 @@
|
||||
</div>
|
||||
|
||||
<div v-else v-for="model in models" :key="model.id" class="model-entry">
|
||||
<div class="model-header" @click="toggleModel(model.id)">
|
||||
<div class="model-header" @click="expandedModelId.toggle(model.id)">
|
||||
<span class="model-name">{{ model.name }}</span>
|
||||
<span class="model-kind">{{ model.kind }}</span>
|
||||
<div class="model-actions">
|
||||
|
||||
@@ -108,10 +108,10 @@ import * as ui from '../ui';
|
||||
const upstreamRemotes = ref([]);
|
||||
|
||||
/** Expanded remote rows, keyed by row key; several can be open at once */
|
||||
const expandedRemotes = ref(new Set());
|
||||
const expandedRemotes = ui.useToggleSet();
|
||||
|
||||
/** Expanded function rows, keyed by `<rowKey>|<fnKey>` */
|
||||
const expandedFns = ref(new Set());
|
||||
const expandedFns = ui.useToggleSet();
|
||||
|
||||
/** Per-function call state, keyed like expandedFns */
|
||||
const callStates = reactive({});
|
||||
@@ -222,27 +222,10 @@ function functionsOf(row) {
|
||||
}));
|
||||
}
|
||||
|
||||
// ---- Expansion ----
|
||||
|
||||
function toggleRemote(key) {
|
||||
const set = new Set(expandedRemotes.value);
|
||||
if (set.has(key)) set.delete(key); else set.add(key);
|
||||
expandedRemotes.value = set;
|
||||
}
|
||||
|
||||
// Function key, used in expandedFns
|
||||
function fnKey(row, fn) {
|
||||
return fn.id != null ? `l${fn.id}` : `u${fn.name}`;
|
||||
}
|
||||
|
||||
function fnStateKey(row, fn) {
|
||||
return `${row.key}|${fnKey(row, fn)}`;
|
||||
}
|
||||
|
||||
function toggleFn(row, fn) {
|
||||
const key = fnStateKey(row, fn);
|
||||
const set = new Set(expandedFns.value);
|
||||
if (set.has(key)) set.delete(key); else set.add(key);
|
||||
expandedFns.value = set;
|
||||
let fkey = fn.id != null ? `l${fn.id}` : `u${fn.name}`;
|
||||
return `${row.key}|${fkey}`;
|
||||
}
|
||||
|
||||
// ---- Calling ----
|
||||
@@ -276,7 +259,7 @@ function defaultArgs(fn) {
|
||||
}
|
||||
|
||||
function callStateFor(row, fn) {
|
||||
const key = fnStateKey(row, fn);
|
||||
const key = fnKey(row, fn);
|
||||
if (!callStates[key]) {
|
||||
callStates[key] = { args: defaultArgs(fn), result: null, error: '', busy: false };
|
||||
}
|
||||
@@ -413,7 +396,7 @@ function removeArgument(fn, argIdx) {
|
||||
<template v-for="row in remoteRows" :key="rowKey(row)">
|
||||
<!-- Remote row -->
|
||||
<div class="rt-row rt-remote" :class="{ open: expandedRemotes.has(row.key) }">
|
||||
<div class="col-arrow toggle" @click="toggleRemote(row.key)">
|
||||
<div class="col-arrow toggle" @click="expandedRemotes.toggle(row.key)">
|
||||
{{ expandedRemotes.has(row.key) ? '▼' : '▶' }}
|
||||
</div>
|
||||
<div class="col-name">
|
||||
@@ -464,8 +447,8 @@ function removeArgument(fn, argIdx) {
|
||||
<template v-for="fn in functionsOf(row)" :key="fnKey(row, fn)">
|
||||
<!-- Function row -->
|
||||
<div class="rt-row rt-fn">
|
||||
<div class="col-arrow toggle" @click="toggleFn(row, fn)">
|
||||
{{ expandedFns.has(fnStateKey(row, fn)) ? '▼' : '▶' }}
|
||||
<div class="col-arrow toggle" @click="expandedFns.toggle(fnKey(row, fn))">
|
||||
{{ expandedFns.has(fnKey(row, fn)) ? '▼' : '▶' }}
|
||||
</div>
|
||||
<div class="col-name">
|
||||
<input
|
||||
@@ -499,7 +482,7 @@ function removeArgument(fn, argIdx) {
|
||||
</div>
|
||||
|
||||
<!-- Expanded function detail: left = arguments, right = output/body -->
|
||||
<div v-if="expandedFns.has(fnStateKey(row, fn))" class="rt-row rt-fndetail">
|
||||
<div v-if="expandedFns.has(fnKey(row, fn))" class="rt-row rt-fndetail">
|
||||
<div class="col-arrow"></div>
|
||||
<div class="detail">
|
||||
<!-- Callable mode (connected remotes) -->
|
||||
|
||||
Reference in new issue
Block a user