mirror of
https://github.com/rohitg00/agentmemory.git
synced 2026-09-14 20:16:33 +08:00
bc64107791
Three concerns surfaced when auditing PRs merged since v0.9.21: 1) Graph parser regex from #494 was correct for self-closing tags ONLY when they're the only entity in the document. With a self-closing entity followed by an explicit-close entity, the greedy `[^>]*` ate the trailing `/` of the self-close, the alternation fell through to the explicit-close branch, and `[\s\S]*?` ran ahead to the *next* `</entity>` — merging two entity declarations into one match and silently dropping a node. Switch to lazy `[^>]*?` so the self-closing alternation gets first chance. Test from #494 (which was failing on main but I didn't notice) now passes. 2) #386 shipped `${AGENTMEMORY_URL}` / `${AGENTMEMORY_SECRET}` placeholders in plugin/.mcp.json. Claude Code and Cursor expand those at MCP launch time; some hosts pass the literal string through. A truthy literal `"${AGENTMEMORY_URL}"` defeats the existing `|| DEFAULT_URL` fallback and would have the shim POST to `${AGENTMEMORY_URL}/agentmemory/...` (DNS failure). Add a defensive guard in src/mcp/rest-proxy.ts that strips any value of the form `${...}` so the fallback engages. Mirror in src/mcp/standalone.ts's mode-announce log line. 3) CHANGELOG entries for all PRs landed since v0.9.21 (#321, #325, #386, #454, #494, #526, #542, #560, #561, #562, #564, #567) plus the regex + env-guard hardening here. Validation: - npm test → 98 files, 1091 tests pass - npm pack → 142 files, fresh install clean, iii-sdk@0.11.2 pinned, plugin/ shipped with hooks/scripts/skills/opencode/ - New test file covers 8 placeholder cases (unset, empty, `${VAR}` literal, mismatched braces, real values with $, unclosed `${`, no-braces `$VAR`).
58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
import { describe, it, expect, afterEach, beforeEach } from "vitest";
|
|
import { resolveEnvOrEmpty } from "../src/mcp/rest-proxy.js";
|
|
|
|
const VAR = "AGENTMEMORY_TEST_URL";
|
|
|
|
describe("resolveEnvOrEmpty — guards against literal ${VAR} placeholders", () => {
|
|
let original: string | undefined;
|
|
|
|
beforeEach(() => {
|
|
original = process.env[VAR];
|
|
delete process.env[VAR];
|
|
});
|
|
|
|
afterEach(() => {
|
|
if (original === undefined) delete process.env[VAR];
|
|
else process.env[VAR] = original;
|
|
});
|
|
|
|
it("returns '' when env var is unset", () => {
|
|
expect(resolveEnvOrEmpty(VAR)).toBe("");
|
|
});
|
|
|
|
it("returns '' when env var is empty string", () => {
|
|
process.env[VAR] = "";
|
|
expect(resolveEnvOrEmpty(VAR)).toBe("");
|
|
});
|
|
|
|
it("returns '' when env var is literal ${VAR} placeholder", () => {
|
|
process.env[VAR] = "${AGENTMEMORY_TEST_URL}";
|
|
expect(resolveEnvOrEmpty(VAR)).toBe("");
|
|
});
|
|
|
|
it("returns '' when env var is a different literal placeholder", () => {
|
|
process.env[VAR] = "${SOME_OTHER_VAR}";
|
|
expect(resolveEnvOrEmpty(VAR)).toBe("");
|
|
});
|
|
|
|
it("preserves a real URL value", () => {
|
|
process.env[VAR] = "https://memory.prod.example/api";
|
|
expect(resolveEnvOrEmpty(VAR)).toBe("https://memory.prod.example/api");
|
|
});
|
|
|
|
it("preserves a real secret value that happens to contain a $ char", () => {
|
|
process.env[VAR] = "secret-with-$dollar";
|
|
expect(resolveEnvOrEmpty(VAR)).toBe("secret-with-$dollar");
|
|
});
|
|
|
|
it("does not treat ${ at start without matching } as placeholder", () => {
|
|
process.env[VAR] = "${unclosed";
|
|
expect(resolveEnvOrEmpty(VAR)).toBe("${unclosed");
|
|
});
|
|
|
|
it("does not treat $VAR (no braces) as placeholder", () => {
|
|
process.env[VAR] = "$AGENTMEMORY_URL";
|
|
expect(resolveEnvOrEmpty(VAR)).toBe("$AGENTMEMORY_URL");
|
|
});
|
|
});
|