@remnic/bench 9.6.18 → 9.6.19

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 CHANGED
@@ -16,6 +16,71 @@ pnpm add @remnic/bench
16
16
 
17
17
  The CLI loads `@remnic/bench` via a computed-specifier dynamic import. If it's not installed, `remnic bench *` prints a clear install hint; the rest of the CLI keeps working.
18
18
 
19
+ ## OpenAI Build Week: five-minute MemCorrect path
20
+
21
+ MemCorrect scores correction uptake and stale-memory harm through the same
22
+ `remnic bench` surface. This keyless smoke path uses the packaged stdio MCP
23
+ server, so it tests the actual MCP adapter rather than the in-memory baseline:
24
+
25
+ ```bash
26
+ remnic bench run --quick memcorrect-v1 --adapter mcp --mcp-demo
27
+ remnic bench runs list
28
+ remnic bench export <run-id> --format html --output ./memcorrect-report.html
29
+ ```
30
+
31
+ The run itself is deterministic and offline. It needs no dataset or API key.
32
+ The generated HTML is self-contained and includes the correction ledger,
33
+ per-dimension evidence, task drill-down, and reproducibility provenance. Treat
34
+ the packaged demo as a transport and product smoke test, not a publishable
35
+ backend-quality result.
36
+
37
+ From a source checkout, build the optional companion before invoking the CLI:
38
+
39
+ ```bash
40
+ pnpm install --frozen-lockfile
41
+ pnpm --filter @remnic/bench build
42
+ pnpm exec tsx packages/remnic-cli/src/index.ts bench run \
43
+ --quick memcorrect-v1 --adapter mcp --mcp-demo
44
+ ```
45
+
46
+ An external MCP server can replace `--mcp-demo` with exactly one of:
47
+
48
+ ```bash
49
+ # stdio
50
+ remnic bench run --quick memcorrect-v1 --adapter mcp \
51
+ --mcp-command memory-server --mcp-args '["--stdio"]' \
52
+ --mcp-tool-map '{"store":"memory_store","recall":"memory_recall","correct":"memory_correct","reset":"memory_reset"}'
53
+
54
+ # Streamable HTTP; set REMNIC_BENCH_MCP_BEARER_TOKEN if authentication is required
55
+ remnic bench run --quick memcorrect-v1 --adapter mcp \
56
+ --mcp-url https://memory.example/mcp \
57
+ --mcp-tool-map '{"store":"memory_store","recall":"memory_recall","correct":"memory_correct","reset":"memory_reset"}'
58
+ ```
59
+
60
+ Tool names alone may not be enough for a non-canonical server. The mapping can
61
+ also describe argument semantics; see `remnic bench --help` for the current CLI
62
+ surface and use preflight failures as conformance errors rather than empty
63
+ recall scores.
64
+
65
+ GPT-5.6 judging is explicit and uses the OpenAI Responses API:
66
+
67
+ ```bash
68
+ export OPENAI_API_KEY=...
69
+ remnic bench run --quick memcorrect-v1 --adapter mcp --mcp-demo \
70
+ --judge-provider openai --judge-model gpt-5.6
71
+ ```
72
+
73
+ Codex built and adversarially reviewed the Build Week adapter, Responses
74
+ provider, and report card. The underlying Remnic engine and original benchmark
75
+ harness are prior work. The evidence ledger, credential-dependent frontier-run
76
+ placeholder, and release status live in the root [`HACKATHON.md`](../../HACKATHON.md).
77
+
78
+ The claimed judge path requires Node.js 22.12+. It is verified from source and
79
+ from packed tarballs installed into a clean global prefix on Linux; macOS is
80
+ supported with the same Node CLI but still needs a release-install receipt.
81
+ Windows judges should use WSL2; native Windows is not currently claimed as
82
+ Build Week-verified.
83
+
19
84
  ## What it does
20
85
 
