mirror of
https://github.com/hansjone/netxops.git
synced 2026-10-19 20:23:19 +08:00
feat(skills): merge unavailable tools into footnote, bind cache to token, prune stale caches, warn on remote plain HTTP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
056f2d4ea3
commit
05bfd97c6e
19 changed files with 1100 additions and 496 deletions
|
|
@ -1070,6 +1070,40 @@ function serializeDisabledTools(names) {
|
|||
return JSON.stringify([...new Set(names.map((n) => n.trim()).filter(Boolean))].sort());
|
||||
}
|
||||
|
||||
// src/netx/http.ts
|
||||
function normalizeApiUrl(raw) {
|
||||
const trimmed = typeof raw === "string" ? raw.trim() : "";
|
||||
if (!trimmed)
|
||||
return { ok: false, error: "empty" };
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(trimmed);
|
||||
} catch {
|
||||
return { ok: false, error: "invalid_url" };
|
||||
}
|
||||
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
||||
return { ok: false, error: "unsupported_scheme" };
|
||||
}
|
||||
if (parsed.username || parsed.password) {
|
||||
return { ok: false, error: "credentials_in_url" };
|
||||
}
|
||||
const path = parsed.pathname === "/" ? "" : parsed.pathname.replace(/\/$/, "");
|
||||
const search = parsed.search && parsed.search !== "?" ? parsed.search : "";
|
||||
return { ok: true, url: `${parsed.origin}${path}${search}` };
|
||||
}
|
||||
function isInsecureRemoteApiUrl(raw) {
|
||||
let url;
|
||||
try {
|
||||
url = new URL(raw.trim());
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
if (url.protocol !== "http:")
|
||||
return false;
|
||||
const host = url.hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
||||
return !(host === "localhost" || host.endsWith(".localhost") || host === "::1" || /^127\./.test(host));
|
||||
}
|
||||
|
||||
// src/client/NetxopsCard.tsx
|
||||
var jsx_runtime = require("react/jsx-runtime");
|
||||
function phaseLocaleKey(phase) {
|
||||
|
|
@ -1641,6 +1675,10 @@ function NetxopsCard(props) {
|
|||
props.resetField("apiUrl");
|
||||
}
|
||||
}),
|
||||
isInsecureRemoteApiUrl(state.apiUrl.text) ? /* @__PURE__ */ jsx_runtime.jsx("p", {
|
||||
className: "dsh-nx-invalid",
|
||||
children: t("apiUrlInsecure")
|
||||
}) : null,
|
||||
/* @__PURE__ */ jsx_runtime.jsxs("div", {
|
||||
className: "dsh-nx-fieldGrid",
|
||||
children: [
|
||||
|
|
@ -2161,28 +2199,6 @@ function NetxopsCard(props) {
|
|||
});
|
||||
}
|
||||
|
||||
// src/netx/http.ts
|
||||
function normalizeApiUrl(raw) {
|
||||
const trimmed = typeof raw === "string" ? raw.trim() : "";
|
||||
if (!trimmed)
|
||||
return { ok: false, error: "empty" };
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(trimmed);
|
||||
} catch {
|
||||
return { ok: false, error: "invalid_url" };
|
||||
}
|
||||
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
||||
return { ok: false, error: "unsupported_scheme" };
|
||||
}
|
||||
if (parsed.username || parsed.password) {
|
||||
return { ok: false, error: "credentials_in_url" };
|
||||
}
|
||||
const path = parsed.pathname === "/" ? "" : parsed.pathname.replace(/\/$/, "");
|
||||
const search = parsed.search && parsed.search !== "?" ? parsed.search : "";
|
||||
return { ok: true, url: `${parsed.origin}${path}${search}` };
|
||||
}
|
||||
|
||||
// src/client/snapshot-store.ts
|
||||
function createSnapshotStore(init) {
|
||||
let state = init;
|
||||
|
|
@ -3228,6 +3244,7 @@ var en = {
|
|||
sectionExport: "Session export",
|
||||
apiUrl: "API URL",
|
||||
apiUrlHint: "http://127.0.0.1:8890",
|
||||
apiUrlInsecure: "Plain HTTP to a remote host: the token and the skills sent to the model are not encrypted. Use https://.",
|
||||
apiUrlInvalid: "Enter an HTTP or HTTPS URL without credentials.",
|
||||
lang: "API / alarm language",
|
||||
thinkingLanguage: "Thinking language",
|
||||
|
|
@ -3324,6 +3341,7 @@ var zh = {
|
|||
sectionExport: "会话导出",
|
||||
apiUrl: "API 地址",
|
||||
apiUrlHint: "http://127.0.0.1:8890",
|
||||
apiUrlInsecure: "连接的是远程主机且用的是明文 HTTP:token 和发给模型的 skill 都不加密,请改用 https://。",
|
||||
apiUrlInvalid: "请输入不含账号密码的 HTTP 或 HTTPS 地址。",
|
||||
lang: "API / 告警语言",
|
||||
thinkingLanguage: "思考语言",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue