jishushell 0.4.30 → 0.5.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile.hermes-slim +2 -5
- package/apps/anythingllm-container.yaml +287 -0
- package/apps/browserless-chromium-container.yaml +18 -6
- package/apps/filebrowser-container.yaml +164 -0
- package/apps/ollama-binary.yaml +44 -0
- package/apps/ollama-with-hollama-binary.yaml +45 -1
- package/apps/openclaw-binary.yaml +8 -0
- package/apps/openclaw-container.yaml +9 -1
- package/apps/openclaw-with-searxng-container.yaml +4 -0
- package/apps/searxng-container.yaml +5 -4
- package/apps/weknora-container.yaml +471 -0
- package/dist/cli/doctor.js +144 -16
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/panel.js.map +1 -1
- package/dist/config.d.ts +19 -0
- package/dist/config.js +99 -1
- package/dist/config.js.map +1 -1
- package/dist/install.js +4 -4
- package/dist/install.js.map +1 -1
- package/dist/routes/auth.js +2 -2
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/backup.js +64 -11
- package/dist/routes/backup.js.map +1 -1
- package/dist/routes/external-mounts.d.ts +17 -0
- package/dist/routes/external-mounts.js +73 -0
- package/dist/routes/external-mounts.js.map +1 -0
- package/dist/routes/file-mounts.d.ts +13 -0
- package/dist/routes/file-mounts.js +90 -0
- package/dist/routes/file-mounts.js.map +1 -0
- package/dist/routes/files-organize.d.ts +28 -0
- package/dist/routes/files-organize.js +167 -0
- package/dist/routes/files-organize.js.map +1 -0
- package/dist/routes/files.d.ts +31 -0
- package/dist/routes/files.js +321 -0
- package/dist/routes/files.js.map +1 -0
- package/dist/routes/instances.js +87 -12
- package/dist/routes/instances.js.map +1 -1
- package/dist/routes/internal.d.ts +2 -0
- package/dist/routes/internal.js +59 -0
- package/dist/routes/internal.js.map +1 -0
- package/dist/routes/llm.js +29 -0
- package/dist/routes/llm.js.map +1 -1
- package/dist/routes/setup.js +9 -9
- package/dist/routes/setup.js.map +1 -1
- package/dist/routes/system.js +1 -1
- package/dist/routes/system.js.map +1 -1
- package/dist/routes/webdav.d.ts +17 -0
- package/dist/routes/webdav.js +114 -0
- package/dist/routes/webdav.js.map +1 -0
- package/dist/server.js +358 -6
- package/dist/server.js.map +1 -1
- package/dist/services/agent-apps/catalog.d.ts +3 -0
- package/dist/services/agent-apps/catalog.js +40 -13
- package/dist/services/agent-apps/catalog.js.map +1 -1
- package/dist/services/agent-apps/installers/shell-script.d.ts +1 -1
- package/dist/services/agent-apps/installers/shell-script.js +19 -2
- package/dist/services/agent-apps/installers/shell-script.js.map +1 -1
- package/dist/services/agent-apps/types.d.ts +3 -0
- package/dist/services/app/app-compiler.d.ts +1 -1
- package/dist/services/app/app-compiler.js +5 -5
- package/dist/services/app/app-compiler.js.map +1 -1
- package/dist/services/app/app-manager.d.ts +9 -0
- package/dist/services/app/app-manager.js +248 -43
- package/dist/services/app/app-manager.js.map +1 -1
- package/dist/services/app/custom-manager.js.map +1 -1
- package/dist/services/app/hermes-agent-manager.js +1 -0
- package/dist/services/app/hermes-agent-manager.js.map +1 -1
- package/dist/services/app/ollama-manager.js +1 -1
- package/dist/services/app/ollama-manager.js.map +1 -1
- package/dist/services/app/openclaw-manager.js +37 -5
- package/dist/services/app/openclaw-manager.js.map +1 -1
- package/dist/services/app/platform-transform.d.ts +32 -0
- package/dist/services/app/platform-transform.js +65 -0
- package/dist/services/app/platform-transform.js.map +1 -0
- package/dist/services/app-passwords.d.ts +61 -0
- package/dist/services/app-passwords.js +173 -0
- package/dist/services/app-passwords.js.map +1 -0
- package/dist/services/backup-manager.d.ts +11 -0
- package/dist/services/backup-manager.js +220 -8
- package/dist/services/backup-manager.js.map +1 -1
- package/dist/services/capability-endpoint-validator.js +26 -7
- package/dist/services/capability-endpoint-validator.js.map +1 -1
- package/dist/services/connection-apply.d.ts +2 -0
- package/dist/services/connection-apply.js +55 -1
- package/dist/services/connection-apply.js.map +1 -1
- package/dist/services/connection-resolver.js +1 -1
- package/dist/services/connection-resolver.js.map +1 -1
- package/dist/services/connection-transactor.d.ts +2 -0
- package/dist/services/connection-transactor.js +12 -2
- package/dist/services/connection-transactor.js.map +1 -1
- package/dist/services/external-mounts.d.ts +40 -0
- package/dist/services/external-mounts.js +187 -0
- package/dist/services/external-mounts.js.map +1 -0
- package/dist/services/files-manager.d.ts +252 -0
- package/dist/services/files-manager.js +1075 -0
- package/dist/services/files-manager.js.map +1 -0
- package/dist/services/files-mounts.d.ts +42 -0
- package/dist/services/files-mounts.js +207 -0
- package/dist/services/files-mounts.js.map +1 -0
- package/dist/services/instance-manager.js +90 -32
- package/dist/services/instance-manager.js.map +1 -1
- package/dist/services/llm-proxy/index.d.ts +28 -0
- package/dist/services/llm-proxy/index.js +76 -3
- package/dist/services/llm-proxy/index.js.map +1 -1
- package/dist/services/llm-proxy/ssrf.js +6 -2
- package/dist/services/llm-proxy/ssrf.js.map +1 -1
- package/dist/services/llm-proxy/validate-key.d.ts +41 -0
- package/dist/services/llm-proxy/validate-key.js +672 -0
- package/dist/services/llm-proxy/validate-key.js.map +1 -0
- package/dist/services/macos-launchd.d.ts +89 -0
- package/dist/services/macos-launchd.js +273 -0
- package/dist/services/macos-launchd.js.map +1 -0
- package/dist/services/nomad-manager.d.ts +11 -0
- package/dist/services/nomad-manager.js +343 -98
- package/dist/services/nomad-manager.js.map +1 -1
- package/dist/services/organize/applier.d.ts +46 -0
- package/dist/services/organize/applier.js +218 -0
- package/dist/services/organize/applier.js.map +1 -0
- package/dist/services/organize/rules.d.ts +57 -0
- package/dist/services/organize/rules.js +286 -0
- package/dist/services/organize/rules.js.map +1 -0
- package/dist/services/organize/scanner.d.ts +50 -0
- package/dist/services/organize/scanner.js +366 -0
- package/dist/services/organize/scanner.js.map +1 -0
- package/dist/services/organize/store.d.ts +14 -0
- package/dist/services/organize/store.js +82 -0
- package/dist/services/organize/store.js.map +1 -0
- package/dist/services/panel-manager.js +40 -11
- package/dist/services/panel-manager.js.map +1 -1
- package/dist/services/process-manager.js +3 -2
- package/dist/services/process-manager.js.map +1 -1
- package/dist/services/runtime/adapters/custom.js +56 -0
- package/dist/services/runtime/adapters/custom.js.map +1 -1
- package/dist/services/runtime/adapters/hermes.d.ts +4 -3
- package/dist/services/runtime/adapters/hermes.js +166 -64
- package/dist/services/runtime/adapters/hermes.js.map +1 -1
- package/dist/services/runtime/adapters/openclaw-routes.d.ts +8 -2
- package/dist/services/runtime/adapters/openclaw-routes.js +68 -0
- package/dist/services/runtime/adapters/openclaw-routes.js.map +1 -1
- package/dist/services/runtime/adapters/openclaw.d.ts +118 -0
- package/dist/services/runtime/adapters/openclaw.js +1459 -49
- package/dist/services/runtime/adapters/openclaw.js.map +1 -1
- package/dist/services/runtime/instance.d.ts +1 -1
- package/dist/services/runtime/instance.js +1 -1
- package/dist/services/runtime/instance.js.map +1 -1
- package/dist/services/runtime/mcp-shims/anythingllm-shim.d.ts +46 -0
- package/dist/services/runtime/mcp-shims/anythingllm-shim.js +281 -0
- package/dist/services/runtime/mcp-shims/anythingllm-shim.js.map +1 -0
- package/dist/services/runtime/mcp-shims/drive-shim.d.ts +54 -0
- package/dist/services/runtime/mcp-shims/drive-shim.js +489 -0
- package/dist/services/runtime/mcp-shims/drive-shim.js.map +1 -0
- package/dist/services/runtime/types.d.ts +31 -0
- package/dist/services/setup-manager.js +190 -68
- package/dist/services/setup-manager.js.map +1 -1
- package/dist/services/suggestions.js.map +1 -1
- package/dist/services/update-manager.js +32 -14
- package/dist/services/update-manager.js.map +1 -1
- package/dist/services/webdav/server.d.ts +24 -0
- package/dist/services/webdav/server.js +420 -0
- package/dist/services/webdav/server.js.map +1 -0
- package/dist/services/webdav/xml-builder.d.ts +73 -0
- package/dist/services/webdav/xml-builder.js +156 -0
- package/dist/services/webdav/xml-builder.js.map +1 -0
- package/dist/services/workspace-builder.d.ts +29 -0
- package/dist/services/workspace-builder.js +188 -0
- package/dist/services/workspace-builder.js.map +1 -0
- package/dist/types.d.ts +61 -0
- package/dist/utils/path-locks.d.ts +30 -0
- package/dist/utils/path-locks.js +63 -0
- package/dist/utils/path-locks.js.map +1 -0
- package/dist/utils/path-safety.d.ts +41 -0
- package/dist/utils/path-safety.js +119 -0
- package/dist/utils/path-safety.js.map +1 -0
- package/dist/utils/safe-write.d.ts +24 -0
- package/dist/utils/safe-write.js +82 -0
- package/dist/utils/safe-write.js.map +1 -0
- package/install/jishu-install.sh +247 -35
- package/install/jishu-uninstall.sh +45 -5
- package/package.json +20 -2
- package/public/assets/ApiKeyField-CvyAOcJS.js +1 -0
- package/public/assets/Dashboard-AuJESBlJ.js +1 -0
- package/public/assets/{HermesChatPanel-_GHoklgo.js → HermesChatPanel-CByPREwb.js} +1 -1
- package/public/assets/HermesConfigForm-DRda8FKX.js +4 -0
- package/public/assets/InitPassword-ka4wNpM5.js +1 -0
- package/public/assets/InstanceDetail-Cg1nS8HX.js +92 -0
- package/public/assets/Login-aPajuQzf.js +1 -0
- package/public/assets/NewInstance-Dd1ebNIx.js +1 -0
- package/public/assets/ProviderRecommendations-DFmADQ7V.js +1 -0
- package/public/assets/Settings-BYQnbLYL.js +1 -0
- package/public/assets/Setup-D05lwDOV.js +1 -0
- package/public/assets/WeixinLoginPanel-D89kdhP4.js +9 -0
- package/public/assets/index-HSXCsceK.css +1 -0
- package/public/assets/index-bnBu0nlQ.js +19 -0
- package/public/assets/registry-C_qeFTkZ.js +2 -0
- package/public/assets/usePolling-Bn93fe7M.js +1 -0
- package/public/assets/{vendor-i18n-ucpM0OR0.js → vendor-i18n-flxcMVeP.js} +2 -2
- package/public/assets/{vendor-react-Bk1hRGiY.js → vendor-react-ZC5T_huj.js} +7 -7
- package/public/index.html +4 -4
- package/scripts/check-app-spec.mjs +18 -4
- package/scripts/check-colima-launchd.mjs +230 -0
- package/scripts/check-new-file-tests.mjs +230 -0
- package/scripts/check-quarantine-expiry.mjs +105 -0
- package/scripts/perf/README.md +49 -0
- package/scripts/perf/auth.js +99 -0
- package/scripts/perf/config.js +63 -0
- package/scripts/perf/instances.js +143 -0
- package/scripts/perf/proxy.js +96 -0
- package/scripts/smoke/files-w1.sh +142 -0
- package/scripts/smoke-backend.mjs +122 -0
- package/scripts/smoke-post-publish.mjs +346 -0
- package/public/assets/Dashboard-rkWp-CXd.js +0 -1
- package/public/assets/HermesConfigForm-anDnwUp_.js +0 -4
- package/public/assets/InitPassword-ZU9_-hDr.js +0 -1
- package/public/assets/InstanceDetail-CN0FH1aw.js +0 -92
- package/public/assets/Login-BItXqYAJ.js +0 -1
- package/public/assets/NewInstance-BousE6kY.js +0 -1
- package/public/assets/ProviderRecommendations-DFYj7Fb6.js +0 -1
- package/public/assets/Settings-Bttc6QmM.js +0 -1
- package/public/assets/Setup-Bsxx1zgj.js +0 -1
- package/public/assets/WeixinLoginPanel-DPZpAKgO.js +0 -9
- package/public/assets/index-8xZy1z5k.css +0 -1
- package/public/assets/index-Dw3HhUYE.js +0 -19
- package/public/assets/input-paste-CrNVAyOy.js +0 -1
- package/public/assets/providers-DtNXh9JD.js +0 -1
- package/public/assets/registry-5s2UB6is.js +0 -2
- package/public/assets/usePolling-Do5Erqm_.js +0 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AnythingLLM MCP shim — exposes the user's installed AnythingLLM
|
|
3
|
+
* workspace as a single `kb_search(query)` MCP tool to the agent
|
|
4
|
+
* inside the OpenClaw container.
|
|
5
|
+
*
|
|
6
|
+
* Why a shim, not direct MCP:
|
|
7
|
+
* AnythingLLM speaks HTTP REST (`/api/v1/workspace/{slug}/chat`),
|
|
8
|
+
* not MCP. The shim translates one MCP tool call into one
|
|
9
|
+
* workspace-chat HTTP call and packages the textResponse + sources
|
|
10
|
+
* array as a text content block for the agent.
|
|
11
|
+
*
|
|
12
|
+
* Wiring: the OpenClaw adapter writes this shim into
|
|
13
|
+
* `__mcp_shims__/anythingllm/anythingllm-shim.js` per instance and
|
|
14
|
+
* registers it in mcporter.json under the `kb` server name.
|
|
15
|
+
* Non-secret config (baseUrl + workspace) is baked into the source by
|
|
16
|
+
* `substituteAnythingllmShimPlaceholders` because OpenClaw scrubs
|
|
17
|
+
* env when spawning MCP subprocesses (verified via the drive shim
|
|
18
|
+
* regression on pi2 2026-05-11). The API key is NOT baked into the
|
|
19
|
+
* source — it lives in a sibling `secret.json` file written with
|
|
20
|
+
* mode 0o600 so the readable-to-world shim source stays free of
|
|
21
|
+
* secrets and mcporter.json (mode 0o644) does too. Env fallbacks are
|
|
22
|
+
* kept only for hand-running during development.
|
|
23
|
+
*
|
|
24
|
+
* Stdio framing: NDJSON JSON-RPC 2.0 (MCP standard). Pure Node
|
|
25
|
+
* builtins, no npm install needed inside the runtime image.
|
|
26
|
+
*/
|
|
27
|
+
export const ANYTHINGLLM_MCP_SHIM_VERSION = "0.2.0";
|
|
28
|
+
/** Filename for the sibling 0o600 secret file (path resolved at runtime). */
|
|
29
|
+
export const ANYTHINGLLM_SHIM_SECRET_FILENAME = "secret.json";
|
|
30
|
+
export const ANYTHINGLLM_MCP_SHIM_SOURCE = `#!/usr/bin/env node
|
|
31
|
+
// jishushell-anythingllm-shim — generated, do not edit by hand.
|
|
32
|
+
// Source: src/services/runtime/mcp-shims/anythingllm-shim.ts
|
|
33
|
+
|
|
34
|
+
const path = require("node:path");
|
|
35
|
+
const fs = require("node:fs");
|
|
36
|
+
|
|
37
|
+
const BASE_URL_LIT = "__JS_BASE_URL__";
|
|
38
|
+
const WORKSPACE_LIT = "__JS_WORKSPACE__";
|
|
39
|
+
|
|
40
|
+
// API key comes from a 0o600 sibling file so neither the shim source
|
|
41
|
+
// (mode 0o644) nor mcporter.json (also 0o644) carries the plaintext key.
|
|
42
|
+
function loadApiKey() {
|
|
43
|
+
try {
|
|
44
|
+
const secretPath = path.join(__dirname, ${JSON.stringify(ANYTHINGLLM_SHIM_SECRET_FILENAME)});
|
|
45
|
+
const raw = fs.readFileSync(secretPath, "utf-8");
|
|
46
|
+
const j = JSON.parse(raw);
|
|
47
|
+
if (j && typeof j.apiKey === "string" && j.apiKey) return j.apiKey;
|
|
48
|
+
} catch (_) { /* fall through to env fallback */ }
|
|
49
|
+
return process.env.ANYTHINGLLM_API_KEY || "";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const BASE_URL = (BASE_URL_LIT.startsWith("__JS_") ? (process.env.ANYTHINGLLM_BASE_URL || "") : BASE_URL_LIT).replace(/\\/+$/, "");
|
|
53
|
+
const API_KEY = loadApiKey();
|
|
54
|
+
const WORKSPACE = WORKSPACE_LIT.startsWith("__JS_") ? (process.env.ANYTHINGLLM_WORKSPACE || "default") : WORKSPACE_LIT;
|
|
55
|
+
|
|
56
|
+
function envCheck() {
|
|
57
|
+
const missing = [];
|
|
58
|
+
if (!BASE_URL) missing.push("ANYTHINGLLM_BASE_URL");
|
|
59
|
+
if (!API_KEY) missing.push("ANYTHINGLLM_API_KEY");
|
|
60
|
+
if (missing.length) {
|
|
61
|
+
throw new Error("anythingllm-shim: missing env: " + missing.join(", "));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function kbSearch(query) {
|
|
66
|
+
envCheck();
|
|
67
|
+
// mode=query forces "answer only from KB" — what we want for a tool call.
|
|
68
|
+
// Workspace endpoint surfaces \`sources\` array natively for citation.
|
|
69
|
+
const r = await fetch(BASE_URL + "/api/v1/workspace/" + WORKSPACE + "/chat", {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: {
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
"Authorization": "Bearer " + API_KEY,
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify({ message: query, mode: "query" }),
|
|
76
|
+
});
|
|
77
|
+
if (!r.ok) {
|
|
78
|
+
const txt = await r.text();
|
|
79
|
+
throw new Error("workspace chat " + r.status + ": " + txt.slice(0, 400));
|
|
80
|
+
}
|
|
81
|
+
const j = await r.json();
|
|
82
|
+
return {
|
|
83
|
+
answer: j.textResponse || "(no answer)",
|
|
84
|
+
sources: Array.isArray(j.sources) ? j.sources : [],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// kb_ingest — read a host-side file and push it into AnythingLLM, then
|
|
89
|
+
// embed into the workspace. The agent gets the absolute path via
|
|
90
|
+
// drive_resolve_local_path, so this is a thin "upload + embed" wrapper.
|
|
91
|
+
//
|
|
92
|
+
// AnythingLLM endpoints used:
|
|
93
|
+
// POST /api/v1/document/upload — multipart, returns documents[]
|
|
94
|
+
// with .location strings
|
|
95
|
+
// POST /api/v1/workspace/{slug}/update-embeddings
|
|
96
|
+
// — body: { adds: [location, ...] }
|
|
97
|
+
//
|
|
98
|
+
// We intentionally don't use AnythingLLM's own \`addToWorkspaces\` query
|
|
99
|
+
// param on /upload — it returns success but doesn't always trigger
|
|
100
|
+
// embedding on first call (verified empirically on 1.7.4); explicit
|
|
101
|
+
// /update-embeddings is the reliable path.
|
|
102
|
+
async function kbIngest(absPath, workspace) {
|
|
103
|
+
envCheck();
|
|
104
|
+
const fs = require("node:fs");
|
|
105
|
+
const path = require("node:path");
|
|
106
|
+
if (!absPath || typeof absPath !== "string") {
|
|
107
|
+
throw new Error("kb_ingest: missing 'path' argument");
|
|
108
|
+
}
|
|
109
|
+
if (!fs.existsSync(absPath)) throw new Error("kb_ingest: file not found: " + absPath);
|
|
110
|
+
const stat = fs.statSync(absPath);
|
|
111
|
+
if (!stat.isFile()) throw new Error("kb_ingest: not a regular file: " + absPath);
|
|
112
|
+
const ws = workspace || WORKSPACE;
|
|
113
|
+
const filename = path.basename(absPath);
|
|
114
|
+
const buf = fs.readFileSync(absPath);
|
|
115
|
+
|
|
116
|
+
// Browser-style FormData is available since Node 18 globally.
|
|
117
|
+
const fd = new FormData();
|
|
118
|
+
// Blob with simple application/octet-stream is fine — AnythingLLM sniffs
|
|
119
|
+
// type from the filename extension server-side.
|
|
120
|
+
fd.append("file", new Blob([buf]), filename);
|
|
121
|
+
|
|
122
|
+
const upRes = await fetch(BASE_URL + "/api/v1/document/upload", {
|
|
123
|
+
method: "POST",
|
|
124
|
+
headers: { "Authorization": "Bearer " + API_KEY },
|
|
125
|
+
body: fd,
|
|
126
|
+
});
|
|
127
|
+
if (!upRes.ok) {
|
|
128
|
+
const txt = await upRes.text();
|
|
129
|
+
throw new Error("upload " + upRes.status + ": " + txt.slice(0, 400));
|
|
130
|
+
}
|
|
131
|
+
const upJson = await upRes.json();
|
|
132
|
+
if (upJson.error) throw new Error("upload error: " + upJson.error);
|
|
133
|
+
const docs = Array.isArray(upJson.documents) ? upJson.documents : [];
|
|
134
|
+
if (docs.length === 0) throw new Error("upload returned no documents");
|
|
135
|
+
|
|
136
|
+
// Each doc has \`.location\` like "custom-documents/<filename>-<uuid>.json"
|
|
137
|
+
// — that is the string /update-embeddings expects in adds[].
|
|
138
|
+
const adds = docs.map((d) => d.location).filter(Boolean);
|
|
139
|
+
if (adds.length === 0) throw new Error("uploaded docs missing location field");
|
|
140
|
+
|
|
141
|
+
const embRes = await fetch(BASE_URL + "/api/v1/workspace/" + ws + "/update-embeddings", {
|
|
142
|
+
method: "POST",
|
|
143
|
+
headers: {
|
|
144
|
+
"Content-Type": "application/json",
|
|
145
|
+
"Authorization": "Bearer " + API_KEY,
|
|
146
|
+
},
|
|
147
|
+
body: JSON.stringify({ adds, deletes: [] }),
|
|
148
|
+
});
|
|
149
|
+
if (!embRes.ok) {
|
|
150
|
+
const txt = await embRes.text();
|
|
151
|
+
throw new Error("embed " + embRes.status + ": " + txt.slice(0, 400));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return { filename, sizeBytes: stat.size, workspace: ws, locations: adds };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function fmtResult(res) {
|
|
158
|
+
let out = res.answer;
|
|
159
|
+
if (res.sources.length) {
|
|
160
|
+
const seen = new Set();
|
|
161
|
+
const lines = [];
|
|
162
|
+
for (const s of res.sources) {
|
|
163
|
+
const key = s.title || s.url || s.docId || "?";
|
|
164
|
+
if (seen.has(key)) continue;
|
|
165
|
+
seen.add(key);
|
|
166
|
+
const scoreStr = s.score != null ? " [score " + Number(s.score).toFixed(2) + "]" : "";
|
|
167
|
+
lines.push("- " + key + scoreStr);
|
|
168
|
+
if (lines.length >= 5) break;
|
|
169
|
+
}
|
|
170
|
+
if (lines.length) out += "\\n\\n--- 引用 ---\\n" + lines.join("\\n");
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const TOOLS = [
|
|
176
|
+
{
|
|
177
|
+
name: "kb_search",
|
|
178
|
+
description: "Search the user's knowledge base (uploaded docs / manuals / PDFs / notes) for an answer. Use whenever the user asks something likely to be answered by their uploaded documents. Returns the answer text plus up to 5 cited source files. DO NOT call for greetings, code generation, math, real-time queries, or NAS file operations (those go to drive_*).",
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: "object",
|
|
181
|
+
properties: {
|
|
182
|
+
query: { type: "string", description: "The user question, in their original language" },
|
|
183
|
+
},
|
|
184
|
+
required: ["query"],
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: "kb_ingest",
|
|
189
|
+
description: "Push a host-side file into the user's knowledge base and embed it so future kb_search calls can find it. Use when the user says \\"加进知识库 / index this / add to KB / 学习这份资料\\" about a file already on disk. Workflow: drive_resolve_local_path to get the absolute path, then kb_ingest with that path. Returns filename + size + workspace.",
|
|
190
|
+
inputSchema: {
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: {
|
|
193
|
+
path: { type: "string", description: "Absolute host path to the file (from drive_resolve_local_path)" },
|
|
194
|
+
workspace: { type: "string", description: "Optional workspace slug; defaults to the panel-wired workspace" },
|
|
195
|
+
},
|
|
196
|
+
required: ["path"],
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
function reply(id, result, error) {
|
|
202
|
+
const msg = { jsonrpc: "2.0", id };
|
|
203
|
+
if (error) msg.error = { code: -32603, message: error.message || String(error) };
|
|
204
|
+
else msg.result = result;
|
|
205
|
+
process.stdout.write(JSON.stringify(msg) + "\\n");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function handle(req) {
|
|
209
|
+
const { id, method, params } = req;
|
|
210
|
+
try {
|
|
211
|
+
if (method === "initialize") {
|
|
212
|
+
reply(id, {
|
|
213
|
+
protocolVersion: "2024-11-05",
|
|
214
|
+
capabilities: { tools: {} },
|
|
215
|
+
serverInfo: { name: "anythingllm-shim", version: ${JSON.stringify(ANYTHINGLLM_MCP_SHIM_VERSION)} },
|
|
216
|
+
});
|
|
217
|
+
} else if (method === "tools/list") {
|
|
218
|
+
reply(id, { tools: TOOLS });
|
|
219
|
+
} else if (method === "tools/call") {
|
|
220
|
+
const tool = params?.name;
|
|
221
|
+
if (tool === "kb_search") {
|
|
222
|
+
const query = params?.arguments?.query;
|
|
223
|
+
if (!query) throw new Error("kb_search: missing 'query' argument");
|
|
224
|
+
const result = await kbSearch(query);
|
|
225
|
+
reply(id, { content: [{ type: "text", text: fmtResult(result) }] });
|
|
226
|
+
} else if (tool === "kb_ingest") {
|
|
227
|
+
const a = params?.arguments || {};
|
|
228
|
+
const result = await kbIngest(a.path, a.workspace);
|
|
229
|
+
reply(id, { content: [{ type: "text", text:
|
|
230
|
+
"✅ 已加入知识库: " + result.filename +
|
|
231
|
+
" (" + result.sizeBytes + " bytes, workspace=" + result.workspace + ")" +
|
|
232
|
+
"\\n embeddings 处理中,几秒后 kb_search 即可命中。"
|
|
233
|
+
}] });
|
|
234
|
+
} else {
|
|
235
|
+
throw new Error("unknown tool: " + tool);
|
|
236
|
+
}
|
|
237
|
+
} else if (method === "notifications/initialized") {
|
|
238
|
+
// no reply for notifications
|
|
239
|
+
} else {
|
|
240
|
+
reply(id, null, new Error("method not implemented: " + method));
|
|
241
|
+
}
|
|
242
|
+
} catch (e) {
|
|
243
|
+
reply(id, null, e);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
let inbuf = "";
|
|
248
|
+
process.stdin.setEncoding("utf-8");
|
|
249
|
+
process.stdin.on("data", (chunk) => {
|
|
250
|
+
inbuf += chunk;
|
|
251
|
+
let idx;
|
|
252
|
+
while ((idx = inbuf.indexOf("\\n")) >= 0) {
|
|
253
|
+
const line = inbuf.slice(0, idx).trim();
|
|
254
|
+
inbuf = inbuf.slice(idx + 1);
|
|
255
|
+
if (!line) continue;
|
|
256
|
+
let req;
|
|
257
|
+
try { req = JSON.parse(line); } catch { continue; }
|
|
258
|
+
void handle(req);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
process.stdin.on("end", () => process.exit(0));
|
|
262
|
+
`;
|
|
263
|
+
/**
|
|
264
|
+
* Substitute baked-in NON-SECRET values into the shim source.
|
|
265
|
+
* Same pattern as substituteDriveShimPlaceholders — done at install
|
|
266
|
+
* time because OpenClaw scrubs env on MCP subprocess spawn, so the
|
|
267
|
+
* env-fallback inside the template is unreliable in production.
|
|
268
|
+
*
|
|
269
|
+
* The API key is intentionally NOT baked in. Write it to a sibling
|
|
270
|
+
* file named `ANYTHINGLLM_SHIM_SECRET_FILENAME` (mode 0o600) and the
|
|
271
|
+
* shim will load it at startup.
|
|
272
|
+
*
|
|
273
|
+
* Placeholders use `__JS_*__` so they grep cleanly.
|
|
274
|
+
*/
|
|
275
|
+
export function substituteAnythingllmShimPlaceholders(params) {
|
|
276
|
+
const escapeStr = (s) => s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
277
|
+
return ANYTHINGLLM_MCP_SHIM_SOURCE
|
|
278
|
+
.replace(/__JS_BASE_URL__/g, escapeStr(params.baseUrl))
|
|
279
|
+
.replace(/__JS_WORKSPACE__/g, escapeStr(params.workspace || "default"));
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=anythingllm-shim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anythingllm-shim.js","sourceRoot":"","sources":["../../../../src/services/runtime/mcp-shims/anythingllm-shim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAC;AACpD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,gCAAgC,GAAG,aAAa,CAAC;AAE9D,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;8CAcG,IAAI,CAAC,SAAS,CAAC,gCAAgC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DA2KnC,IAAI,CAAC,SAAS,CAAC,4BAA4B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CtG,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qCAAqC,CACnD,MAA8C;IAE9C,MAAM,SAAS,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/E,OAAO,2BAA2B;SAC/B,OAAO,CAAC,kBAAkB,EAAE,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;SACtD,OAAO,CAAC,mBAAmB,EAAE,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drive MCP shim — exposes the panel's file + organize API to the
|
|
3
|
+
* agent inside the OpenClaw container (M1 W1.6).
|
|
4
|
+
*
|
|
5
|
+
* Why a shim, not a direct MCP server in panel:
|
|
6
|
+
* - Panel and agent run in different processes (and often different
|
|
7
|
+
* containers). Stdio MCP is the cheapest contract — the container
|
|
8
|
+
* already runs node, and `mcporter.json` already wires shim
|
|
9
|
+
* stdio servers via `command/args`.
|
|
10
|
+
* - The shim translates JSON-RPC tool calls into HTTP calls back
|
|
11
|
+
* to the panel via `host.docker.internal:8090`, authenticated
|
|
12
|
+
* with the per-host internal token (`X-Jishushell-Internal-Token`)
|
|
13
|
+
* plus the per-instance id (`X-Jishushell-Instance`).
|
|
14
|
+
*
|
|
15
|
+
* Tool surface (matches panel REST one-to-one):
|
|
16
|
+
* drive_list → GET /api/files
|
|
17
|
+
* drive_read_preview → GET /api/files/preview
|
|
18
|
+
* drive_quota → GET /api/files/quota
|
|
19
|
+
* drive_mkdir → POST /api/files/mkdir
|
|
20
|
+
* drive_organize_scan → POST /api/files/organize/scan
|
|
21
|
+
* drive_organize_apply → PUT /api/files/organize/batches/:id/apply
|
|
22
|
+
* drive_organize_revert → POST /api/files/organize/batches/:id/revert
|
|
23
|
+
* drive_search → GET /api/files/search
|
|
24
|
+
* drive_get_meta → GET /api/files/meta
|
|
25
|
+
* drive_set_meta → PUT /api/files/meta
|
|
26
|
+
* drive_reindex → POST /api/files/reindex
|
|
27
|
+
* drive_resolve_local_path → GET /api/files/resolve (v0.4 — IM-plugin bridge)
|
|
28
|
+
* drive_write_binary → PUT /api/files (v0.4 — base64 body)
|
|
29
|
+
*
|
|
30
|
+
* The user-facing chat experience this enables:
|
|
31
|
+
* user: "整理一下 inbox 里的发票"
|
|
32
|
+
* agent → drive_organize_scan({ path: "inbox" })
|
|
33
|
+
* agent → drive_organize_apply({ batch_id, selected_ids: [...] })
|
|
34
|
+
* agent: "✅ 整理了 8 张发票到 finance/2026/05/, 30 秒内可撤销"
|
|
35
|
+
*
|
|
36
|
+
* Stdio framing: NDJSON JSON-RPC 2.0 (MCP standard). Pure Node
|
|
37
|
+
* builtins — no npm install needed inside the runtime image.
|
|
38
|
+
*/
|
|
39
|
+
export declare const DRIVE_MCP_SHIM_VERSION = "0.4.0";
|
|
40
|
+
export declare const DRIVE_MCP_SHIM_SOURCE: string;
|
|
41
|
+
/**
|
|
42
|
+
* Bake per-instance values into the shim template. Returns the source to
|
|
43
|
+
* write to disk. Must be called before writing because OpenClaw scrubs
|
|
44
|
+
* env when spawning MCP subprocesses, so the env-based fallback in the
|
|
45
|
+
* template is unreliable in production.
|
|
46
|
+
*
|
|
47
|
+
* Placeholders use non-JS-identifier marker `__JS_*__` so they grep cleanly
|
|
48
|
+
* and never collide with real code paths.
|
|
49
|
+
*/
|
|
50
|
+
export declare function substituteDriveShimPlaceholders(params: {
|
|
51
|
+
panelUrl: string;
|
|
52
|
+
token: string;
|
|
53
|
+
instanceId: string;
|
|
54
|
+
}): string;
|