mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-09 00:12:21 +02:00
Squash Odysseus development history
This commit is contained in:
+43
-7
@@ -6,7 +6,7 @@
|
||||
// to that folder (see routes/chat_routes.py + src/tool_execution.py).
|
||||
|
||||
import Storage, { KEYS } from './storage.js';
|
||||
import uiModule from './ui.js';
|
||||
import uiModule from './ui.js?v=20260908weekhoverfix1';
|
||||
import { makeWindowDraggable } from './windowDrag.js';
|
||||
|
||||
const API_BASE = window.location.origin;
|
||||
@@ -14,6 +14,7 @@ const API_BASE = window.location.origin;
|
||||
const _FOLDER_SVG = '<svg class="workspace-row-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>';
|
||||
let _modal = null;
|
||||
let _curPath = '';
|
||||
let _defaultWorkspaceLoad = null;
|
||||
|
||||
export function getWorkspace() {
|
||||
return Storage.get(KEYS.WORKSPACE, '') || '';
|
||||
@@ -41,7 +42,7 @@ export function syncWorkspaceIndicator(path) {
|
||||
if (pill) {
|
||||
pill.style.display = (path && !chat) ? '' : 'none';
|
||||
pill.classList.toggle('active', !!path);
|
||||
if (path) pill.title = `Workspace: ${path}\nFile tools are confined here; shell commands start here but are not sandboxed and can reach outside it.\nClick to clear.`;
|
||||
if (path) pill.title = `Workspace: ${path}\nFile tools are confined here; shell commands start here but are not sandboxed and can reach outside it.\nClick to open workspace picker. Click X to clear.`;
|
||||
}
|
||||
if (name) name.textContent = path ? _basename(path) : '';
|
||||
if (overflow) {
|
||||
@@ -84,6 +85,22 @@ export async function vetAndSetWorkspace(path) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadDefaultWorkspace() {
|
||||
if (_defaultWorkspaceLoad) return _defaultWorkspaceLoad;
|
||||
_defaultWorkspaceLoad = fetch(`${API_BASE}/api/workspace/default`, { credentials: 'same-origin' })
|
||||
.then(async (res) => {
|
||||
if (!res.ok) return { ok: false, path: null };
|
||||
const data = await res.json();
|
||||
if (data.ok && data.path && !getWorkspace()) {
|
||||
setWorkspace(data.path);
|
||||
return { ok: true, path: data.path };
|
||||
}
|
||||
return { ok: false, path: null };
|
||||
})
|
||||
.catch(() => ({ ok: false, path: null }));
|
||||
return _defaultWorkspaceLoad;
|
||||
}
|
||||
|
||||
export function clearWorkspace() {
|
||||
setWorkspace('');
|
||||
if (uiModule && uiModule.showToast) uiModule.showToast('Workspace cleared');
|
||||
@@ -156,13 +173,19 @@ function _getModal() {
|
||||
<p class="muted workspace-note">File tools are <strong>confined</strong> to this folder. Shell commands start here but are <strong>not sandboxed</strong> and can reach outside it. A workspace scopes the tools; it is not a security boundary.</p>
|
||||
<div class="modal-body workspace-body" id="workspace-body"></div>
|
||||
<div class="modal-footer workspace-footer">
|
||||
<button type="button" class="confirm-btn confirm-btn-secondary" id="workspace-cancel">Cancel</button>
|
||||
<button type="button" class="confirm-btn confirm-btn-primary" id="workspace-use">Use this folder</button>
|
||||
<button type="button" class="confirm-btn confirm-btn-secondary" id="workspace-cancel"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>Cancel</button>
|
||||
<button type="button" class="confirm-btn confirm-btn-primary" id="workspace-use">${_FOLDER_SVG}Use this folder</button>
|
||||
</div>
|
||||
</div>`;
|
||||
document.body.appendChild(_modal);
|
||||
_modal.querySelector('#workspace-close').addEventListener('click', closeWorkspaceBrowser);
|
||||
_modal.querySelector('#workspace-cancel').addEventListener('click', closeWorkspaceBrowser);
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key !== 'Escape' || !_modal || _modal.style.display === 'none') return;
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
closeWorkspaceBrowser();
|
||||
}, true);
|
||||
// Editable path bar: Enter navigates to a typed/pasted folder.
|
||||
_modal.querySelector('#workspace-cur-path').addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
@@ -198,11 +221,24 @@ export function closeWorkspaceBrowser() {
|
||||
|
||||
export function initWorkspace() {
|
||||
// Restore persisted workspace into the pill on load.
|
||||
syncWorkspaceIndicator(getWorkspace());
|
||||
const current = getWorkspace();
|
||||
syncWorkspaceIndicator(current);
|
||||
// A browser has no trustworthy local launch directory. Let a deployment
|
||||
// provide one explicitly, and only use it when the user has no saved choice.
|
||||
if (!current) loadDefaultWorkspace();
|
||||
const overflow = document.getElementById('overflow-workspace-btn');
|
||||
if (overflow) overflow.addEventListener('click', openWorkspaceBrowser);
|
||||
const pill = document.getElementById('workspace-indicator-btn');
|
||||
if (pill) pill.addEventListener('click', clearWorkspace);
|
||||
if (pill) {
|
||||
pill.addEventListener('click', openWorkspaceBrowser);
|
||||
const clearBtn = pill.querySelector('.tool-indicator-x');
|
||||
if (clearBtn) {
|
||||
clearBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
clearWorkspace();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default { initWorkspace, openWorkspaceBrowser, getWorkspace, setWorkspace, vetAndSetWorkspace, clearWorkspace, syncWorkspaceIndicator, applyMode };
|
||||
export default { initWorkspace, openWorkspaceBrowser, getWorkspace, setWorkspace, vetAndSetWorkspace, loadDefaultWorkspace, clearWorkspace, syncWorkspaceIndicator, applyMode };
|
||||
|
||||
Reference in New Issue
Block a user