@openviking/dsh-memory-plugin 0.3.0 → 0.4.3
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/README.md +86 -22
- package/capture.mjs +14 -0
- package/client.mjs +6 -155
- package/config.mjs +36 -166
- package/index.mjs +17 -4
- package/mcp-env.mjs +33 -0
- package/mcp.mjs +2 -33
- package/package.json +9 -6
- package/runtime.mjs +115 -28
- package/servers/mcp-proxy.mjs +13 -19
- package/shared/capture-utils.mjs +146 -7
- package/shared/config-schema.mjs +359 -0
- package/shared/credentials.mjs +238 -102
- package/shared/input-filters.mjs +219 -0
- package/shared/mcp-proxy-config.mjs +171 -9
- package/shared/mcp-proxy-core.mjs +35 -15
- package/shared/ov-http.mjs +112 -0
- package/shared/pending-queue.mjs +41 -5
- package/shared/plugin-config.mjs +239 -29
- package/shared/recall-compress-core.mjs +17 -6
- package/shared/recall-core.mjs +128 -10
- package/shared/uri-guard.mjs +173 -1
- package/shared/workspace-config.mjs +433 -0
- package/shared/workspace-identity.mjs +334 -0
- package/shared/workspace-peer.mjs +189 -8
- package/shared/workspace-registry.mjs +87 -0
- package/skills/openviking-memory/SKILL.md +19 -0
- package/skills.mjs +3 -4
- package/uri-guard.mjs +20 -10
- package/shared/setup-wizard.mjs +0 -114
package/uri-guard.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { boundContextSummary } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
import { pluginMessage } from "./capture.mjs";
|
|
1
3
|
import { MCP_SERVER_NAME } from "./config.mjs";
|
|
2
|
-
import {
|
|
4
|
+
import { evaluateUriGuard, evaluateUriNotice } from "./shared/uri-guard.mjs";
|
|
3
5
|
|
|
4
6
|
/** Model-facing name of a bridged OpenViking MCP tool. */
|
|
5
7
|
const mcp = rawName => `mcp__${MCP_SERVER_NAME}__${rawName}`;
|
|
@@ -37,16 +39,24 @@ const GUARDED_TOOLS = {
|
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
export async function guardVikingUri(exec, next) {
|
|
40
|
-
const
|
|
41
|
-
if (!
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const decision = evaluateUriGuard(exec.name, exec.arguments, { hints: GUARDED_TOOLS });
|
|
43
|
+
if (!decision) return next();
|
|
44
|
+
return { kind: "deny", reason: decision.reason };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Delegates first so a later listener's block or content replacement survives;
|
|
48
|
+
// the notice only rides along as one more context.
|
|
49
|
+
export async function noticeVikingUri(exec, _result, next) {
|
|
50
|
+
const notice = evaluateUriNotice(exec.name, exec.arguments, { hints: GUARDED_TOOLS });
|
|
51
|
+
if (!notice) return next();
|
|
52
|
+
const decision = await next();
|
|
53
|
+
const context = pluginMessage(notice.reason, {
|
|
54
|
+
form: "notice",
|
|
55
|
+
summary: boundContextSummary(`OpenViking URI guard: shell command contains ${notice.uri}`),
|
|
56
|
+
});
|
|
44
57
|
return {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
tool: hint.tool,
|
|
48
|
-
example: hint.example(uri, exec.arguments),
|
|
49
|
-
}),
|
|
58
|
+
...decision,
|
|
59
|
+
additionalContexts: [...(decision.additionalContexts ?? []), context],
|
|
50
60
|
};
|
|
51
61
|
}
|
|
52
62
|
|
package/shared/setup-wizard.mjs
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
// GENERATED FROM examples/memory-plugin-shared/lib. DO NOT EDIT.
|
|
2
|
-
/**
|
|
3
|
-
* Interactive ovcli.conf setup wizard shared by the OpenViking memory plugins.
|
|
4
|
-
*
|
|
5
|
-
* Lets a pure-marketplace install (no installer script) configure the server
|
|
6
|
-
* URL and API key that both the lifecycle hooks and the stdio MCP proxy read:
|
|
7
|
-
*
|
|
8
|
-
* node <plugin>/scripts/setup.mjs
|
|
9
|
-
*
|
|
10
|
-
* Conventions: show current values, keep existing secrets on empty input,
|
|
11
|
-
* merge-write (never drop unknown fields), back up the previous file, 0600.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "node:fs";
|
|
15
|
-
import { dirname } from "node:path";
|
|
16
|
-
import { createInterface } from "node:readline/promises";
|
|
17
|
-
import { loadCredentialFiles } from "./credentials.mjs";
|
|
18
|
-
|
|
19
|
-
const CLOUD_URL = "https://api.vikingdb.cn-beijing.volces.com/openviking";
|
|
20
|
-
const LOCAL_URL = "http://127.0.0.1:1933";
|
|
21
|
-
|
|
22
|
-
function maskSecret(value) {
|
|
23
|
-
const s = String(value || "");
|
|
24
|
-
if (!s) return "(not set)";
|
|
25
|
-
if (s.length <= 8) return "****";
|
|
26
|
-
return `${s.slice(0, 4)}…${s.slice(-4)} (${s.length} chars)`;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function readJsonSafe(path) {
|
|
30
|
-
try {
|
|
31
|
-
return JSON.parse(readFileSync(path, "utf-8"));
|
|
32
|
-
} catch {
|
|
33
|
-
return {};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export async function runSetupWizard({
|
|
38
|
-
input = process.stdin,
|
|
39
|
-
output = process.stdout,
|
|
40
|
-
env = process.env,
|
|
41
|
-
} = {}) {
|
|
42
|
-
// cliPath is empty until the file exists; first-run writes go to the candidate
|
|
43
|
-
// path (OPENVIKING_CLI_CONFIG_FILE, else ~/.openviking/ovcli.conf).
|
|
44
|
-
const { cliPath, cliPathCandidate } = loadCredentialFiles(env);
|
|
45
|
-
const targetPath = cliPath || cliPathCandidate;
|
|
46
|
-
const current = readJsonSafe(targetPath);
|
|
47
|
-
const rl = createInterface({ input, output });
|
|
48
|
-
const say = (line = "") => output.write(`${line}\n`);
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
say("OpenViking memory plugin setup");
|
|
52
|
-
say(`Config file: ${targetPath}`);
|
|
53
|
-
say("");
|
|
54
|
-
say("Current values:");
|
|
55
|
-
say(` url: ${current.url || "(not set)"}`);
|
|
56
|
-
say(` api_key: ${maskSecret(current.api_key)}`);
|
|
57
|
-
if (current.account) say(` account: ${current.account}`);
|
|
58
|
-
if (current.user) say(` user: ${current.user}`);
|
|
59
|
-
say("");
|
|
60
|
-
|
|
61
|
-
const defaultUrl = current.url || LOCAL_URL;
|
|
62
|
-
say("Where do you connect to OpenViking?");
|
|
63
|
-
say(` 1) Self-hosted / local [${LOCAL_URL}]`);
|
|
64
|
-
say(` 2) Volcengine OpenViking Cloud [${CLOUD_URL}]`);
|
|
65
|
-
say(` 3) Custom URL / keep current [${defaultUrl}]`);
|
|
66
|
-
const mode = (await rl.question("Choice [1/2/3, default 3]: ")).trim();
|
|
67
|
-
let url = defaultUrl;
|
|
68
|
-
if (mode === "1") {
|
|
69
|
-
url = LOCAL_URL;
|
|
70
|
-
} else if (mode === "2") {
|
|
71
|
-
url = CLOUD_URL;
|
|
72
|
-
} else {
|
|
73
|
-
const answer = (await rl.question(`Server URL [${defaultUrl}]: `)).trim();
|
|
74
|
-
if (answer) url = answer;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const keyPrompt = current.api_key
|
|
78
|
-
? `API key [enter = keep ${maskSecret(current.api_key)}, '-' = clear]: `
|
|
79
|
-
: "API key (leave empty for unauthenticated local mode): ";
|
|
80
|
-
const keyAnswer = await rl.question(keyPrompt);
|
|
81
|
-
let apiKey = current.api_key || "";
|
|
82
|
-
if (keyAnswer === "-") apiKey = "";
|
|
83
|
-
else if (keyAnswer.trim()) apiKey = keyAnswer.trim();
|
|
84
|
-
else if (!current.api_key) apiKey = "";
|
|
85
|
-
|
|
86
|
-
const next = { ...current, url, api_key: apiKey };
|
|
87
|
-
|
|
88
|
-
say("");
|
|
89
|
-
say("Changes:");
|
|
90
|
-
say(` url: ${current.url || "(not set)"} -> ${next.url}`);
|
|
91
|
-
say(` api_key: ${maskSecret(current.api_key)} -> ${maskSecret(next.api_key)}`);
|
|
92
|
-
const confirm = (await rl.question("Write config? [Y/n] ")).trim().toLowerCase();
|
|
93
|
-
if (confirm === "n" || confirm === "no") {
|
|
94
|
-
say("Aborted; nothing written.");
|
|
95
|
-
return { written: false, path: targetPath };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
mkdirSync(dirname(targetPath), { recursive: true });
|
|
99
|
-
if (existsSync(targetPath)) {
|
|
100
|
-
copyFileSync(targetPath, `${targetPath}.bak.${Date.now()}`);
|
|
101
|
-
}
|
|
102
|
-
writeFileSync(targetPath, `${JSON.stringify(next, null, 2)}\n`, { mode: 0o600 });
|
|
103
|
-
try {
|
|
104
|
-
chmodSync(targetPath, 0o600);
|
|
105
|
-
} catch {
|
|
106
|
-
/* best effort on platforms without chmod semantics */
|
|
107
|
-
}
|
|
108
|
-
say(`Written: ${targetPath}`);
|
|
109
|
-
say("The stdio MCP proxy and hooks pick this up on the next harness start.");
|
|
110
|
-
return { written: true, path: targetPath };
|
|
111
|
-
} finally {
|
|
112
|
-
rl.close();
|
|
113
|
-
}
|
|
114
|
-
}
|