@remnic/plugin-codex 9.51.0 → 9.52.0
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/.codex-plugin/plugin.json +1 -1
- package/README.md +5 -5
- package/hooks/bin/remnic-codex-hook.test.cjs +74 -16
- package/hooks/hooks.json +5 -5
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remnic",
|
|
3
3
|
"description": "Universal memory for AI agents — automatic recall, observation, and cross-agent knowledge sharing",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.52.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Joshua Warren",
|
|
7
7
|
"url": "https://github.com/joshuaswarren"
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ The package is **data + one small runtime materializer** (no runtime JS beyond t
|
|
|
31
31
|
| File / dir | Purpose |
|
|
32
32
|
|---|---|
|
|
33
33
|
| `.codex-plugin/plugin.json` | Plugin manifest |
|
|
34
|
-
| `hooks/hooks.json` + `hooks/bin/remnic-codex-hook.{cjs,sh,ps1}` | Codex session
|
|
34
|
+
| `hooks/hooks.json` + `hooks/bin/remnic-codex-hook.{cjs,sh,ps1}` | Codex session hooks for recall, observe, session end, and pre-compact LCM flush. `hooks.json` invokes the POSIX launcher through `sh`, so hooks still run when an install path does not preserve its executable mode. Windows uses the PowerShell launcher. |
|
|
35
35
|
| `skills/` | `remnic-recall`, `remnic-remember`, `remnic-search`, `remnic-status`, `remnic-entities`, `remnic-memory-workflow` — invocable from Codex chats |
|
|
36
36
|
| `memories_extensions/remnic/` | Codex phase-2 consolidation instructions — tells the Codex compactor sub-agent to treat Remnic's on-disk Markdown as an authoritative local memory source when it builds `MEMORY.md`. Local-only (no MCP, no network); runtime recall/observe still flow through the hooks above. |
|
|
37
37
|
| `.mcp.json` | MCP server config pointing Codex at `http://localhost:4318/mcp` |
|
|
@@ -132,10 +132,10 @@ the foreground path reads it.
|
|
|
132
132
|
|
|
133
133
|
Codex does not run non-managed command hooks until a human reviews and trusts
|
|
134
134
|
them. The first time these hooks are enabled, Codex prints a startup warning
|
|
135
|
-
directing you to run `/hooks` in the CLI
|
|
136
|
-
(SessionStart
|
|
137
|
-
records trust against the current hook hash, so updates
|
|
138
|
-
|
|
135
|
+
directing you to run `/hooks` in the CLI. Review the five Remnic entries
|
|
136
|
+
(SessionStart, PostToolUse, UserPromptSubmit, Stop, and PreCompact), then
|
|
137
|
+
approve them. Codex records trust against the current hook hash, so updates
|
|
138
|
+
to `hooks.json` will trigger a new review.
|
|
139
139
|
|
|
140
140
|
For fleet / headless automation there is no non-interactive trust CLI today;
|
|
141
141
|
pick one of:
|
|
@@ -351,26 +351,25 @@ test("unknown event fails open with continue", async () => {
|
|
|
351
351
|
|
|
352
352
|
// ── #1443 review fixes ──────────────────────────────────────────────────────
|
|
353
353
|
|
|
354
|
-
|
|
354
|
+
const POSIX_HOOK_EVENTS = Object.freeze({
|
|
355
|
+
SessionStart: "session-start",
|
|
356
|
+
PostToolUse: "post-tool-observe",
|
|
357
|
+
UserPromptSubmit: "user-prompt-recall",
|
|
358
|
+
Stop: "session-end",
|
|
359
|
+
PreCompact: "pre-compact",
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
test("hooks.json: every POSIX event invokes the correct launcher event through sh", () => {
|
|
355
363
|
const cfg = JSON.parse(
|
|
356
364
|
fs.readFileSync(path.join(__dirname, "..", "hooks.json"), "utf8"),
|
|
357
365
|
);
|
|
358
|
-
for (const event
|
|
366
|
+
for (const [event, runnerEvent] of Object.entries(POSIX_HOOK_EVENTS)) {
|
|
359
367
|
for (const matcher of cfg.hooks[event]) {
|
|
360
368
|
for (const hook of matcher.hooks) {
|
|
361
|
-
|
|
362
|
-
// substitutes ${PLUGIN_ROOT} (openai/codex discovery.rs + command_runner.rs),
|
|
363
|
-
// so the path must be PLUGIN_ROOT-relative AND quoted — an unquoted path
|
|
364
|
-
// would word-split on a plugin root containing spaces (e.g.
|
|
365
|
-
// C:\Users\Jane Doe).
|
|
366
|
-
assert.ok(
|
|
367
|
-
hook.command.startsWith('"${PLUGIN_ROOT}/hooks/bin/'),
|
|
368
|
-
`${event}.command must resolve via a quoted \${PLUGIN_ROOT}, got: ${hook.command}`,
|
|
369
|
-
);
|
|
370
|
-
assert.match(
|
|
369
|
+
assert.equal(
|
|
371
370
|
hook.command,
|
|
372
|
-
|
|
373
|
-
`${event}.command
|
|
371
|
+
`sh "\${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh" ${runnerEvent}`,
|
|
372
|
+
`${event}.command must invoke the matching runner event through sh`,
|
|
374
373
|
);
|
|
375
374
|
assert.ok(hook.commandWindows, `${event} must declare commandWindows`);
|
|
376
375
|
assert.match(
|
|
@@ -378,8 +377,6 @@ test("hooks.json: every event resolves via ${PLUGIN_ROOT} and uses powershell (#
|
|
|
378
377
|
/-File "\$\{PLUGIN_ROOT\}\\hooks\\bin\\remnic-codex-hook\.ps1"\s/,
|
|
379
378
|
`${event}.commandWindows must pass a quoted \${PLUGIN_ROOT} -File path`,
|
|
380
379
|
);
|
|
381
|
-
// Use `powershell` not `pwsh` so stock Windows 10/11 works without
|
|
382
|
-
// PowerShell 7 installed (#1443 review).
|
|
383
380
|
assert.match(
|
|
384
381
|
hook.commandWindows,
|
|
385
382
|
/^powershell\b/,
|
|
@@ -390,6 +387,67 @@ test("hooks.json: every event resolves via ${PLUGIN_ROOT} and uses powershell (#
|
|
|
390
387
|
}
|
|
391
388
|
});
|
|
392
389
|
|
|
390
|
+
test(
|
|
391
|
+
"hooks.json: every POSIX command runs a packaged launcher without executable mode",
|
|
392
|
+
{ skip: process.platform === "win32" },
|
|
393
|
+
async () => {
|
|
394
|
+
const home = mkHome();
|
|
395
|
+
try {
|
|
396
|
+
const pluginRoot = path.join(home, "plugin root");
|
|
397
|
+
const binDir = path.join(pluginRoot, "hooks", "bin");
|
|
398
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
399
|
+
for (const file of ["remnic-codex-hook.sh", "remnic-codex-hook.cjs"]) {
|
|
400
|
+
fs.copyFileSync(path.join(__dirname, file), path.join(binDir, file));
|
|
401
|
+
}
|
|
402
|
+
fs.chmodSync(path.join(binDir, "remnic-codex-hook.sh"), 0o644);
|
|
403
|
+
|
|
404
|
+
const cfg = JSON.parse(
|
|
405
|
+
fs.readFileSync(path.join(__dirname, "..", "hooks.json"), "utf8"),
|
|
406
|
+
);
|
|
407
|
+
const runCommand = (command, sessionId) => new Promise((resolve, reject) => {
|
|
408
|
+
const child = spawn("sh", ["-c", command], {
|
|
409
|
+
env: {
|
|
410
|
+
...process.env,
|
|
411
|
+
HOME: home,
|
|
412
|
+
USERPROFILE: home,
|
|
413
|
+
XDG_STATE_HOME: path.join(home, "state"),
|
|
414
|
+
PLUGIN_ROOT: pluginRoot,
|
|
415
|
+
REMNIC_CODEX_MATERIALIZE: "0",
|
|
416
|
+
OPENCLAW_REMNIC_ACCESS_TOKEN: "",
|
|
417
|
+
OPENCLAW_ENGRAM_ACCESS_TOKEN: "",
|
|
418
|
+
REMNIC_AUTH_TOKEN: "",
|
|
419
|
+
ENGRAM_AUTH_TOKEN: "",
|
|
420
|
+
REMNIC_HOOK_TOKEN: "",
|
|
421
|
+
REMNIC_DAEMON_URL: "",
|
|
422
|
+
ENGRAM_DAEMON_URL: "",
|
|
423
|
+
},
|
|
424
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
425
|
+
});
|
|
426
|
+
let stdout = "";
|
|
427
|
+
let stderr = "";
|
|
428
|
+
child.stdout.on("data", (data) => {
|
|
429
|
+
stdout += data;
|
|
430
|
+
});
|
|
431
|
+
child.stderr.on("data", (data) => {
|
|
432
|
+
stderr += data;
|
|
433
|
+
});
|
|
434
|
+
child.stdin.end(JSON.stringify({ session_id: sessionId, cwd: home }));
|
|
435
|
+
child.on("error", reject);
|
|
436
|
+
child.on("close", (exitCode) => resolve({ exitCode, stdout, stderr }));
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
for (const [event, runnerEvent] of Object.entries(POSIX_HOOK_EVENTS)) {
|
|
440
|
+
const command = cfg.hooks[event][0].hooks[0].command;
|
|
441
|
+
const result = await runCommand(command, `${runnerEvent}-mode-test`);
|
|
442
|
+
assert.equal(result.exitCode, 0, `${event}: ${result.stderr}`);
|
|
443
|
+
assert.equal(JSON.parse(result.stdout).continue, true, event);
|
|
444
|
+
}
|
|
445
|
+
} finally {
|
|
446
|
+
fs.rmSync(home, { recursive: true, force: true });
|
|
447
|
+
}
|
|
448
|
+
},
|
|
449
|
+
);
|
|
450
|
+
|
|
393
451
|
test("runner source: remnic→engram fallthrough is PATH-gated and Windows-shim aware (#1443 review)", () => {
|
|
394
452
|
const src = fs.readFileSync(path.join(__dirname, "remnic-codex-hook.cjs"), "utf8");
|
|
395
453
|
// Both the migration and daemon-start loops pre-check PATH with onPath()
|
package/hooks/hooks.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "\"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" session-start",
|
|
9
|
+
"command": "sh \"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" session-start",
|
|
10
10
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\hooks\\bin\\remnic-codex-hook.ps1\" session-start",
|
|
11
11
|
"timeout": 45
|
|
12
12
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"hooks": [
|
|
20
20
|
{
|
|
21
21
|
"type": "command",
|
|
22
|
-
"command": "\"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" post-tool-observe",
|
|
22
|
+
"command": "sh \"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" post-tool-observe",
|
|
23
23
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\hooks\\bin\\remnic-codex-hook.ps1\" post-tool-observe",
|
|
24
24
|
"timeout": 10
|
|
25
25
|
}
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"hooks": [
|
|
33
33
|
{
|
|
34
34
|
"type": "command",
|
|
35
|
-
"command": "\"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" user-prompt-recall",
|
|
35
|
+
"command": "sh \"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" user-prompt-recall",
|
|
36
36
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\hooks\\bin\\remnic-codex-hook.ps1\" user-prompt-recall",
|
|
37
37
|
"timeout": 20
|
|
38
38
|
}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"hooks": [
|
|
46
46
|
{
|
|
47
47
|
"type": "command",
|
|
48
|
-
"command": "\"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" session-end",
|
|
48
|
+
"command": "sh \"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" session-end",
|
|
49
49
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\hooks\\bin\\remnic-codex-hook.ps1\" session-end",
|
|
50
50
|
"timeout": 30
|
|
51
51
|
}
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"hooks": [
|
|
59
59
|
{
|
|
60
60
|
"type": "command",
|
|
61
|
-
"command": "\"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" pre-compact",
|
|
61
|
+
"command": "sh \"${PLUGIN_ROOT}/hooks/bin/remnic-codex-hook.sh\" pre-compact",
|
|
62
62
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\hooks\\bin\\remnic-codex-hook.ps1\" pre-compact",
|
|
63
63
|
"timeout": 90
|
|
64
64
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/plugin-codex",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.52.0",
|
|
4
4
|
"description": "Remnic memory plugin for Codex CLI — hooks, skills, MCP integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,6 +30,6 @@
|
|
|
30
30
|
".mcp.json"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@remnic/core": "^9.
|
|
33
|
+
"@remnic/core": "^9.52.0"
|
|
34
34
|
}
|
|
35
35
|
}
|