clawmem 0.10.4 → 0.10.5
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/package.json +1 -1
- package/src/openclaw/index.ts +4 -4
- package/src/store.ts +21 -7
package/package.json
CHANGED
package/src/openclaw/index.ts
CHANGED
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
* 4. REST API service (`clawmem serve`) lifecycle — unchanged.
|
|
38
38
|
*
|
|
39
39
|
* §14.3 critical correctness contract: `agent_end` is fire-and-forget at
|
|
40
|
-
* `attempt.ts:
|
|
41
|
-
* `handleBeforePromptBuild` (which IS awaited at `attempt.ts:
|
|
40
|
+
* `attempt.ts:3870-3892`. Precompact-extract MUST run inside
|
|
41
|
+
* `handleBeforePromptBuild` (which IS awaited at `attempt.ts:2973`), gated
|
|
42
42
|
* by the proximity heuristic in `compaction-threshold.ts`. See `engine.ts`
|
|
43
43
|
* top-of-file comment for the full rationale.
|
|
44
44
|
*/
|
|
@@ -161,7 +161,7 @@ const clawmemPlugin = {
|
|
|
161
161
|
// ----- Plugin Hook: before_prompt_build (AWAITED — load-bearing path) -----
|
|
162
162
|
// Both context-surfacing retrieval injection and pre-emptive precompact
|
|
163
163
|
// extraction live here. handleBeforePromptBuild is async and the OpenClaw
|
|
164
|
-
// attempt path awaits the result at attempt.ts:
|
|
164
|
+
// attempt path awaits the result at attempt.ts:2973 before building the
|
|
165
165
|
// effective prompt. precompact-extract therefore runs strictly before
|
|
166
166
|
// the LLM call that could trigger compaction on this turn.
|
|
167
167
|
api.on(
|
|
@@ -175,7 +175,7 @@ const clawmemPlugin = {
|
|
|
175
175
|
// ----- Plugin Hook: agent_end (FIRE-AND-FORGET in core) -----
|
|
176
176
|
// Decision-extractor, handoff-generator, and feedback-loop run here.
|
|
177
177
|
// These writes are eventually-consistent (saveMemory dedupes), so the
|
|
178
|
-
// fire-and-forget context at attempt.ts:
|
|
178
|
+
// fire-and-forget context at attempt.ts:3870-3892 is acceptable.
|
|
179
179
|
// OpenClaw v2026.4.26+ also enforces a 30s default void-hook timeout
|
|
180
180
|
// (DEFAULT_VOID_HOOK_TIMEOUT_MS_BY_HOOK in src/plugins/hooks.ts) — a
|
|
181
181
|
// timed-out handler is logged but our underlying postrun work is not
|
package/src/store.ts
CHANGED
|
@@ -298,13 +298,20 @@ if (process.platform === "darwin") {
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
function initializeDatabase(db: Database): void {
|
|
301
|
+
// Set busy_timeout FIRST so subsequent PRAGMAs (journal_mode in particular,
|
|
302
|
+
// which acquires a write lock when switching or initializing WAL state) wait
|
|
303
|
+
// instead of returning SQLITE_BUSY when concurrent Stop hooks
|
|
304
|
+
// (decision-extractor, handoff-generator, feedback-loop) — and the parallel
|
|
305
|
+
// before_reset hook fan-out in src/openclaw/engine.ts — open the DB
|
|
306
|
+
// simultaneously. busy_timeout is a connection-level setting that only
|
|
307
|
+
// governs *subsequent* statements (default busy handler is NULL → SQLITE_BUSY
|
|
308
|
+
// returns immediately), so it must precede the contending PRAGMAs. 15s is
|
|
309
|
+
// well within the 30s Stop hook timeout. createStore() resets to operational
|
|
310
|
+
// value (5000ms or opts.busyTimeout) after DDL completes. Issue #13.
|
|
311
|
+
db.exec("PRAGMA busy_timeout = 15000");
|
|
301
312
|
sqliteVec.load(db);
|
|
302
313
|
db.exec("PRAGMA journal_mode = WAL");
|
|
303
314
|
db.exec("PRAGMA foreign_keys = ON");
|
|
304
|
-
// Set generous busy_timeout during DDL — concurrent Stop hooks (decision-extractor,
|
|
305
|
-
// handoff-generator, feedback-loop) all run initializeDatabase simultaneously.
|
|
306
|
-
// 15s is well within the 30s Stop hook timeout. Reset to normal after DDL completes.
|
|
307
|
-
db.exec("PRAGMA busy_timeout = 15000");
|
|
308
315
|
|
|
309
316
|
// Drop legacy tables that are now managed in YAML
|
|
310
317
|
db.exec(`DROP TABLE IF EXISTS path_contexts`);
|
|
@@ -1123,13 +1130,20 @@ export function createStore(dbPath?: string, opts?: { readonly?: boolean; busyTi
|
|
|
1123
1130
|
if (!opts?.readonly) {
|
|
1124
1131
|
initializeDatabase(db);
|
|
1125
1132
|
} else {
|
|
1126
|
-
// Readonly:
|
|
1133
|
+
// Readonly: set busy_timeout FIRST so the journal_mode PRAGMA below
|
|
1134
|
+
// doesn't race when concurrent processes open the DB. PRAGMA
|
|
1135
|
+
// journal_mode=WAL can contend when switching or initializing WAL
|
|
1136
|
+
// state, even on readonly handles. Public-API hardening — no
|
|
1137
|
+
// production caller in this repo currently passes readonly:true,
|
|
1138
|
+
// but the ordering invariant should hold regardless. Issue #13.
|
|
1139
|
+
db.exec(`PRAGMA busy_timeout = ${opts?.busyTimeout ?? 5000}`);
|
|
1127
1140
|
sqliteVec.load(db);
|
|
1128
1141
|
db.exec("PRAGMA journal_mode = WAL");
|
|
1129
1142
|
db.exec("PRAGMA query_only = ON");
|
|
1130
1143
|
}
|
|
1131
|
-
//
|
|
1132
|
-
//
|
|
1144
|
+
// For the writable branch: initializeDatabase() set 15000 during DDL —
|
|
1145
|
+
// reset to operational value here. For readonly: already set inside the
|
|
1146
|
+
// branch above; this assignment is a no-op rewrite to the same value.
|
|
1133
1147
|
db.exec(`PRAGMA busy_timeout = ${opts?.busyTimeout ?? 5000}`);
|
|
1134
1148
|
|
|
1135
1149
|
return {
|