mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-02 21:12:21 +02:00
fix(agent): authorize exact actions after untrusted context
This commit is contained in:
+2
-2
@@ -10,7 +10,7 @@ import modelsModule from './js/models.js?v=20260715startupcalm2';
|
||||
import ragModule from './js/rag.js';
|
||||
import presetsModule from './js/presets.js';
|
||||
import searchModule from './js/search.js';
|
||||
import chatModule from './js/chat.js?v=20260801fix1';
|
||||
import chatModule from './js/chat.js?v=20260815toolapproval1';
|
||||
import compareModule from './js/compare/index.js?v=20260723compareicon2';
|
||||
import documentModule from './js/document.js?v=20260722emailfastindex1';
|
||||
import searchChatModule from './js/search-chat.js';
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
settleSessionHydration
|
||||
} from './js/startupShell.js';
|
||||
import markdownModule from './js/markdown.js';
|
||||
import chatRenderer from './js/chatRenderer.js?v=20260722emailfastindex1';
|
||||
import chatRenderer from './js/chatRenderer.js?v=20260815toolapproval1';
|
||||
import sessionModule from './js/sessions.js';
|
||||
import memoryModule from './js/memory.js?v=20260722memoryloading1';
|
||||
import voiceRecorderModule from './js/voiceRecorder.js';
|
||||
|
||||
+3
-3
@@ -259,7 +259,7 @@
|
||||
<link rel="preload" as="font" type="font/woff2" crossorigin href="/static/fonts/FiraCode-SemiBold.woff2">
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260808startupshell1">
|
||||
<link rel="modulepreload" href="/static/app.js?v=20260808startupshell1">
|
||||
<link rel="modulepreload" href="/static/js/chat.js?v=20260801fix1">
|
||||
<link rel="modulepreload" href="/static/js/chat.js?v=20260815toolapproval1">
|
||||
<link rel="modulepreload" href="/static/js/ui.js">
|
||||
<link rel="modulepreload" href="/static/js/sessions.js">
|
||||
<link rel="modulepreload" href="/static/js/markdown.js">
|
||||
@@ -2534,10 +2534,10 @@
|
||||
<script type="module" src="/static/js/tts-ai.js"></script>
|
||||
<script type="module" src="/static/js/document.js?v=20260722emailfastindex1"></script>
|
||||
<script type="module" src="/static/js/gallery.js?v=20260708match1"></script>
|
||||
<script type="module" src="/static/js/chatRenderer.js?v=20260722emailfastindex1"></script>
|
||||
<script type="module" src="/static/js/chatRenderer.js?v=20260815toolapproval1"></script>
|
||||
<script type="module" src="/static/js/codeRunner.js"></script>
|
||||
<script type="module" src="/static/js/chatStream.js?v=20260722emailfastindex1"></script>
|
||||
<script type="module" src="/static/js/chat.js?v=20260801fix1"></script>
|
||||
<script type="module" src="/static/js/chat.js?v=20260815toolapproval1"></script>
|
||||
<script type="module" src="/static/js/cookbook.js"></script>
|
||||
<script src="/static/js/cookbookSchedule.js"></script>
|
||||
<script type="module" src="/static/js/search-chat.js"></script>
|
||||
|
||||
+23
-1
@@ -8,7 +8,7 @@
|
||||
import Storage from './storage.js';
|
||||
import uiModule from './ui.js';
|
||||
import sessionModule from './sessions.js';
|
||||
import chatRenderer from './chatRenderer.js?v=20260722emailfastindex1';
|
||||
import chatRenderer from './chatRenderer.js?v=20260815toolapproval1';
|
||||
import chatStream from './chatStream.js';
|
||||
import { addAITTSButton } from './tts-ai.js';
|
||||
import markdownModule from './markdown.js';
|
||||
@@ -59,6 +59,23 @@ import { createTerminalStreamError, isRecoverableStreamError } from './chatStrea
|
||||
let _contextHeaderSeq = 0;
|
||||
let _contextHeaderData = null;
|
||||
let _contextHeaderBound = false;
|
||||
let _pendingToolApproval = null;
|
||||
|
||||
document.addEventListener('odysseus:tool-approval', (event) => {
|
||||
const detail = event && event.detail ? event.detail : {};
|
||||
const decision = String(detail.decision || '').toLowerCase();
|
||||
if (!detail.approval_id || !['approve', 'deny'].includes(decision)) return;
|
||||
_pendingToolApproval = {
|
||||
approval_id: String(detail.approval_id),
|
||||
decision,
|
||||
};
|
||||
const input = document.getElementById('message');
|
||||
if (input) {
|
||||
input.value = detail.label || (decision === 'approve' ? 'Allow once' : 'Deny');
|
||||
}
|
||||
const sendButton = document.querySelector('.send-btn');
|
||||
if (sendButton) sendButton.click();
|
||||
});
|
||||
|
||||
function _fmtContextNumber(n) {
|
||||
const v = Number(n || 0);
|
||||
@@ -1756,6 +1773,11 @@ import { createTerminalStreamError, isRecoverableStreamError } from './chatStrea
|
||||
const fd = new FormData();
|
||||
fd.append('message', _finalMsgWithInject);
|
||||
fd.append('session', streamSessionId);
|
||||
if (_pendingToolApproval) {
|
||||
fd.append('tool_approval_id', _pendingToolApproval.approval_id);
|
||||
fd.append('tool_approval_decision', _pendingToolApproval.decision);
|
||||
_pendingToolApproval = null;
|
||||
}
|
||||
if (selectedRouteForSend.model) fd.append('selected_model', selectedRouteForSend.model);
|
||||
if (selectedRouteForSend.endpoint_url) fd.append('selected_endpoint_url', selectedRouteForSend.endpoint_url);
|
||||
if (selectedRouteForSend.endpoint_id) fd.append('selected_endpoint_id', selectedRouteForSend.endpoint_id);
|
||||
|
||||
@@ -2342,6 +2342,7 @@ export function renderAskUserCard(payload, options) {
|
||||
card.setAttribute('role', 'group');
|
||||
card.tabIndex = -1;
|
||||
const multi = !!aq.multi;
|
||||
const isToolApproval = aq.kind === 'tool_approval' && !!aq.approval_id;
|
||||
const emojiText = (value) => svgifyEmoji(uiModule.esc(String(value)));
|
||||
|
||||
const head = document.createElement('div');
|
||||
@@ -2366,6 +2367,27 @@ export function renderAskUserCard(payload, options) {
|
||||
card.appendChild(question);
|
||||
card.setAttribute('aria-labelledby', question.id);
|
||||
|
||||
if (isToolApproval && aq.action) {
|
||||
const action = document.createElement('div');
|
||||
action.className = 'ask-user-option-desc';
|
||||
const effects = Array.isArray(aq.action.effects)
|
||||
? aq.action.effects.join(', ')
|
||||
: '';
|
||||
action.textContent = [
|
||||
aq.action.tool || 'tool',
|
||||
aq.action.content || '',
|
||||
effects ? `Effects: ${effects}` : '',
|
||||
aq.action.workspace ? `Workspace: ${aq.action.workspace}` : '',
|
||||
aq.action.document_id ? `Document: ${aq.action.document_id}` : '',
|
||||
aq.action.document_version != null
|
||||
? `Document version: ${aq.action.document_version}`
|
||||
: '',
|
||||
aq.action.digest ? `Approval fingerprint: ${aq.action.digest}` : '',
|
||||
].filter(Boolean).join('\n');
|
||||
action.style.whiteSpace = 'pre-wrap';
|
||||
card.appendChild(action);
|
||||
}
|
||||
|
||||
const list = document.createElement('div');
|
||||
list.className = 'ask-user-options';
|
||||
card.appendChild(list);
|
||||
@@ -2403,7 +2425,20 @@ export function renderAskUserCard(payload, options) {
|
||||
}
|
||||
if (!multi) {
|
||||
row.type = 'button';
|
||||
row.addEventListener('click', () => send(label));
|
||||
row.addEventListener('click', () => {
|
||||
if (isToolApproval) {
|
||||
card.remove();
|
||||
document.dispatchEvent(new CustomEvent('odysseus:tool-approval', {
|
||||
detail: {
|
||||
approval_id: aq.approval_id,
|
||||
decision: String((opt && opt.value) || '').toLowerCase(),
|
||||
label,
|
||||
},
|
||||
}));
|
||||
} else {
|
||||
send(label);
|
||||
}
|
||||
});
|
||||
}
|
||||
list.appendChild(row);
|
||||
});
|
||||
@@ -2439,7 +2474,7 @@ export function renderAskUserCard(payload, options) {
|
||||
});
|
||||
other.appendChild(otherInput);
|
||||
other.appendChild(otherSend);
|
||||
card.appendChild(other);
|
||||
if (!isToolApproval) card.appendChild(other);
|
||||
|
||||
chatBox.appendChild(card);
|
||||
if (renderOptions.scroll !== false) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import Storage from './storage.js';
|
||||
import uiModule, { autoResize, styledPrompt } from './ui.js';
|
||||
import chatRenderer from './chatRenderer.js?v=20260722ctxheader1';
|
||||
import chatRenderer from './chatRenderer.js?v=20260815toolapproval1';
|
||||
import { providerLogo } from './providers.js';
|
||||
import { initModelPicker, updateModelPicker } from './modelPicker.js?v=20260722ctxheader1';
|
||||
import themeModule from './theme.js';
|
||||
|
||||
Reference in New Issue
Block a user