Merge pull request 'Implement unique filename generation to prevent overwriting existing session files' (#4) from no-overrides into main
Reviewed-on: #4 Reviewed-by: Luna <clawy@reversed.dev>
This commit was merged in pull request #4.
This commit is contained in:
3
HOOK.md
3
HOOK.md
@@ -17,6 +17,9 @@ metadata:
|
|||||||
Writes full user/assistant transcript context from the previous session into
|
Writes full user/assistant transcript context from the previous session into
|
||||||
`<workspace>/memory/YYYY-MM-DD-slug.md` when `/new` or `/reset` runs.
|
`<workspace>/memory/YYYY-MM-DD-slug.md` when `/new` or `/reset` runs.
|
||||||
|
|
||||||
|
This hook avoids overwriting existing files by choosing a unique filename
|
||||||
|
when a collision occurs (it appends `-1`, `-2`, etc. to the base name).
|
||||||
|
|
||||||
Differences from bundled session-memory:
|
Differences from bundled session-memory:
|
||||||
|
|
||||||
- Uses full session context in output file
|
- Uses full session context in output file
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ Custom OpenClaw session-memory hook.
|
|||||||
- Saves the **full** user/assistant session context into `workspace/memory/`
|
- Saves the **full** user/assistant session context into `workspace/memory/`
|
||||||
- Uses `agents.defaults.userTimezone` for date/time formatting
|
- Uses `agents.defaults.userTimezone` for date/time formatting
|
||||||
- Uses a slugged filename, with slug generation based on a small excerpt
|
- Uses a slugged filename, with slug generation based on a small excerpt
|
||||||
|
- Avoids overwriting existing files: if a filename already exists the hook
|
||||||
|
appends `-1`, `-2`, ... to produce a unique filename.
|
||||||
|
|
||||||
## Disable the bundled hook
|
## Disable the bundled hook
|
||||||
|
|
||||||
@@ -42,3 +44,8 @@ Or set it false in config:
|
|||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
This repo is intentionally lightweight, it exists so the custom hook can live in the managed hooks directory and stay separate from the bundled one.
|
This repo is intentionally lightweight, it exists so the custom hook can live in the managed hooks directory and stay separate from the bundled one.
|
||||||
|
|
||||||
|
If you prefer atomic creation to fully eliminate a race window (two processes
|
||||||
|
creating the same new filename simultaneously), replace the simple existence
|
||||||
|
check with an atomic open/write using `fs.open(..., 'wx')` or write to a
|
||||||
|
temporary file and `fs.rename()` it into place.
|
||||||
|
|||||||
22
handler.ts
22
handler.ts
@@ -197,6 +197,26 @@ function buildSlugExcerpt(full: string): string {
|
|||||||
return tail.slice(-3000);
|
return tail.slice(-3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getUniqueFilePath(dir: string, filename: string): Promise<string> {
|
||||||
|
const candidate = path.join(dir, filename);
|
||||||
|
try {
|
||||||
|
await fs.access(candidate);
|
||||||
|
} catch {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsed = path.parse(filename);
|
||||||
|
for (let i = 1; ; i += 1) {
|
||||||
|
const name = `${parsed.name}-${i}${parsed.ext}`;
|
||||||
|
const p = path.join(dir, name);
|
||||||
|
try {
|
||||||
|
await fs.access(p);
|
||||||
|
} catch {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function generateSlug(params: {
|
async function generateSlug(params: {
|
||||||
excerpt: string;
|
excerpt: string;
|
||||||
cfg: AnyObj;
|
cfg: AnyObj;
|
||||||
@@ -274,7 +294,7 @@ const handler = async (event: {
|
|||||||
await fs.mkdir(memoryDir, { recursive: true });
|
await fs.mkdir(memoryDir, { recursive: true });
|
||||||
|
|
||||||
const filename = `${dateStr}-${slug}.md`;
|
const filename = `${dateStr}-${slug}.md`;
|
||||||
const memoryFilePath = path.join(memoryDir, filename);
|
const memoryFilePath = await getUniqueFilePath(memoryDir, filename);
|
||||||
|
|
||||||
const source = typeof context.commandSource === "string" ? context.commandSource : "unknown";
|
const source = typeof context.commandSource === "string" ? context.commandSource : "unknown";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user