157 lines
3.4 KiB
JavaScript
157 lines
3.4 KiB
JavaScript
import * as backend from './backend';
|
|
|
|
// State
|
|
let runs = [];
|
|
let unsubscribeRunEvents = null;
|
|
|
|
// Event listeners for UI components
|
|
const listeners = {
|
|
created: [],
|
|
runs: [],
|
|
chats: {},
|
|
};
|
|
|
|
class RunListener {
|
|
constructor() {
|
|
this.runIds = new Set();
|
|
this.callbacks = [];
|
|
this.cancelled = false;
|
|
|
|
this.allRuns = false;
|
|
}
|
|
|
|
setIdList(runIds) {
|
|
this.runIds = new Set(runIds);
|
|
}
|
|
|
|
addRunId(runId) {
|
|
this.runIds.add(runId);
|
|
}
|
|
|
|
addCallback(callback) {
|
|
this.callbacks.push(callback);
|
|
}
|
|
|
|
cancel() {
|
|
this.cancelled = true;
|
|
listeners.runs = listeners.runs.filter(l => l !== this);
|
|
}
|
|
|
|
hasRunId(runId) {
|
|
return this.allRuns || this.runIds.has(runId);
|
|
}
|
|
|
|
emitChange(data) {
|
|
if (this.cancelled) return;
|
|
for (let cb of this.callbacks) cb(data);
|
|
}
|
|
}
|
|
|
|
// Update a run based on an incoming event
|
|
function updateRun(event) {
|
|
const { name, runId, data } = event.data;
|
|
|
|
// Find the run by ID
|
|
const runIndex = runs.findIndex(r => r.id === runId);
|
|
let run = runIndex >= 0 ? runs[runIndex] : null;
|
|
|
|
if (name == 'created') {
|
|
if (!run) {
|
|
run = Object.assign({}, data, {id: runId, events: []});
|
|
runs.push(run);
|
|
for (let cb of listeners.created) {
|
|
cb(run);
|
|
}
|
|
} else {
|
|
console.warn("Created but existing?", run, data);
|
|
}
|
|
} else if (name == 'done') {
|
|
run.done = true;
|
|
} else if (name == 'chat-message') {
|
|
let chatListeners = listeners.chats[data.chatId] || [];
|
|
for (let f of chatListeners) {
|
|
f({runId: runId, ...data});
|
|
}
|
|
}
|
|
|
|
if (run) {
|
|
run.events.push({name, runId, data});
|
|
for (let listener of listeners.runs) {
|
|
if (listener.hasRunId(runId)) {
|
|
listener.emitChange(run);
|
|
}
|
|
}
|
|
} else {
|
|
console.error('Bad run event (non-existing run)', event);
|
|
}
|
|
}
|
|
|
|
// Initialize the runs module
|
|
async function init() {
|
|
// Listen for connection establishment
|
|
const res = await backend.sendAction("get-agent-runs");
|
|
runs = res.runs || [];
|
|
|
|
// Listen for run events
|
|
if (unsubscribeRunEvents) unsubscribeRunEvents();
|
|
unsubscribeRunEvents = backend.onAction('run-event', updateRun);
|
|
}
|
|
|
|
backend.onConnect(init);
|
|
|
|
// Get all runs
|
|
export function getRuns() {
|
|
return runs;
|
|
}
|
|
|
|
// Get a specific run by ID
|
|
export function getRun(runId) {
|
|
return runs.find(r => r.id === runId);
|
|
}
|
|
|
|
|
|
// Cancel a run
|
|
export async function cancelRun(runId) {
|
|
try {
|
|
const res = await backend.sendAction("cancel-agent-run", { runId });
|
|
console.log(`Cancelled run ${runId}`, res);
|
|
return res;
|
|
} catch (err) {
|
|
console.error(`Failed to cancel run ${runId}:`, err);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
// Subscribe to runs changes
|
|
export function onCreated(callback) {
|
|
listeners.created.push(callback);
|
|
return () => {
|
|
const index = listeners.created.indexOf(callback);
|
|
if (index > -1) {
|
|
listeners.created.splice(index, 1);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function addRunListener(callback) {
|
|
const listener = new RunListener();
|
|
listener.addCallback(callback);
|
|
listeners.runs.push(listener);
|
|
return listener;
|
|
}
|
|
|
|
// Subscribe to run chat message events
|
|
export function onChatMessage(chatId, callback) {
|
|
let chatListeners = listeners.chats[chatId];
|
|
if (!chatListeners) {
|
|
chatListeners = [];
|
|
listeners.chats[chatId] = chatListeners;
|
|
}
|
|
chatListeners.push(callback);
|
|
return () => {
|
|
const index = chatListeners.indexOf(callback);
|
|
if (index > -1) {
|
|
chatListeners.splice(index, 1);
|
|
}
|
|
};
|
|
} |