mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-22 09:58:06 +00:00
feat(webui): 总览底部源码区改为独立的「开源许可」框(协议 + 全文 + 源码)
此前总览底部只在 KPI 卡里挂了一行小链接(.ov-foot),既看不出受什么许可
约束,也看不出 AGPL 网络服务场景下的义务。现在单独成一张卡:
开销许可
许可协议 AGPL-3.0-only → GNU 官方全文
源码仓库 <source_url> → 仓库
网络服务条款(§13):把修改后的版本作为网络服务对外提供时,
必须向使用者提供取得对应源码的途径。
内核侧(License 是新事实,不能只靠前端写死):
- internal/meta:新增 License(SPDX 标识)与 LicenseURL,都可 -ldflags 覆盖。
LicenseURL 默认指向 GNU 官方 AGPL-3.0 全文页 —— 与仓库托管方、分支名、
文件路径都无关,换仓库/换分支不会失效。
- internal/sdk/status.go 的 BuildStatus:新增 License / LicenseURL 两个
json 字段(additive,旧消费方忽略未知字段即可)。
❗注意 internal/sdk 不受公开接口冻结约束(docs/git-branching.md §六),
本次未触碰 third_party/homeagent-sdk/sdk/。
- internal/agent/core/status.go:从 meta 填充。
前端:
- 骨架里 .ov-foot 换成独立的 <div class="card" id="ov-legal">(放在 KPI 卡之后)。
- 网络条款那一段按许可标识是否含 AGPL 决定是否渲染,不硬写协议名。
- 内容对一次构建是常量,沿用 __html 比对,填一次后不再重建(不引入闪烁)。
验证(现网 1400x920,CDP 实测):
- /api/v1/kernel 的 build 现在带 license="AGPL-3.0-only"、
license_url="https://www.gnu.org/licenses/agpl-3.0.html"
- 卡片为真框:class=card、border 1px、radius 14px;总览结构 = rt-panel | card | ov-legal
- 两个链接均为真 <a>,target=_blank + rel=noopener noreferrer
- updateOverview() 再跑一次,卡片子节点身份不变(不重建、不闪)
- 回归:KPI 版本副行、阶段管道 5 节点/5 列/6 SVG、队列 5 行×5 格 均正常
- 无横向溢出;总览/侧栏/顶栏渲染文本无 emoji
- go vet 干净;agent/core、plugins/webui、plugins 全量测试通过
This commit is contained in:
@ -103,6 +103,9 @@ func collectKernelStatus(
|
||||
KernelName: meta.KernelName,
|
||||
// AGPL-3.0 §13:状态页向网络使用者展示取得源码的入口。
|
||||
SourceURL: meta.SourceURL,
|
||||
// 许可标识与全文:与源码链接一起构成「这是什么许可 + 怎么拿到源码」。
|
||||
License: meta.License,
|
||||
LicenseURL: meta.LicenseURL,
|
||||
},
|
||||
Runtime: RuntimeStatus{
|
||||
Goroutines: runtime.NumGoroutine(),
|
||||
|
||||
@ -65,6 +65,22 @@ var (
|
||||
// 构建时可用 -ldflags 覆盖,无需改源码:
|
||||
// -X gitcode.com/JianFeeeee/HomeAgent/internal/meta.SourceURL=<你的仓库>
|
||||
SourceURL = "https://gitcode.com/JianFeeeee/HomeAgent"
|
||||
|
||||
// License 是本项目的开源许可标识(SPDX 表达式)。
|
||||
//
|
||||
// AGPL-3.0-only 带**网络条款**:把修改过的版本作为网络服务对外提供时,
|
||||
// 必须给使用者提供取得 Corresponding Source 的机会(§13)。所以 WebUI
|
||||
// 总览底部把「许可标识 + 许可全文 + 源码仓库」三者一起渲染成可见的许可卡——
|
||||
// 只给一个源码链接、不标明协议名,使用者在界面上根本看不出这是什么许可。
|
||||
License = "AGPL-3.0-only"
|
||||
|
||||
// LicenseURL 是上述许可的全文地址。
|
||||
//
|
||||
// 默认指向 GNU 官方的 AGPL-3.0 全文页:与仓库托管方、分支名、文件路径都
|
||||
// 无关,换仓库/换分支都不会失效。若你的发行版把 LICENSE 放在别处,
|
||||
// 用 -ldflags 覆盖即可:
|
||||
// -X gitcode.com/JianFeeeee/HomeAgent/internal/meta.LicenseURL=<你的链接>
|
||||
LicenseURL = "https://www.gnu.org/licenses/agpl-3.0.html"
|
||||
)
|
||||
|
||||
// FullVersion 返回完整的版本字符串。
|
||||
|
||||
@ -2855,9 +2855,15 @@
|
||||
.ov-dot.bad {
|
||||
background: var(--error);
|
||||
}
|
||||
.ov-foot {
|
||||
margin-top: 10px;
|
||||
/* 开源许可卡:协议标识 + 协议全文 + 源码仓库。
|
||||
此前只是 KPI 卡底部一行小链接(.ov-foot),在长页面里基本看不见。 */
|
||||
.ov-legal h2 {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.ov-legal-note {
|
||||
margin: 10px 0 0;
|
||||
font-size: 11px;
|
||||
line-height: 1.55;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
|
||||
@ -1378,7 +1378,10 @@
|
||||
ovKpi("memory", OV_ICONS.db, __("记忆", "Memory")) +
|
||||
ovKpi("docs", OV_ICONS.file, __("文档", "Docs")) +
|
||||
ovKpi("runtime", OV_ICONS.cpu, __("运行时", "Runtime")) +
|
||||
'</div><div class="ov-foot" id="ov-foot"></div></div>';
|
||||
'</div></div>' +
|
||||
// 开源许可单独成框:之前在 KPI 卡底部只是一行小链接(.ov-foot),
|
||||
// 几乎看不见,也看不出是许可证还是别的什么。
|
||||
'<div class="card" id="ov-legal"></div>';
|
||||
}
|
||||
updateOverview();
|
||||
}
|
||||
@ -1427,20 +1430,55 @@
|
||||
"ov-runtime",
|
||||
rt.goroutines ? rt.goroutines + (rt.memory_mb ? " · " + rt.memory_mb + "M" : "") : "—",
|
||||
);
|
||||
// 源码链接(AGPL §13):静态文本,第一次填好后不参与轮询刷新。
|
||||
var foot = document.getElementById("ov-foot");
|
||||
if (foot) {
|
||||
var src = k && k.build && k.build.source_url;
|
||||
var want = src
|
||||
? '<a href="' +
|
||||
// 开源许可卡:协议标识 + 协议全文 + 源码仓库。
|
||||
//
|
||||
// 为什么单独成框、且三者都给:AGPL-3.0 §13 的义务是「向网络使用者提供
|
||||
// 取得 Corresponding Source 的机会」——只给一个仓库链接、不写协议名,
|
||||
// 使用者看不出这受什么许可约束,也看不出网络服务场景下还有 §13 的义务。
|
||||
// 内容对一次构建是常量,所以填一次就够(__html 比对避免重复重建)。
|
||||
var legal = document.getElementById("ov-legal");
|
||||
if (legal) {
|
||||
var lb = (k && k.build) || {};
|
||||
var src = lb.source_url || "";
|
||||
var lic = lb.license || "";
|
||||
var licURL = lb.license_url || "";
|
||||
var rows = "";
|
||||
if (lic) {
|
||||
rows +=
|
||||
'<div class="kv-row"><span class="key">' +
|
||||
__("许可协议", "License") +
|
||||
'</span><span class="val">' +
|
||||
(licURL
|
||||
? '<a href="' + escHtml(licURL) + '" target="_blank" rel="noopener noreferrer">' + escHtml(lic) + "</a>"
|
||||
: escHtml(lic)) +
|
||||
"</span></div>";
|
||||
}
|
||||
if (src) {
|
||||
rows +=
|
||||
'<div class="kv-row"><span class="key">' +
|
||||
__("源码仓库", "Source") +
|
||||
'</span><span class="val"><a href="' +
|
||||
escHtml(src) +
|
||||
'" target="_blank" rel="noopener noreferrer">' +
|
||||
__("源码", "Source") +
|
||||
"</a>"
|
||||
escHtml(src) +
|
||||
"</a></span></div>";
|
||||
}
|
||||
// 网络条款只在 AGPL 系的许可下才成立,所以按标识判断,不硬写协议名。
|
||||
var note =
|
||||
lic && lic.toUpperCase().indexOf("AGPL") >= 0
|
||||
? '<p class="ov-legal-note">' +
|
||||
__(
|
||||
"网络服务条款(§13):把修改后的版本作为网络服务对外提供时,必须向使用者提供取得对应源码的途径。",
|
||||
"Network clause (section 13): offering a modified version as a network service requires giving users a way to obtain the Corresponding Source.",
|
||||
) +
|
||||
"</p>"
|
||||
: "";
|
||||
var want = rows
|
||||
? '<h2>' + __("开源许可", "License") + "</h2>" + rows + note
|
||||
: "";
|
||||
if (foot.__html !== want) {
|
||||
foot.__html = want;
|
||||
foot.innerHTML = want;
|
||||
if (legal.__html !== want) {
|
||||
legal.__html = want;
|
||||
legal.innerHTML = want;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,6 +251,13 @@ type BuildStatus struct {
|
||||
// 服务时,要给他们拿到 Corresponding Source 的机会——WebUI 状态页会把它渲染成
|
||||
// 可见链接,所以**修改后对外部署的分支必须把这个值改指向自己的源码仓库**。
|
||||
SourceURL string `json:"source_url,omitempty"`
|
||||
// License 是开源许可标识(SPDX,如 AGPL-3.0-only)。
|
||||
//
|
||||
// 为何与 SourceURL 分开:只看一个源码链接,使用者没法从界面上看出这是什么
|
||||
// 许可、网络服务场景下有哪些义务。许可名与许可全文地址是两个独立事实。
|
||||
License string `json:"license,omitempty"`
|
||||
// LicenseURL 是 License 对应的全文地址。
|
||||
LicenseURL string `json:"license_url,omitempty"`
|
||||
}
|
||||
|
||||
type TrackerStatus struct {
|
||||
|
||||
Reference in New Issue
Block a user