@remnic/plugin-openclaw 1.0.6 → 1.0.7
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 +36 -0
- package/dist/{calibration-3JHF25QT.js → calibration-BAC7KNKR.js} +2 -1
- package/dist/{causal-consolidation-EBLROS42.js → causal-consolidation-S6M7UTZG.js} +2 -1
- package/dist/chunk-3A5ELHTT.js +61 -0
- package/dist/chunk-DIZW6H5J.js +136 -0
- package/dist/{chunk-3SA5F4WT.js → chunk-NXLHSCLU.js} +125 -69
- package/dist/{chunk-GUKYM4XZ.js → chunk-SVGN3ACY.js} +2 -2
- package/dist/contradiction-review-SVGBS3V5.js +21 -0
- package/dist/contradiction-scan-LRRLWUOS.js +376 -0
- package/dist/{engine-BU6GNUJ5.js → engine-WGNTTFYE.js} +1 -1
- package/dist/{fallback-llm-HJRCHKSA.js → fallback-llm-QEAPMDW7.js} +2 -1
- package/dist/index.js +516 -93
- package/dist/resolution-YITUVUTH.js +100 -0
- package/openclaw.plugin.json +28 -2
- package/package.json +2 -2
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readPair,
|
|
3
|
+
resolvePair
|
|
4
|
+
} from "./chunk-DIZW6H5J.js";
|
|
5
|
+
import {
|
|
6
|
+
log
|
|
7
|
+
} from "./chunk-UFU5GGGA.js";
|
|
8
|
+
import "./chunk-MLKGABMK.js";
|
|
9
|
+
|
|
10
|
+
// ../remnic-core/src/contradiction/resolution.ts
|
|
11
|
+
var VALID_VERBS = ["keep-a", "keep-b", "merge", "both-valid", "needs-more-context"];
|
|
12
|
+
function isValidResolutionVerb(value) {
|
|
13
|
+
return VALID_VERBS.includes(value);
|
|
14
|
+
}
|
|
15
|
+
async function executeResolution(memoryDir, storage, pairId, verb) {
|
|
16
|
+
const pair = readPair(memoryDir, pairId);
|
|
17
|
+
if (!pair) {
|
|
18
|
+
return { pairId, verb, affectedIds: [], message: `Pair ${pairId} not found` };
|
|
19
|
+
}
|
|
20
|
+
if (pair.resolution) {
|
|
21
|
+
return { pairId, verb, affectedIds: [], message: `Pair already resolved with verb "${pair.resolution}"` };
|
|
22
|
+
}
|
|
23
|
+
const [idA, idB] = pair.memoryIds;
|
|
24
|
+
const affectedIds = [];
|
|
25
|
+
let message = "";
|
|
26
|
+
let supersedeFailed = false;
|
|
27
|
+
switch (verb) {
|
|
28
|
+
case "keep-a": {
|
|
29
|
+
const ok = await supersedeSafe(storage, idB, idA, "contradiction-resolution:keep-a");
|
|
30
|
+
if (ok) {
|
|
31
|
+
affectedIds.push(idB);
|
|
32
|
+
message = `Kept ${idA}, superseded ${idB}`;
|
|
33
|
+
} else {
|
|
34
|
+
supersedeFailed = true;
|
|
35
|
+
message = `Supersede failed for ${idB}; not resolving`;
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
case "keep-b": {
|
|
40
|
+
const ok = await supersedeSafe(storage, idA, idB, "contradiction-resolution:keep-b");
|
|
41
|
+
if (ok) {
|
|
42
|
+
affectedIds.push(idA);
|
|
43
|
+
message = `Kept ${idB}, superseded ${idA}`;
|
|
44
|
+
} else {
|
|
45
|
+
supersedeFailed = true;
|
|
46
|
+
message = `Supersede failed for ${idA}; not resolving`;
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case "merge": {
|
|
51
|
+
const mergedId = `merged-${pairId}`;
|
|
52
|
+
const okA = await supersedeSafe(storage, idA, mergedId, "contradiction-resolution:merge");
|
|
53
|
+
const okB = await supersedeSafe(storage, idB, mergedId, "contradiction-resolution:merge");
|
|
54
|
+
if (okA) affectedIds.push(idA);
|
|
55
|
+
if (okB) affectedIds.push(idB);
|
|
56
|
+
if (!okA || !okB) {
|
|
57
|
+
supersedeFailed = true;
|
|
58
|
+
message = `Merge incomplete: ${affectedIds.length}/2 superseded; not resolving to allow retry`;
|
|
59
|
+
} else {
|
|
60
|
+
message = `Both memories superseded by merged ${mergedId}`;
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
case "both-valid": {
|
|
65
|
+
message = "Pair marked as both-valid; cooldown applied";
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case "needs-more-context": {
|
|
69
|
+
message = "Deferred; no action taken, short cooldown applied";
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!supersedeFailed) {
|
|
74
|
+
resolvePair(memoryDir, pairId, verb);
|
|
75
|
+
}
|
|
76
|
+
log.info("[contradiction-resolution] pair=%s verb=%s affected=%d", pairId, verb, affectedIds.length);
|
|
77
|
+
return { pairId, verb, affectedIds, message };
|
|
78
|
+
}
|
|
79
|
+
async function supersedeSafe(storage, oldId, newId, reason) {
|
|
80
|
+
try {
|
|
81
|
+
const result = await storage.supersedeMemory(oldId, newId, reason);
|
|
82
|
+
if (result === false) {
|
|
83
|
+
log.warn("[contradiction-resolution] supersede returned false for %s \u2192 %s", oldId, newId);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
} catch (err) {
|
|
88
|
+
log.warn(
|
|
89
|
+
"[contradiction-resolution] supersede failed %s \u2192 %s: %s",
|
|
90
|
+
oldId,
|
|
91
|
+
newId,
|
|
92
|
+
err instanceof Error ? err.message : err
|
|
93
|
+
);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
executeResolution,
|
|
99
|
+
isValidResolutionVerb
|
|
100
|
+
};
|
package/openclaw.plugin.json
CHANGED
|
@@ -1918,6 +1918,18 @@
|
|
|
1918
1918
|
"default": true,
|
|
1919
1919
|
"description": "Automatically supersede contradicted memories"
|
|
1920
1920
|
},
|
|
1921
|
+
"contradictionScan": {
|
|
1922
|
+
"type": "object",
|
|
1923
|
+
"description": "Configuration for the nightly contradiction-scan cron (issue #520)",
|
|
1924
|
+
"properties": {
|
|
1925
|
+
"enabled": { "type": "boolean", "default": false, "description": "Enable the nightly contradiction scan cron (disabled by default per rule 48)" },
|
|
1926
|
+
"similarityFloor": { "type": "number", "default": 0.82, "minimum": 0, "maximum": 1, "description": "Embedding cosine similarity floor for candidate pair generation" },
|
|
1927
|
+
"topicOverlapFloor": { "type": "number", "default": 0.4, "minimum": 0, "maximum": 1, "description": "Minimum topic-token Jaccard overlap for unstructured pairs" },
|
|
1928
|
+
"maxPairsPerRun": { "type": "integer", "default": 500, "minimum": 1, "description": "Cap on candidate pairs evaluated per cron run" },
|
|
1929
|
+
"cooldownDays": { "type": "integer", "default": 14, "minimum": 0, "description": "Cooldown in days. 0 = always re-evaluate." },
|
|
1930
|
+
"autoMergeDuplicates": { "type": "boolean", "default": false, "description": "Auto-flag pairs judged duplicates for dedup (still requires user approval)" }
|
|
1931
|
+
}
|
|
1932
|
+
},
|
|
1921
1933
|
"temporalSupersessionEnabled": {
|
|
1922
1934
|
"type": "boolean",
|
|
1923
1935
|
"default": true,
|
|
@@ -1930,8 +1942,8 @@
|
|
|
1930
1942
|
},
|
|
1931
1943
|
"recallDirectAnswerEnabled": {
|
|
1932
1944
|
"type": "boolean",
|
|
1933
|
-
"default":
|
|
1934
|
-
"description": "When true, recall
|
|
1945
|
+
"default": true,
|
|
1946
|
+
"description": "When true, recall runs the direct-answer tier in observation mode: annotates LastRecallSnapshot.tierExplain with which tier would have served the query (issue #518). Does not short-circuit the QMD path in the current release."
|
|
1935
1947
|
},
|
|
1936
1948
|
"recallDirectAnswerTokenOverlapFloor": {
|
|
1937
1949
|
"type": "number",
|
|
@@ -2375,6 +2387,11 @@
|
|
|
2375
2387
|
"default": 15000,
|
|
2376
2388
|
"description": "Timeout for fast-tier local LLM requests (ms). Lower than primary since fast ops should complete quickly."
|
|
2377
2389
|
},
|
|
2390
|
+
"localLlmDisableThinking": {
|
|
2391
|
+
"type": "boolean",
|
|
2392
|
+
"default": true,
|
|
2393
|
+
"description": "When true (default), request chain-of-thought / thinking-mode suppression on the main local LLM (issue #548). The `chat_template_kwargs: { enable_thinking: false }` field is only injected when the detected backend is known to support it (LM Studio, vLLM); strict OpenAI-compat backends fail open to avoid the 400-cooldown path. Structured-output tasks like extraction and consolidation gain nothing from reasoning tokens and thinking-capable models (Qwen 3.5, Gemma 4, DeepSeek) often blow the 60s timeout before emitting content. Set to false to restore thinking for narrative tasks. The fast-tier client always disables thinking and is not affected by this flag."
|
|
2394
|
+
},
|
|
2378
2395
|
"hourlySummaryCronAutoRegister": {
|
|
2379
2396
|
"type": "boolean",
|
|
2380
2397
|
"default": false,
|
|
@@ -4037,6 +4054,10 @@
|
|
|
4037
4054
|
"label": "Auto-Resolve Contradictions",
|
|
4038
4055
|
"help": "Automatically supersede old memories when contradiction is confirmed"
|
|
4039
4056
|
},
|
|
4057
|
+
"contradictionScan": {
|
|
4058
|
+
"label": "Contradiction Scan",
|
|
4059
|
+
"help": "Nightly cron that pairs similar memories and flags contradictions for review (issue #520)"
|
|
4060
|
+
},
|
|
4040
4061
|
"temporalSupersessionEnabled": {
|
|
4041
4062
|
"label": "Temporal Supersession",
|
|
4042
4063
|
"help": "Mark older facts superseded when a newer fact writes a conflicting value for the same entityRef + structured attribute (issue #375)"
|
|
@@ -4271,6 +4292,11 @@
|
|
|
4271
4292
|
"advanced": true,
|
|
4272
4293
|
"help": "Timeout for fast-tier requests. Lower than primary since fast ops should complete quickly."
|
|
4273
4294
|
},
|
|
4295
|
+
"localLlmDisableThinking": {
|
|
4296
|
+
"label": "Disable Local LLM Thinking Mode",
|
|
4297
|
+
"advanced": true,
|
|
4298
|
+
"help": "Suppress chain-of-thought reasoning on the main local LLM. Default on — extraction / consolidation are structured-output tasks where thinking is pure latency tax and a common cause of 60s timeouts on Qwen 3.5 / Gemma 4 / DeepSeek. The suppression field (chat_template_kwargs) is only sent when the backend is known to support it (LM Studio, vLLM); strict OpenAI-compat backends fail open. Turn off if you want thinking on narrative tasks. Fast-tier client always disables thinking regardless."
|
|
4299
|
+
},
|
|
4274
4300
|
"evalHarnessEnabled": {
|
|
4275
4301
|
"label": "Evaluation Harness",
|
|
4276
4302
|
"help": "Enable Engram's benchmark/evaluation harness foundation and benchmark-status diagnostics."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/plugin-openclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "OpenClaw adapter for Remnic memory — thin wrapper delegating to @remnic/core",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"openai": "^6.0.0",
|
|
28
|
-
"@remnic/core": "^1.0
|
|
28
|
+
"@remnic/core": "^1.1.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"openclaw": ">=2026.4.8"
|