Skip to content

Commit 08d781d

Browse files
committed
chore(release): v0.9.20 — hotfix Codex Stop revert (#501)
v0.9.19 shipped #495 which chained session-end.mjs after stop.mjs on the Codex Stop hook. Field-testing surfaced the underlying issue: Codex fires Stop multiple times within a single conversation (once per assistant turn), so chaining session-end marked sessions as completed while later observations were still arriving. #501 reverts the chain. Stop returns to summarize-only behavior. The SessionEnd-shaped solution (a dedicated terminate event the agent sends only once on real session end) tracks at #493. Files bumped (9): - package.json, packages/mcp/package.json - plugin/.claude-plugin/plugin.json, plugin/.codex-plugin/plugin.json - src/version.ts, src/types.ts - src/functions/export-import.ts - test/export-import.test.ts - CHANGELOG.md 1034/1034 tests pass.
1 parent a953cad commit 08d781d

10 files changed

Lines changed: 120 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66

77
## [Unreleased]
88

9+
## [0.9.20] — 2026-05-18
10+
11+
Hotfix: revert the Codex Stop → session-end chain shipped in v0.9.19.
12+
13+
### Fixed
14+
15+
- **Revert Codex Stop hook session-end chain** ([PR #501](https://github.com/rohitg00/agentmemory/pull/501) by [@Rex57](https://github.com/Rex57), reverts v0.9.19's [#495](https://github.com/rohitg00/agentmemory/pull/495), re-opens [#493](https://github.com/rohitg00/agentmemory/issues/493)). Post-merge field-testing surfaced the underlying issue: Codex `Stop` fires before the overall conversation is truly finished — multiple Stops bracket each assistant turn within one session. Chaining `session-end.mjs` from Stop marked sessions completed too early, with later observations still arriving against an `endedAt`-stamped record. Restored to summarize-only Stop; the SessionEnd-shaped solution stays open as [#493](https://github.com/rohitg00/agentmemory/issues/493).
16+
17+
[0.9.20]: https://github.com/rohitg00/agentmemory/compare/v0.9.19...v0.9.20
18+
919
## [0.9.19] — 2026-05-18
1020

1121
Feature + hardening wave. Sessions now link to the git commits they shipped (forward + reverse lookup, REST + MCP surfaces). OpenAI provider transport collapses into one shared module with auto-detected Azure URL style (legacy `/openai/deployments/<dep>` and v1 `/openai/v1` both supported). Graph retrieval switches from BFS to Dijkstra over the weighted edge graph. Codex Stop hook chains session-end. Plugin MCP server inherits `AGENTMEMORY_URL` / `AGENTMEMORY_SECRET` from the shell. Point fix routes the bundled iii-console installer around an upstream tag-prefix bug. 1007+ tests pass.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@agentmemory/agentmemory",
3-
"version": "0.9.19",
3+
"version": "0.9.20",
44
"description": "Persistent memory for AI coding agents, powered by iii-engine's three primitives",
55
"type": "module",
66
"main": "dist/index.mjs",

packages/mcp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@agentmemory/mcp",
3-
"version": "0.9.19",
3+
"version": "0.9.20",
44
"description": "Standalone MCP server for agentmemory — thin shim that re-exposes @agentmemory/agentmemory's MCP entrypoint",
55
"type": "module",
66
"bin": {

plugin/.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "agentmemory",
3-
"version": "0.9.19",
3+
"version": "0.9.20",
44
"description": "Persistent memory for AI coding agents -- captures tool usage, compresses via LLM, injects context into future sessions. 12 hooks, 51 MCP tools, 4 skills, real-time viewer.",
55
"author": {
66
"name": "Rohit Ghumare",

plugin/.codex-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "agentmemory",
3-
"version": "0.9.19",
3+
"version": "0.9.20",
44
"description": "Persistent memory for AI coding agents -- captures tool usage, compresses via LLM, injects context into future sessions. 6 hooks, 51 MCP tools, 4 skills, real-time viewer.",
55
"author": {
66
"name": "Rohit Ghumare",

plugin/scripts/post-commit.mjs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env node
2+
import { execFile } from "node:child_process";
3+
import { promisify } from "node:util";
4+
5+
//#region src/hooks/post-commit.ts
6+
const exec = promisify(execFile);
7+
function isSdkChildContext(payload) {
8+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
9+
if (!payload || typeof payload !== "object") return false;
10+
return payload.entrypoint === "sdk-ts";
11+
}
12+
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
13+
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
14+
const TIMEOUT_MS = 1500;
15+
function authHeaders() {
16+
const h = { "Content-Type": "application/json" };
17+
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
18+
return h;
19+
}
20+
async function git(args, cwd) {
21+
try {
22+
const { stdout } = await exec("git", args, {
23+
cwd,
24+
timeout: 1500
25+
});
26+
return stdout.trim();
27+
} catch {
28+
return null;
29+
}
30+
}
31+
async function main() {
32+
let input = "";
33+
for await (const chunk of process.stdin) input += chunk;
34+
let data = {};
35+
if (input.trim()) try {
36+
data = JSON.parse(input);
37+
} catch {}
38+
if (isSdkChildContext(data)) return;
39+
const cwd = data.cwd || process.env["AGENTMEMORY_CWD"] || process.cwd();
40+
const sessionId = data.session_id || process.env["AGENTMEMORY_SESSION_ID"] || void 0;
41+
const sha = process.env["AGENTMEMORY_COMMIT_SHA"] || await git(["rev-parse", "HEAD"], cwd);
42+
if (!sha) return;
43+
const branch = await git([
44+
"rev-parse",
45+
"--abbrev-ref",
46+
"HEAD"
47+
], cwd);
48+
const repo = await git([
49+
"config",
50+
"--get",
51+
"remote.origin.url"
52+
], cwd);
53+
const message = await git([
54+
"log",
55+
"-1",
56+
"--pretty=%B",
57+
sha
58+
], cwd);
59+
const author = await git([
60+
"log",
61+
"-1",
62+
"--pretty=%an <%ae>",
63+
sha
64+
], cwd);
65+
const authoredAt = await git([
66+
"log",
67+
"-1",
68+
"--pretty=%aI",
69+
sha
70+
], cwd);
71+
const filesRaw = await git([
72+
"diff-tree",
73+
"--no-commit-id",
74+
"--name-only",
75+
"-r",
76+
sha
77+
], cwd);
78+
const files = filesRaw ? filesRaw.split("\n").filter(Boolean) : void 0;
79+
const body = {
80+
sessionId,
81+
sha,
82+
branch: branch || void 0,
83+
repo: repo || void 0,
84+
message: message || void 0,
85+
author: author || void 0,
86+
authoredAt: authoredAt || void 0,
87+
files
88+
};
89+
try {
90+
await fetch(`${REST_URL}/agentmemory/session/commit`, {
91+
method: "POST",
92+
headers: authHeaders(),
93+
body: JSON.stringify(body),
94+
signal: AbortSignal.timeout(TIMEOUT_MS)
95+
});
96+
} catch {}
97+
}
98+
main();
99+
100+
//#endregion
101+
export { };
102+
//# sourceMappingURL=post-commit.mjs.map

src/functions/export-import.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export function registerExportImportFunction(sdk: ISdk, kv: StateKV): void {
176176
const strategy = data.strategy || "merge";
177177
const importData = data.exportData;
178178

179-
const supportedVersions = new Set(["0.3.0", "0.4.0", "0.5.0", "0.6.0", "0.6.1", "0.7.0", "0.7.2", "0.7.3", "0.7.4", "0.7.5", "0.7.6", "0.7.7", "0.7.9", "0.8.0", "0.8.1", "0.8.2", "0.8.3", "0.8.4", "0.8.5", "0.8.6", "0.8.7", "0.8.8", "0.8.9", "0.8.10", "0.8.11", "0.8.12", "0.8.13", "0.9.0", "0.9.1", "0.9.2", "0.9.3", "0.9.4", "0.9.5", "0.9.6", "0.9.7", "0.9.8", "0.9.9", "0.9.10", "0.9.11", "0.9.12", "0.9.13", "0.9.14", "0.9.15", "0.9.16", "0.9.17", "0.9.18", "0.9.19"]);
179+
const supportedVersions = new Set(["0.3.0", "0.4.0", "0.5.0", "0.6.0", "0.6.1", "0.7.0", "0.7.2", "0.7.3", "0.7.4", "0.7.5", "0.7.6", "0.7.7", "0.7.9", "0.8.0", "0.8.1", "0.8.2", "0.8.3", "0.8.4", "0.8.5", "0.8.6", "0.8.7", "0.8.8", "0.8.9", "0.8.10", "0.8.11", "0.8.12", "0.8.13", "0.9.0", "0.9.1", "0.9.2", "0.9.3", "0.9.4", "0.9.5", "0.9.6", "0.9.7", "0.9.8", "0.9.9", "0.9.10", "0.9.11", "0.9.12", "0.9.13", "0.9.14", "0.9.15", "0.9.16", "0.9.17", "0.9.18", "0.9.19", "0.9.20"]);
180180
if (!supportedVersions.has(importData.version)) {
181181
return {
182182
success: false,

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ export interface ExportPagination {
293293
}
294294

295295
export interface ExportData {
296-
version: "0.3.0" | "0.4.0" | "0.5.0" | "0.6.0" | "0.6.1" | "0.7.0" | "0.7.2" | "0.7.3" | "0.7.4" | "0.7.5" | "0.7.6" | "0.7.7" | "0.7.9" | "0.8.0" | "0.8.1" | "0.8.2" | "0.8.3" | "0.8.4" | "0.8.5" | "0.8.6" | "0.8.7" | "0.8.8" | "0.8.9" | "0.8.10" | "0.8.11" | "0.8.12" | "0.8.13" | "0.9.0" | "0.9.1" | "0.9.2" | "0.9.3" | "0.9.4" | "0.9.5" | "0.9.6" | "0.9.7" | "0.9.8" | "0.9.9" | "0.9.10" | "0.9.11" | "0.9.12" | "0.9.13" | "0.9.14" | "0.9.15" | "0.9.16" | "0.9.17" | "0.9.18" | "0.9.19";
296+
version: "0.3.0" | "0.4.0" | "0.5.0" | "0.6.0" | "0.6.1" | "0.7.0" | "0.7.2" | "0.7.3" | "0.7.4" | "0.7.5" | "0.7.6" | "0.7.7" | "0.7.9" | "0.8.0" | "0.8.1" | "0.8.2" | "0.8.3" | "0.8.4" | "0.8.5" | "0.8.6" | "0.8.7" | "0.8.8" | "0.8.9" | "0.8.10" | "0.8.11" | "0.8.12" | "0.8.13" | "0.9.0" | "0.9.1" | "0.9.2" | "0.9.3" | "0.9.4" | "0.9.5" | "0.9.6" | "0.9.7" | "0.9.8" | "0.9.9" | "0.9.10" | "0.9.11" | "0.9.12" | "0.9.13" | "0.9.14" | "0.9.15" | "0.9.16" | "0.9.17" | "0.9.18" | "0.9.19" | "0.9.20";
297297
exportedAt: string;
298298
sessions: Session[];
299299
observations: Record<string, CompressedObservation[]>;

src/version.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const VERSION = "0.9.19";
1+
export const VERSION = "0.9.20";

test/export-import.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ describe("Export/Import Functions", () => {
119119
it("export produces valid ExportData structure", async () => {
120120
const result = (await sdk.trigger("mem::export", {})) as ExportData;
121121

122-
expect(result.version).toBe("0.9.19");
122+
expect(result.version).toBe("0.9.20");
123123
expect(result.exportedAt).toBeDefined();
124124
expect(result.sessions.length).toBe(1);
125125
expect(result.sessions[0].id).toBe("ses_1");

0 commit comments

Comments
 (0)