ArchiveBox/archivebox/opencode/templates/opencode/agent.html
2026-07-24 00:50:40 -07:00

212 lines
8.6 KiB
HTML

{% extends "admin/base.html" %}
{% load i18n %}
{% block title %}Agent{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; Agent
</div>
{% endblock %}
{% block extrastyle %}
{{ block.super }}
<style>
body.opencode-agent #content {
padding: 0;
}
body.opencode-agent #content-main {
height: calc(100vh - 150px);
min-height: 560px;
}
.opencode-agent-error {
margin: 24px;
color: #0f172a;
font: 14px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.opencode-agent-error code {
color: #0369a1;
}
.opencode-agent-frame {
width: 100%;
height: 100%;
border: 0;
display: block;
}
.opencode-agent-shell {
position: relative;
height: 100%;
}
.opencode-agent-welcome {
position: absolute;
inset: 0;
z-index: 20;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: rgba(0, 0, 0, 0.48);
color: #111827;
}
.opencode-agent-welcome[hidden] {
display: none;
}
.opencode-agent-welcome-panel {
width: min(720px, 100%);
max-height: min(720px, calc(100vh - 190px));
overflow: auto;
border-radius: 8px;
border: 1px solid #d1d5db;
background: Canvas;
color: CanvasText;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.32);
padding: 24px;
font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.opencode-agent-welcome-panel h1 {
margin: 0 0 10px;
font-size: 22px;
line-height: 1.25;
}
.opencode-agent-welcome-panel p {
margin: 0 0 14px;
}
.opencode-agent-welcome-panel ul {
margin: 0 0 16px 20px;
padding: 0;
}
.opencode-agent-welcome-panel li {
margin: 0 0 8px;
}
.opencode-agent-welcome-warning {
margin: 16px 0;
padding: 12px 14px;
border: 1px solid #f59e0b;
border-radius: 6px;
background: color-mix(in srgb, #f59e0b 12%, Canvas);
}
.opencode-agent-welcome-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
}
.opencode-agent-welcome button {
cursor: pointer;
border: 1px solid #2563eb;
border-radius: 6px;
background: #2563eb;
color: #fff;
padding: 8px 14px;
font-weight: 600;
}
@media (max-width: 700px) {
.opencode-agent-welcome {
padding: 12px;
}
.opencode-agent-welcome-panel {
max-height: calc(100vh - 170px);
padding: 18px;
}
}
</style>
{% endblock %}
{% block bodyclass %}{{ block.super }} opencode-agent{% endblock %}
{% block content %}
<div id="content-main">
{% if error %}
<div class="opencode-agent-error">
{{ error }}
{% if command %}<br><br><code>{{ command }}</code>{% endif %}
</div>
{% else %}
<script>
(() => {
const workdir = "{{ workdir|escapejs }}";
const recentSessionId = "{{ recent_session_id|escapejs }}";
const merge = (left, right) => {
if (!left || typeof left !== "object" || Array.isArray(left)) return right;
const out = {...left};
for (const [key, value] of Object.entries(right)) {
out[key] = value && typeof value === "object" && !Array.isArray(value) ? merge(out[key], value) : value;
}
return out;
};
const seed = (key, value) => {
try {
localStorage.setItem(key, JSON.stringify(merge(JSON.parse(localStorage.getItem(key) || "{}"), value)));
} catch {
localStorage.setItem(key, JSON.stringify(value));
}
};
const setJSON = (key, value) => localStorage.setItem(key, JSON.stringify(value));
const page = {
activeProject: workdir,
activeWorkspace: workdir,
gettingStartedDismissed: true,
workspaceExpanded: {[workdir]: true},
};
if (recentSessionId) {
page.lastProjectSession = {[workdir]: {directory: workdir, id: recentSessionId, at: Date.now()}};
}
seed("opencode.global.dat:layout.page", page);
seed("opencode.global.dat:layout", {
sidebar: {opened: true, width: 280},
fileTree: {opened: true, width: 280, tab: "all"},
});
const serverKey = `${location.origin}/admin/agent/opencode`;
setJSON("opencode.global.dat:server", {
list: [],
projects: {
[serverKey]: [{worktree: workdir, expanded: true}],
},
lastProject: {
[serverKey]: workdir,
},
});
localStorage.setItem("opencode.settings.dat:defaultServerUrl", serverKey);
})();
</script>
<div class="opencode-agent-shell">
<iframe src="{{ proxy_url }}" title="OpenCode Agent" class="opencode-agent-frame"></iframe>
<div class="opencode-agent-welcome" id="opencode-agent-welcome" hidden>
<div class="opencode-agent-welcome-panel" role="dialog" aria-modal="true" aria-labelledby="opencode-agent-welcome-title">
<h1 id="opencode-agent-welcome-title">ArchiveBox AI Agent</h1>
<p>This agent can work directly with your ArchiveBox collection. It can inspect the crawl database, create and monitor crawls, run maintenance operations, answer research questions, query archived data, and help with complex collection workflows.</p>
<p>Example prompts:</p>
<ul>
<li>Archive this list of URLs with depth 0, then report which ones failed and why.</li>
<li>Find snapshots from the last month that failed PDF or screenshot extraction and retry them.</li>
<li>Create a constrained crawl for this site, avoid login/privacy/sitemap URLs, and watch the logs as it runs.</li>
<li>Summarize what my collection contains about this topic and link to the best saved pages.</li>
</ul>
<div class="opencode-agent-welcome-warning">
The agent has unrestricted access to this collection and can make destructive edits. Review requests carefully. Permission settings can be changed from the OpenCode gear icon in the lower left.
</div>
<div class="opencode-agent-welcome-actions">
<button type="button" id="opencode-agent-welcome-dismiss">Start using Agent</button>
</div>
</div>
</div>
</div>
<script>
(() => {
const key = "archivebox.opencode.agentWelcomeDismissed.v1";
const welcome = document.getElementById("opencode-agent-welcome");
const dismiss = document.getElementById("opencode-agent-welcome-dismiss");
if (!welcome || !dismiss) return;
if (localStorage.getItem(key) !== "1") {
welcome.hidden = false;
}
dismiss.addEventListener("click", () => {
localStorage.setItem(key, "1");
welcome.hidden = true;
});
})();
</script>
{% endif %}
</div>
{% endblock %}