release: archivebox 0.9.34rc47

This commit is contained in:
Nick Sweeting 2026-06-03 21:37:13 -07:00
parent 5b74eb5238
commit 77ee827a58
No known key found for this signature in database
6 changed files with 78 additions and 34 deletions

View File

@ -35,6 +35,9 @@
top: 0;
z-index: 10;
}
#progress-monitor.collapsed .header-bar {
cursor: pointer;
}
#progress-monitor .header-left {
display: flex;
align-items: center;
@ -1884,9 +1887,14 @@
}
// Collapse toggle
collapseBtn.addEventListener('click', function() {
collapseBtn.addEventListener('click', function(event) {
event.stopPropagation();
setCollapsedState(!isCollapsed);
});
monitor.querySelector('.header-bar').addEventListener('click', function(event) {
if (event.target.closest('button, a, input, select, textarea, [role="button"]')) return;
if (isCollapsed) setCollapsedState(false);
});
crawlTree.addEventListener('click', function(event) {
const actionBtn = event.target.closest('.crawl-action-btn');

View File

@ -62,7 +62,7 @@ def get_search_mode_options(config: dict[str, Any] | None = None, **config_kwarg
]
options = [
{"value": "meta", "label": "meta"},
{"value": "contents", "label": "contents"},
{"value": "contents", "label": "deep"},
]
if backend_names:
options.extend(

View File

@ -1,5 +1,4 @@
import os
import sqlite3
import pytest
import requests
@ -149,6 +148,17 @@ def test_opencode_project_current_is_seeded_data_project(admin_client, tmp_path,
monkeypatch.setattr(views, "_machine_config", lambda: {"OPENCODE_ENABLED": True, "OPENCODE_WORKDIR": str(workdir)})
monkeypatch.setattr(views, "_ensure_opencode", lambda settings: (True, ""))
def fake_request(method, url, **kwargs):
assert url == "http://127.0.0.1:4096/project/current"
assert kwargs["params"] == (("directory", str(workdir)),)
upstream = requests.Response()
upstream.status_code = 200
upstream._content = (f'{{"id":"global","worktree":"{workdir.resolve()}","name":"data"}}').encode()
upstream.headers["Content-Type"] = "application/json"
return upstream
monkeypatch.setattr(views.requests, "request", fake_request)
response = admin_client.get(
f"/admin/agent/opencode/project/current?directory={workdir}",
HTTP_HOST=ADMIN_TEST_HOST,
@ -167,6 +177,17 @@ def test_opencode_path_reports_data_as_worktree(admin_client, tmp_path, db, monk
monkeypatch.setattr(views, "_machine_config", lambda: {"OPENCODE_ENABLED": True, "OPENCODE_WORKDIR": str(workdir)})
monkeypatch.setattr(views, "_ensure_opencode", lambda settings: (True, ""))
def fake_request(method, url, **kwargs):
assert url == "http://127.0.0.1:4096/path"
assert kwargs["params"] == (("directory", str(workdir)),)
upstream = requests.Response()
upstream.status_code = 200
upstream._content = (f'{{"directory":"{workdir.resolve()}","worktree":"{workdir.resolve()}"}}').encode()
upstream.headers["Content-Type"] = "application/json"
return upstream
monkeypatch.setattr(views.requests, "request", fake_request)
response = admin_client.get(
f"/admin/agent/opencode/path?directory={workdir}",
HTTP_HOST=ADMIN_TEST_HOST,
@ -284,10 +305,9 @@ def test_opencode_starts_without_opening_browser(tmp_path, monkeypatch):
return FakeProcess()
monkeypatch.setattr(views, "_health", lambda settings: next(health_checks))
monkeypatch.setattr(views.shutil, "which", lambda binary: "/usr/bin/false")
monkeypatch.setattr(views.subprocess, "Popen", fake_popen)
settings = views._settings({"OPENCODE_WORKDIR": str(tmp_path)})
settings = views._settings({"OPENCODE_WORKDIR": str(tmp_path), "OPENCODE_BINARY": "/usr/bin/false"})
ok, error = views._ensure_opencode(settings)
assert ok, error
@ -310,35 +330,47 @@ def test_opencode_state_dir_is_separate_from_workdir(tmp_path):
assert settings["config_home"] == workdir / "opencode" / "config"
assert settings["data_home"] == workdir / "opencode" / "data"
assert settings["state_home"] == workdir / "opencode" / "state"
skill = workdir / "opencode" / "config" / "opencode" / "skills" / "archivebox" / "SKILL.md"
assert skill.exists()
assert f"ArchiveBox collection directory: {workdir.resolve()}" in skill.read_text()
editable_skill = workdir / "opencode" / "SKILL.md"
loaded_skill = workdir / "opencode" / "config" / "opencode" / "skills" / "archivebox" / "SKILL.md"
assert editable_skill.exists()
assert loaded_skill.is_symlink()
assert loaded_skill.resolve() == editable_skill.resolve()
assert f"ArchiveBox collection directory: {workdir.resolve()}" in editable_skill.read_text()
def test_opencode_seeds_global_project_under_embedded_data_dir(tmp_path):
def test_opencode_ensures_default_session_with_public_api(tmp_path, monkeypatch):
from abx_plugins.plugins.opencode import views
workdir = tmp_path / "data"
settings = views._settings({"OPENCODE_WORKDIR": str(workdir)})
db_path = settings["data_home"] / "opencode" / "opencode.db"
db_path.parent.mkdir(parents=True)
with sqlite3.connect(db_path) as db:
db.execute(
"""
CREATE TABLE project (
id text PRIMARY KEY,
worktree text NOT NULL,
name text,
time_created integer NOT NULL,
time_updated integer NOT NULL,
sandboxes text NOT NULL
)
""",
)
calls = []
views._ensure_global_project(settings)
def fake_get(url, **kwargs):
calls.append(("GET", url, kwargs))
response = requests.Response()
response.status_code = 200
response._content = b"[]" if url.endswith("/session") else b"{}"
return response
with sqlite3.connect(db_path) as db:
row = db.execute("SELECT id, worktree, name, sandboxes FROM project").fetchone()
def fake_post(url, **kwargs):
calls.append(("POST", url, kwargs))
response = requests.Response()
response.status_code = 200
response._content = b'{"id":"session"}'
return response
assert row == ("global", str(workdir.resolve()), "data", "[]")
monkeypatch.setattr(views.requests, "get", fake_get)
monkeypatch.setattr(views.requests, "post", fake_post)
views._ensure_default_session(settings)
assert calls[0] == (
"GET",
"http://127.0.0.1:4096/project/current",
{"params": {"directory": str(workdir.resolve())}, "timeout": 30},
)
assert calls[1][0:2] == ("GET", "http://127.0.0.1:4096/session")
assert calls[1][2]["params"] == {"directory": str(workdir.resolve()), "roots": "true", "limit": 55}
assert calls[2][0:2] == ("POST", "http://127.0.0.1:4096/session")
assert calls[2][2]["params"] == {"directory": str(workdir.resolve())}
assert calls[2][2]["json"] == {}

View File

@ -128,6 +128,7 @@ def test_search_mode_options_use_canonical_backend_names(monkeypatch):
options = get_search_mode_options()
assert {"value": "contents", "label": "deep"} in options
assert {"value": "deep:ripgrep", "label": "deep:ripgrep"} in options
assert all(not option["label"].startswith("deep: ") for option in options)
@ -176,7 +177,8 @@ class TestAdminSnapshotSearch:
assert response.status_code == 200
assert response.context["cl"].search_mode == "deep:ripgrep"
assert b'name="search_mode"' in response.content
assert b'value="contents"' in response.content
assert b'<option value="contents">deep</option>' in response.content
assert b">contents<" not in response.content
assert b'value="deep:ripgrep"' in response.content
assert b">deep:ripgrep<" in response.content
@ -388,6 +390,8 @@ class TestPublicIndexSearch:
assert response.status_code == 200
assert response.context["search_mode"] == "deep:ripgrep"
assert b'name="search_mode"' in response.content
assert b'<option value="contents">deep</option>' in response.content
assert b">contents<" not in response.content
assert b'value="deep:ripgrep"' in response.content
assert b">deep:ripgrep<" in response.content

View File

@ -1,6 +1,6 @@
{
"name": "archivebox",
"version": "0.9.34rc40",
"version": "0.9.34rc47",
"repository": "github:ArchiveBox/ArchiveBox",
"license": "MIT",
"dependencies": {

View File

@ -1,6 +1,6 @@
[project]
name = "archivebox"
version = "0.9.34rc46"
version = "0.9.34rc47"
requires-python = ">=3.13"
description = "Self-hosted internet archiving solution."
authors = [{name = "Nick Sweeting", email = "pyproject.toml@archivebox.io"}]
@ -79,9 +79,9 @@ dependencies = [
### Extractor dependencies (optional binaries detected at runtime via shutil.which)
### Binary/Package Management
"abxbus==2.5.10", # EventBus API
"abxpkg>=1.11.162", # for: detecting, versioning, and installing binaries via apt/brew/pip/npm
"abx-plugins>=1.11.165", # shared ArchiveBox plugin package with Chrome/Puppeteer dependency wiring
"abx-dl>=1.11.165", # shared ArchiveBox downloader package with blocking install preflight
"abxpkg>=1.11.163", # for: detecting, versioning, and installing binaries via apt/brew/pip/npm
"abx-plugins>=1.11.166", # shared ArchiveBox plugin package with Chrome/Puppeteer dependency wiring
"abx-dl>=1.11.166", # shared ArchiveBox downloader package with blocking install preflight
### UUID7 backport for Python <3.14
"uuid7>=0.1.0; python_version < '3.14'", # provides the uuid_extensions module on Python 3.13
]