Update src/ai-repo-commander.user.js
This commit is contained in:
parent
9ddf1f891f
commit
dd0427b598
|
|
@ -83,6 +83,13 @@
|
||||||
QUEUE_MAX_PER_MINUTE: 15,
|
QUEUE_MAX_PER_MINUTE: 15,
|
||||||
QUEUE_MAX_PER_MESSAGE: 5,
|
QUEUE_MAX_PER_MESSAGE: 5,
|
||||||
QUEUE_WAIT_FOR_COMPOSER_MS: 6000,
|
QUEUE_WAIT_FOR_COMPOSER_MS: 6000,
|
||||||
|
|
||||||
|
RESPONSE_BUFFER_FLUSH_DELAY_MS: 500, // wait for siblings to finish
|
||||||
|
RESPONSE_BUFFER_SECTION_HEADINGS: true,
|
||||||
|
|
||||||
|
MAX_PASTE_CHARS: 250_000, // hard cap per message
|
||||||
|
SPLIT_LONG_RESPONSES: true, // enable multi-message split
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function loadSavedConfig() {
|
function loadSavedConfig() {
|
||||||
|
|
@ -1110,17 +1117,67 @@
|
||||||
|
|
||||||
// ---------------------- UI feedback ----------------------
|
// ---------------------- UI feedback ----------------------
|
||||||
class UIFeedback {
|
class UIFeedback {
|
||||||
static appendStatus(sourceElement, templateType, data) {
|
static ensureBoard(containerEl) {
|
||||||
const statusElement = this.createStatusElement(templateType, data);
|
let board = containerEl.querySelector('.ai-rc-status-board');
|
||||||
const existing = sourceElement.querySelector('.ai-repo-commander-status');
|
if (!board) {
|
||||||
if (existing) existing.remove();
|
board = document.createElement('div');
|
||||||
sourceElement.appendChild(statusElement);
|
board.className = 'ai-rc-status-board';
|
||||||
|
board.style.cssText = `
|
||||||
|
margin:10px 0;padding:8px;border:1px solid rgba(255,255,255,0.15);
|
||||||
|
border-radius:6px;background:rgba(255,255,255,0.06);font-family:monospace;
|
||||||
|
`;
|
||||||
|
containerEl.appendChild(board);
|
||||||
|
}
|
||||||
|
return board;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static appendStatus(containerEl, templateType, data) {
|
||||||
|
// Back-compat: when no key provided, fall through to single-line behavior
|
||||||
|
if (!data || !data.key) {
|
||||||
|
const statusElement = this.createStatusElement(templateType, data);
|
||||||
|
const existing = containerEl.querySelector('.ai-repo-commander-status');
|
||||||
|
if (existing) existing.remove();
|
||||||
|
statusElement.classList.add('ai-repo-commander-status');
|
||||||
|
containerEl.appendChild(statusElement);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Multi-line board (preferred)
|
||||||
|
const board = this.ensureBoard(containerEl);
|
||||||
|
const entry = this.upsertEntry(board, data.key);
|
||||||
|
entry.textContent = this.renderLine(templateType, data);
|
||||||
|
entry.dataset.state = templateType;
|
||||||
|
entry.style.borderLeft = `4px solid ${this.color(templateType)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static upsertEntry(board, key) {
|
||||||
|
let el = board.querySelector(`[data-entry-key="${key}"]`);
|
||||||
|
if (!el) {
|
||||||
|
el = document.createElement('div');
|
||||||
|
el.dataset.entryKey = key;
|
||||||
|
el.style.cssText = `
|
||||||
|
padding:6px 8px;margin:4px 0;border-left:4px solid transparent;
|
||||||
|
background:rgba(0,0,0,0.15);border-radius:4px;
|
||||||
|
white-space:pre-wrap;word-break:break-word;
|
||||||
|
`;
|
||||||
|
board.appendChild(el);
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
static renderLine(templateType, data) {
|
||||||
|
const { action, details, label } = data || {};
|
||||||
|
const state = ({
|
||||||
|
SUCCESS:'Success', ERROR:'Error', VALIDATION_ERROR:'Invalid',
|
||||||
|
EXECUTING:'Processing...', MOCK:'Mock'
|
||||||
|
})[templateType] || templateType;
|
||||||
|
const left = label || action || 'Command';
|
||||||
|
return `${left} — ${state}${details ? `: ${details}` : ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
static createStatusElement(templateType, data) {
|
static createStatusElement(templateType, data) {
|
||||||
const template = STATUS_TEMPLATES[templateType] || STATUS_TEMPLATES.ERROR;
|
const template = STATUS_TEMPLATES[templateType] || STATUS_TEMPLATES.ERROR;
|
||||||
const message = template.replace('{action}', data.action).replace('{details}', data.details);
|
const message = template.replace('{action}', data.action).replace('{details}', data.details);
|
||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
el.className = 'ai-repo-commander-status';
|
|
||||||
el.textContent = message;
|
el.textContent = message;
|
||||||
el.style.cssText = `
|
el.style.cssText = `
|
||||||
padding: 8px 12px; margin: 10px 0; border-radius: 4px;
|
padding: 8px 12px; margin: 10px 0; border-radius: 4px;
|
||||||
|
|
@ -1130,6 +1187,7 @@
|
||||||
`;
|
`;
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
static color(t) {
|
static color(t) {
|
||||||
const c = { SUCCESS:'#10B981', ERROR:'#EF4444', VALIDATION_ERROR:'#F59E0B', EXECUTING:'#3B82F6', MOCK:'#8B5CF6' };
|
const c = { SUCCESS:'#10B981', ERROR:'#EF4444', VALIDATION_ERROR:'#F59E0B', EXECUTING:'#3B82F6', MOCK:'#8B5CF6' };
|
||||||
return c[t] || '#6B7280';
|
return c[t] || '#6B7280';
|
||||||
|
|
@ -1303,7 +1361,14 @@
|
||||||
try {
|
try {
|
||||||
if (typeof GM_setClipboard === 'function') {
|
if (typeof GM_setClipboard === 'function') {
|
||||||
GM_setClipboard(payload, { type: 'text', mimetype: 'text/plain' });
|
GM_setClipboard(payload, { type: 'text', mimetype: 'text/plain' });
|
||||||
GM_notification({ title: 'AI Repo Commander', text: 'Content copied to clipboard — press Ctrl/Cmd+V to paste.', timeout: 5000 });
|
RC_DEBUG?.warn('📋 Clipboard fallback used — manual paste may be required', {
|
||||||
|
length: payload.length
|
||||||
|
});
|
||||||
|
GM_notification({
|
||||||
|
title: 'AI Repo Commander',
|
||||||
|
text: 'Content copied to clipboard — press Ctrl/Cmd+V to paste.',
|
||||||
|
timeout: 5000
|
||||||
|
});
|
||||||
RC_DEBUG?.info('✅ Paste method succeeded: GM_setClipboard (manual paste required)');
|
RC_DEBUG?.info('✅ Paste method succeeded: GM_setClipboard (manual paste required)');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -1457,24 +1522,35 @@
|
||||||
|
|
||||||
// ---------------------- Execution ----------------------
|
// ---------------------- Execution ----------------------
|
||||||
class ExecutionManager {
|
class ExecutionManager {
|
||||||
static async executeCommand(command, sourceElement) {
|
static async executeCommand(command, sourceElement, renderKey = '', label = '') {
|
||||||
try {
|
try {
|
||||||
if ((command.action === 'update_file' || command.action === 'create_file') && !command.commit_message) {
|
if ((command.action === 'update_file' || command.action === 'create_file') && !command.commit_message) {
|
||||||
command.commit_message = `AI Repo Commander: ${command.path} (${new Date().toISOString()})`;
|
command.commit_message = `AI Repo Commander: ${command.path} (${new Date().toISOString()})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CONFIG.ENABLE_API) return this.mockExecution(command, sourceElement);
|
if (!CONFIG.ENABLE_API) {
|
||||||
|
UIFeedback.appendStatus(sourceElement, 'EXECUTING', { action: command.action, details: 'Mocking...', key: renderKey, label });
|
||||||
|
const res = await this.mockExecution(command, sourceElement, renderKey, label);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
UIFeedback.appendStatus(sourceElement, 'EXECUTING', { action: command.action, details: 'Making API request...' });
|
UIFeedback.appendStatus(sourceElement, 'EXECUTING', { action: command.action, details: 'Making API request...', key: renderKey, label });
|
||||||
|
|
||||||
const res = await this.makeAPICallWithRetry(command);
|
const res = await this.makeAPICallWithRetry(command);
|
||||||
return this.handleSuccess(res, command, sourceElement);
|
return this.handleSuccess(res, command, sourceElement, false, renderKey, label);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return this.handleError(error, command, sourceElement);
|
return this.handleError(error, command, sourceElement, renderKey, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async mockExecution(command, sourceElement, renderKey = '', label = '') {
|
||||||
|
await this.delay(500);
|
||||||
|
const mock = { status: 200, responseText: JSON.stringify({ success: true, message: `Mock execution completed for ${command.action}` }) };
|
||||||
|
return this.handleSuccess(mock, command, sourceElement, true, renderKey, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static async makeAPICallWithRetry(command, attempt = 0) {
|
static async makeAPICallWithRetry(command, attempt = 0) {
|
||||||
try {
|
try {
|
||||||
requireBridgeKeyIfNeeded();
|
requireBridgeKeyIfNeeded();
|
||||||
|
|
@ -1519,18 +1595,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async mockExecution(command, sourceElement) {
|
|
||||||
await this.delay(500);
|
|
||||||
const mock = {
|
|
||||||
status: 200,
|
|
||||||
responseText: JSON.stringify({
|
|
||||||
success: true,
|
|
||||||
message: `Mock execution completed for ${command.action}`,
|
|
||||||
data: { command: command.action, repo: command.repo, path: command.path, commit_message: command.commit_message }
|
|
||||||
})
|
|
||||||
};
|
|
||||||
return this.handleSuccess(mock, command, sourceElement, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _extractGetFileBody(payload) {
|
static _extractGetFileBody(payload) {
|
||||||
const item = Array.isArray(payload) ? payload[0] : payload;
|
const item = Array.isArray(payload) ? payload[0] : payload;
|
||||||
|
|
@ -1571,20 +1635,21 @@
|
||||||
return '```text\n' + lines.join('\n') + '\n```';
|
return '```text\n' + lines.join('\n') + '\n```';
|
||||||
}
|
}
|
||||||
|
|
||||||
static async handleSuccess(response, command, sourceElement, isMock = false) {
|
static async handleSuccess(response, command, sourceElement, isMock = false, renderKey = '', label = '') {
|
||||||
let data;
|
let data; try { data = JSON.parse(response.responseText || '{}'); }
|
||||||
try { data = JSON.parse(response.responseText || '{}'); }
|
|
||||||
catch { data = { message: 'Operation completed (no JSON body)' }; }
|
catch { data = { message: 'Operation completed (no JSON body)' }; }
|
||||||
|
|
||||||
UIFeedback.appendStatus(sourceElement, isMock ? 'MOCK' : 'SUCCESS', {
|
UIFeedback.appendStatus(sourceElement, isMock ? 'MOCK' : 'SUCCESS', {
|
||||||
action: command.action,
|
action: command.action,
|
||||||
details: data.message || 'Operation completed successfully'
|
details: data.message || 'Operation completed successfully',
|
||||||
|
key: renderKey,
|
||||||
|
label
|
||||||
});
|
});
|
||||||
|
|
||||||
if (command.action === 'get_file') {
|
if (command.action === 'get_file') {
|
||||||
const body = this._extractGetFileBody(data);
|
const body = this._extractGetFileBody(data);
|
||||||
if (typeof body === 'string' && body.length) {
|
if (typeof body === 'string' && body.length) {
|
||||||
await pasteAndMaybeSubmit(body);
|
RESP_BUFFER.push({ label, content: body });
|
||||||
} else {
|
} else {
|
||||||
GM_notification({ title: 'AI Repo Commander', text: 'get_file succeeded, but no content to paste.', timeout: 4000 });
|
GM_notification({ title: 'AI Repo Commander', text: 'get_file succeeded, but no content to paste.', timeout: 4000 });
|
||||||
}
|
}
|
||||||
|
|
@ -1594,21 +1659,27 @@
|
||||||
const files = this._extractFilesArray(data);
|
const files = this._extractFilesArray(data);
|
||||||
if (files && files.length) {
|
if (files && files.length) {
|
||||||
const listing = this._formatFilesListing(files);
|
const listing = this._formatFilesListing(files);
|
||||||
await pasteAndMaybeSubmit(listing);
|
RESP_BUFFER.push({ label, content: listing });
|
||||||
} else {
|
} else {
|
||||||
const fallback = '```json\n' + JSON.stringify(data, null, 2) + '\n```';
|
const fallback = '```json\n' + JSON.stringify(data, null, 2) + '\n```';
|
||||||
await pasteAndMaybeSubmit(fallback);
|
RESP_BUFFER.push({ label, content: fallback });
|
||||||
GM_notification({ title: 'AI Repo Commander', text: 'list_files succeeded, but response had no obvious files array. Pasted raw JSON.', timeout: 5000 });
|
GM_notification({
|
||||||
|
title: 'AI Repo Commander',
|
||||||
|
text: 'list_files succeeded, but response had no obvious files array. Pasted raw JSON.',
|
||||||
|
timeout: 5000
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { success: true, data, isMock };
|
return { success: true, data, isMock };
|
||||||
}
|
}
|
||||||
|
|
||||||
static handleError(error, command, sourceElement) {
|
static handleError(error, command, sourceElement, renderKey = '', label = '') {
|
||||||
UIFeedback.appendStatus(sourceElement, 'ERROR', {
|
UIFeedback.appendStatus(sourceElement, 'ERROR', {
|
||||||
action: command.action || 'Command',
|
action: command.action || 'Command',
|
||||||
details: error.message
|
details: error.message,
|
||||||
|
key: renderKey,
|
||||||
|
label
|
||||||
});
|
});
|
||||||
return { success: false, error: error.message };
|
return { success: false, error: error.message };
|
||||||
}
|
}
|
||||||
|
|
@ -1670,6 +1741,114 @@
|
||||||
cancelOne: (cb) => execQueue.cancelOne(cb),
|
cancelOne: (cb) => execQueue.cancelOne(cb),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function chunkByLines(s, limit) {
|
||||||
|
const out = [];
|
||||||
|
let start = 0;
|
||||||
|
while (start < s.length) {
|
||||||
|
const endSoft = s.lastIndexOf('\n', Math.min(start + limit, s.length));
|
||||||
|
const end = endSoft > start ? endSoft + 1 : Math.min(start + limit, s.length);
|
||||||
|
out.push(s.slice(start, end));
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSingleFencedBlock(s) {
|
||||||
|
return /^```[^\n]*\n[\s\S]*\n```$/.test(s.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitRespectingCodeFence(text, limit) {
|
||||||
|
const trimmed = text.trim();
|
||||||
|
if (!isSingleFencedBlock(trimmed)) {
|
||||||
|
// Not a single fence → just line-friendly chunking
|
||||||
|
return chunkByLines(text, limit);
|
||||||
|
}
|
||||||
|
// Extract inner payload & language hint
|
||||||
|
const m = /^```([^\n]*)\n([\s\S]*)\n```$/.exec(trimmed);
|
||||||
|
const lang = (m?.[1] || 'text').trim();
|
||||||
|
const inner = m?.[2] ?? '';
|
||||||
|
const chunks = chunkByLines(inner, limit - 16 - lang.length); // budget for fences
|
||||||
|
return chunks.map(c => '```' + lang + '\n' + c.replace(/\n?$/, '\n') + '```');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------- ResponseBuffer ----------------------
|
||||||
|
class ResponseBuffer {
|
||||||
|
constructor() {
|
||||||
|
this.pending = []; // { label, content }
|
||||||
|
this.timer = null;
|
||||||
|
this.flushing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
push(item) {
|
||||||
|
if (!item || !item.content) return;
|
||||||
|
this.pending.push(item);
|
||||||
|
this.scheduleFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduleFlush() {
|
||||||
|
if (this.timer) clearTimeout(this.timer);
|
||||||
|
this.timer = setTimeout(() => this.flush(), CONFIG.RESPONSE_BUFFER_FLUSH_DELAY_MS || 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildCombined() {
|
||||||
|
const parts = [];
|
||||||
|
for (const { label, content } of this.pending) {
|
||||||
|
if (CONFIG.RESPONSE_BUFFER_SECTION_HEADINGS && label) {
|
||||||
|
parts.push(`### ${label}\n`);
|
||||||
|
}
|
||||||
|
parts.push(String(content).trimEnd());
|
||||||
|
parts.push(''); // blank line between sections
|
||||||
|
}
|
||||||
|
return parts.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
async flush() {
|
||||||
|
if (this.flushing) return;
|
||||||
|
if (!this.pending.length) return;
|
||||||
|
this.flushing = true;
|
||||||
|
|
||||||
|
const toPaste = this.buildCombined();
|
||||||
|
this.pending.length = 0; // clear
|
||||||
|
|
||||||
|
try {
|
||||||
|
const limit = CONFIG.MAX_PASTE_CHARS || 250_000;
|
||||||
|
|
||||||
|
if (CONFIG.SPLIT_LONG_RESPONSES && toPaste.length > limit) {
|
||||||
|
const chunks = splitRespectingCodeFence(toPaste, limit);
|
||||||
|
|
||||||
|
RC_DEBUG?.warn(`Splitting long response into ${chunks.length} message(s)`, {
|
||||||
|
totalChars: toPaste.length, perChunkLimit: limit
|
||||||
|
});
|
||||||
|
|
||||||
|
chunks.forEach((chunk, i) => {
|
||||||
|
const header = CONFIG.RESPONSE_BUFFER_SECTION_HEADINGS
|
||||||
|
? `### Part ${i+1}/${chunks.length}\n`
|
||||||
|
: '';
|
||||||
|
const payload = header + chunk;
|
||||||
|
|
||||||
|
execQueue.push(async () => {
|
||||||
|
await pasteAndMaybeSubmit(payload);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return; // done: queued as multiple messages
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal single-message path
|
||||||
|
execQueue.push(async () => {
|
||||||
|
await pasteAndMaybeSubmit(toPaste);
|
||||||
|
});
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
this.flushing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const RESP_BUFFER = new ResponseBuffer();
|
||||||
|
window.AI_REPO_RESPONSES = RESP_BUFFER; // optional debug handle
|
||||||
|
|
||||||
// ---------------------- Bridge Key ----------------------
|
// ---------------------- Bridge Key ----------------------
|
||||||
let BRIDGE_KEY = null;
|
let BRIDGE_KEY = null;
|
||||||
|
|
||||||
|
|
@ -1979,37 +2158,32 @@
|
||||||
const messageId = this.getReadableMessageId(element);
|
const messageId = this.getReadableMessageId(element);
|
||||||
const subId = `${messageId}#${idx + 1}`;
|
const subId = `${messageId}#${idx + 1}`;
|
||||||
|
|
||||||
// track this sub-command so updateState/attachRetryUI can work
|
|
||||||
this.trackedMessages.set(subId, {
|
|
||||||
element,
|
|
||||||
originalText: hit.text,
|
|
||||||
state: COMMAND_STATES.DETECTED,
|
|
||||||
startTime: Date.now(),
|
|
||||||
lastUpdate: Date.now(),
|
|
||||||
cancelToken: { cancelled: false },
|
|
||||||
});
|
|
||||||
|
|
||||||
execQueue.push(async () => {
|
execQueue.push(async () => {
|
||||||
// optional tiny settle for streaming
|
const finalTxt = hit.text; // <<< ADD THIS
|
||||||
await ExecutionManager.delay(CONFIG.SETTLE_POLL_MS);
|
|
||||||
|
|
||||||
const allNow = findAllCommandsInMessage(element);
|
|
||||||
const liveForIdx = allNow[idx]?.text;
|
|
||||||
const finalTxt = (liveForIdx && this.isCompleteCommandText(liveForIdx)) ? liveForIdx : hit.text;
|
|
||||||
|
|
||||||
let parsed;
|
let parsed;
|
||||||
try {
|
try {
|
||||||
parsed = CommandParser.parseYAMLCommand(finalTxt);
|
parsed = CommandParser.parseYAMLCommand(finalTxt);
|
||||||
const val = CommandParser.validateStructure(parsed);
|
const val = CommandParser.validateStructure(parsed);
|
||||||
if (!val.isValid) throw new Error(`Validation failed: ${val.errors.join(', ')}`);
|
if (!val.isValid) throw new Error(`Validation failed: ${val.errors.join(', ')}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
UIFeedback.appendStatus(element, 'ERROR', { action: 'Command', details: err.message });
|
UIFeedback.appendStatus(element, 'ERROR', {
|
||||||
|
action: 'Command',
|
||||||
|
details: err.message,
|
||||||
|
key: subId, // <<< key per sub-command
|
||||||
|
label: `[${idx+1}] parse`
|
||||||
|
});
|
||||||
this.attachRetryUI(element, subId);
|
this.attachRetryUI(element, subId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateState(subId, COMMAND_STATES.EXECUTING);
|
this.updateState(subId, COMMAND_STATES.EXECUTING);
|
||||||
const res = await ExecutionManager.executeCommand(parsed, element);
|
const res = await ExecutionManager.executeCommand(
|
||||||
|
parsed,
|
||||||
|
element,
|
||||||
|
/* renderKey: */ subId, // <<< pass key down
|
||||||
|
/* label: */ `[${idx+1}] ${this.extractAction(finalTxt)}`
|
||||||
|
);
|
||||||
|
|
||||||
if (!res || res.success === false) {
|
if (!res || res.success === false) {
|
||||||
this.updateState(subId, COMMAND_STATES.ERROR);
|
this.updateState(subId, COMMAND_STATES.ERROR);
|
||||||
this.attachRetryUI(element, subId);
|
this.attachRetryUI(element, subId);
|
||||||
|
|
@ -2018,6 +2192,7 @@
|
||||||
this.updateState(subId, COMMAND_STATES.COMPLETE);
|
this.updateState(subId, COMMAND_STATES.COMPLETE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
isAssistantMessage(el) {
|
isAssistantMessage(el) {
|
||||||
if (!CONFIG.ASSISTANT_ONLY) return true;
|
if (!CONFIG.ASSISTANT_ONLY) return true;
|
||||||
const host = location.hostname;
|
const host = location.hostname;
|
||||||
|
|
@ -2214,7 +2389,11 @@
|
||||||
|
|
||||||
// 4) Execute
|
// 4) Execute
|
||||||
this.updateState(messageId, COMMAND_STATES.EXECUTING);
|
this.updateState(messageId, COMMAND_STATES.EXECUTING);
|
||||||
const result = await ExecutionManager.executeCommand(parsed, message.element);
|
|
||||||
|
const action = parsed?.action || 'unknown';
|
||||||
|
const renderKey = `${messageId}#1`;
|
||||||
|
const label = `[1] ${action}`;
|
||||||
|
const result = await ExecutionManager.executeCommand(parsed, message.element, renderKey, label);
|
||||||
|
|
||||||
if (!result || result.success === false) {
|
if (!result || result.success === false) {
|
||||||
RC_DEBUG?.warn('Execution reported failure', { messageId });
|
RC_DEBUG?.warn('Execution reported failure', { messageId });
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue