mirror of
https://github.com/volcengine/OpenViking.git
synced 2026-09-30 17:28:07 +08:00
* feat(plugins): add Agent Plugins 1.0 portable package Add agent-plugins/, an Agent Plugins 1.0 conformant package (https://agent-plugins.org/specification) that any conforming client can load: plugin.json manifest, an openviking-memory skill teaching the hook-less recall + persist loop, and an mcp.json stdio entry running a stdio -> streamable-HTTP proxy that resolves credentials from OPENVIKING_* env -> ~/.openviking/ovcli.conf -> ~/.openviking/ov.conf, same as the ov CLI. servers/shared/* are generated copies of memory-plugin-shared/lib, wired into sync.mjs / sync.test.mjs TARGETS so they cannot drift silently. config.mjs / debug-log.mjs / mcp-proxy.mjs are adapted from claude-code-memory-plugin with the hook-tuning knobs dropped. plugin.test.mjs validates spec conformance (schema URLs and matching spec versions, name rules, closed manifest root, semver, skill frontmatter, referenced files staying inside the plugin root, node --check on all .mjs) and runs in CI via pr.yml. The skill treats tree/write/edit as optional, since they only exist on servers that carry #3936. Docs: docs/{en,zh}/agent-integrations/15-agent-plugins.md, registered in the VitePress sidebar and the integration overview tables, plus a link from the three root READMEs. The docs recommend the per-client plugin whenever the harness has hooks, with the shared installer one-liner. Based on #3994 by @ZaynJarvis. Co-Authored-By: Zayn Jarvis <zaynjarvis@gmail.com> * docs(agent-plugins): pluralize README title --------- Co-authored-by: Zayn Jarvis <zaynjarvis@gmail.com>
73 lines
2.7 KiB
JavaScript
73 lines
2.7 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* stdio -> streamable-HTTP MCP proxy for the OpenViking Agent Plugins 1.0 package.
|
|
*
|
|
* VENDORED (adapted) from examples/claude-code-memory-plugin/servers/mcp-proxy.mjs —
|
|
* keep in sync with that file. Only the import paths and doc comments differ;
|
|
* the proxy behavior is identical. The shared modules under ./shared/ are
|
|
* generated by `node examples/memory-plugin-shared/sync.mjs` (this directory is
|
|
* one of its TARGETS) — edit them in examples/memory-plugin-shared/lib, never here.
|
|
*
|
|
* A conforming Agent Plugins client starts this process as a local stdio MCP
|
|
* server (see ../mcp.json). The proxy reads the same OpenViking credential
|
|
* sources as the ov CLI (OPENVIKING_* env → ~/.openviking/ovcli.conf →
|
|
* ~/.openviking/ov.conf), forwards JSON-RPC requests to the server's /mcp
|
|
* endpoint, and keeps stdout protocol-clean.
|
|
*/
|
|
|
|
import { homedir } from "node:os";
|
|
import { join, resolve as resolvePath } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { loadConfig } from "./config.mjs";
|
|
import { createLogger } from "./debug-log.mjs";
|
|
import { createOpenVikingMcpProxy } from "./shared/mcp-proxy-core.mjs";
|
|
import { resolveEffectivePeerId } from "./shared/workspace-peer.mjs";
|
|
|
|
const DEFAULT_TIMEOUT_MS = 15000;
|
|
|
|
function trimSlash(value) {
|
|
return String(value || "").replace(/\/+$/, "");
|
|
}
|
|
|
|
function normalizePath(value) {
|
|
const raw = String(value || "").trim();
|
|
if (!raw) return "";
|
|
if (raw === "~") return homedir();
|
|
if (raw.startsWith("~/")) return resolvePath(join(homedir(), raw.slice(2)));
|
|
return resolvePath(raw);
|
|
}
|
|
|
|
function uniq(values) {
|
|
return [...new Set(values.filter(Boolean))];
|
|
}
|
|
|
|
function readProxyConfig() {
|
|
const cfg = loadConfig();
|
|
const effectivePeer = resolveEffectivePeerId({ cfg, cwd: process.cwd() });
|
|
return {
|
|
mcpUrl: `${trimSlash(cfg.baseUrl)}/mcp`,
|
|
apiKey: cfg.apiKey || "",
|
|
account: cfg.accountId || "",
|
|
user: cfg.userId || "",
|
|
peerId: effectivePeer.peerId,
|
|
userAgent: cfg.userAgent || "",
|
|
timeoutMs: Math.max(1000, Number(cfg.timeoutMs) || DEFAULT_TIMEOUT_MS),
|
|
debug: cfg.debug === true,
|
|
debugLogPath: cfg.debugLogPath,
|
|
credentialSource: cfg.configPath?.endsWith("ovcli.conf") ? "ovcli" : "auto",
|
|
credentialPath: cfg.configPath || "",
|
|
watchedPaths: uniq([
|
|
cfg.configPath,
|
|
normalizePath(process.env.OPENVIKING_CLI_CONFIG_FILE),
|
|
normalizePath(process.env.OPENVIKING_CONFIG_FILE),
|
|
join(homedir(), ".openviking", "ovcli.conf"),
|
|
join(homedir(), ".openviking", "ov.conf"),
|
|
]),
|
|
};
|
|
}
|
|
|
|
if (process.argv[1] && fileURLToPath(import.meta.url) === resolvePath(process.argv[1])) {
|
|
createOpenVikingMcpProxy({ readConfig: readProxyConfig, loggerFactory: createLogger }).start();
|
|
}
|