21
86
  - **Benchmark runners** for a growing set of memory-oriented evals: `longmemeval`, `locomo`, `memory-arena`, `amemgym`, `ama-bench`, plus a lightweight smoke fixture.
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/demo/mcp-memory-server.ts
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { z } from "zod";
7
+
8
+ // src/demo/mcp-memory-correction.ts
9
+ function parseSyntheticCorrection(content) {
10
+ const trimmed = content.trim();
11
+ const patterns = [
12
+ {
13
+ expression: /^Correction: replace (.+) with (.+)\.$/s,
14
+ oldValueIndex: 1,
15
+ newValueIndex: 2
16
+ },
17
+ {
18
+ expression: /^Correction: my .+? record saying (.+?) is wrong\. It is now (.+)\.$/s,
19
+ oldValueIndex: 1,
20
+ newValueIndex: 2
21
+ },
22
+ {
23
+ expression: /^Oh by the way, we switched .+? from (.+?) to (.+) last month\.$/s,
24
+ oldValueIndex: 1,
25
+ newValueIndex: 2
26
+ },
27
+ {
28
+ expression: /^For this project, .+? is (.+?) now, not (.+)\.$/s,
29
+ oldValueIndex: 2,
30
+ newValueIndex: 1
31
+ },
32
+ {
33
+ expression: /^Update: .+? is (.+?) going forward instead of (.+)\.$/s,
34
+ oldValueIndex: 2,
35
+ newValueIndex: 1
36
+ }
37
+ ];
38
+ for (const pattern of patterns) {
39
+ const match = pattern.expression.exec(trimmed);
40
+ const oldValue = match?.[pattern.oldValueIndex];
41
+ const newValue = match?.[pattern.newValueIndex];
42
+ if (oldValue !== void 0 && newValue !== void 0) return { oldValue, newValue };
43
+ }
44
+ return void 0;
45
+ }
46
+
47
+ // src/demo/mcp-memory-server.ts
48
+ var memories = /* @__PURE__ */ new Map();
49
+ var server = new McpServer({
50
+ name: "remnic-bench-demo-memory",
51
+ version: "1.0.0"
52
+ });
53
+ server.registerTool(
54
+ "store_memory",
55
+ {
56
+ description: "Store one synthetic benchmark memory in an isolated session.",
57
+ inputSchema: {
58
+ namespace: z.string(),
59
+ sessionId: z.string(),
60
+ content: z.string(),
61
+ role: z.string().optional(),
62
+ timestamp: z.string().optional()
63
+ }
64
+ },
65
+ async ({ sessionId, content }) => {
66
+ memories.set(sessionId, [...memories.get(sessionId) ?? [], content]);
67
+ return { content: [{ type: "text", text: JSON.stringify({ stored: true }) }] };
68
+ }
69
+ );
70
+ server.registerTool(
71
+ "search_memory",
72
+ {
73
+ description: "Recall memories from one isolated benchmark session.",
74
+ inputSchema: {
75
+ namespace: z.string(),
76
+ sessionId: z.string(),
77
+ query: z.string(),
78
+ limit: z.number().int().positive().optional()
79
+ }
80
+ },
81
+ async ({ sessionId, limit }) => ({
82
+ content: [
83
+ {
84
+ type: "text",
85
+ text: JSON.stringify({ memories: (memories.get(sessionId) ?? []).slice(0, limit) })
86
+ }
87
+ ]
88
+ })
89
+ );
90
+ server.registerTool(
91
+ "correct_memory",
92
+ {
93
+ description: "Apply a synthetic natural-language correction to one session.",
94
+ inputSchema: {
95
+ namespace: z.string(),
96
+ sessionId: z.string(),
97
+ content: z.string(),
98
+ timestamp: z.string().optional()
99
+ }
100
+ },
101
+ async ({ sessionId, content }) => {
102
+ const replacement = parseSyntheticCorrection(content);
103
+ const current = memories.get(sessionId) ?? [];
104
+ if (replacement) {
105
+ memories.set(
106
+ sessionId,
107
+ current.map((item) => item.replaceAll(replacement.oldValue, replacement.newValue))
108
+ );
109
+ } else {
110
+ memories.set(sessionId, [...current, content]);
111
+ }
112
+ return { content: [{ type: "text", text: JSON.stringify({ applied: true }) }] };
113
+ }
114
+ );
115
+ server.registerTool(
116
+ "delete_memory",
117
+ {
118
+ description: "Delete only the requested isolated benchmark session.",
119
+ inputSchema: {
120
+ namespace: z.string(),
121
+ sessionId: z.string()
122
+ }
123
+ },
124
+ async ({ sessionId }) => {
125
+ memories.delete(sessionId);
126
+ return { content: [{ type: "text", text: JSON.stringify({ deleted: true }) }] };
127
+ }
128
+ );
129
+ await server.connect(new StdioServerTransport());