openclaw-topic-shift-reset 0.4.1 → 0.4.2

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 CHANGED
@@ -154,8 +154,8 @@ All plugin logs are prefixed with `topic-shift-reset:`.
154
154
 
155
155
  ### Debug (`debug: true`)
156
156
 
157
- - `classify source=<...> kind=<warmup|stable|suspect|rotate-hard|rotate-soft> reason=<...> ...`
158
- Full classifier output and metrics for a processed message.
157
+ - `classify source=<...> kind=<warmup|stable|suspect|rotate-hard|rotate-soft> reason=<...> ... textHash=<...> tokens=[...] text="..."`
158
+ Full classifier output and metrics plus a compact message preview for a processed message.
159
159
  - `suspect-queued session=<...>`
160
160
  Soft-suspect state queued for clarification steering.
161
161
  - `ask-injected session=<...>`
@@ -47,7 +47,7 @@ With `softSuspect.mode: "strict"` (default), a soft-confirm reset is blocked unt
47
47
  - `softSuspect.prompt`: optional steer text injected on soft-suspect.
48
48
  - `softSuspect.ttlSeconds`: expiry for pending soft-suspect steer.
49
49
  - `dryRun`: logs would-rotate events without session resets.
50
- - `debug`: emits per-message classifier diagnostics.
50
+ - `debug`: emits per-message classifier diagnostics, including compact message previews.
51
51
 
52
52
  ## Built-in preset defaults
53
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-topic-shift-reset",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "OpenClaw plugin that detects topic shifts and starts a fresh session automatically.",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/index.ts CHANGED
@@ -329,6 +329,8 @@ const STALE_SESSION_STATE_MS = 4 * 60 * 60 * 1000;
329
329
  const MAX_RECENT_MESSAGE_EVENTS = 20_000;
330
330
  const MESSAGE_EVENT_TTL_MS = 5 * 60 * 1000;
331
331
  const ROTATION_DEDUPE_MS = 25_000;
332
+ const DEBUG_LOG_TEXT_PREVIEW_CHARS = 180;
333
+ const DEBUG_LOG_TOKEN_PREVIEW_COUNT = 12;
332
334
  const PERSISTENCE_SCHEMA_VERSION = 1;
333
335
  const PERSISTENCE_FILE_NAME = "runtime-state.v1.json";
334
336
  const PERSISTENCE_FLUSH_DEBOUNCE_MS = 1_200;
@@ -2057,23 +2059,31 @@ export default function register(api: OpenClawPluginApi): void {
2057
2059
  }
2058
2060
 
2059
2061
  if (cfg.debug) {
2060
- api.logger.debug(
2061
- [
2062
- `topic-shift-reset: classify`,
2063
- `source=${params.source}`,
2064
- `kind=${decision.kind}`,
2065
- `reason=${decision.reason}`,
2066
- `session=${sessionKey}`,
2067
- `score=${decision.metrics.score.toFixed(3)}`,
2068
- `novelty=${decision.metrics.novelty.toFixed(3)}`,
2069
- `lex=${decision.metrics.lexicalDistance.toFixed(3)}`,
2070
- `uniq=${decision.metrics.uniqueTokenRatio.toFixed(3)}`,
2071
- `entropy=${decision.metrics.entropy.toFixed(3)}`,
2072
- `sim=${typeof decision.metrics.similarity === "number" ? decision.metrics.similarity.toFixed(3) : "n/a"}`,
2073
- `embed=${decision.metrics.usedEmbedding ? "1" : "0"}`,
2074
- `pending=${state.pendingSoftSignals}`,
2075
- ].join(" "),
2076
- );
2062
+ const textPreview = truncateText(text, DEBUG_LOG_TEXT_PREVIEW_CHARS);
2063
+ const rawPreview = truncateText(rawText, DEBUG_LOG_TEXT_PREVIEW_CHARS);
2064
+ const debugFields = [
2065
+ `topic-shift-reset: classify`,
2066
+ `source=${params.source}`,
2067
+ `kind=${decision.kind}`,
2068
+ `reason=${decision.reason}`,
2069
+ `session=${sessionKey}`,
2070
+ `score=${decision.metrics.score.toFixed(3)}`,
2071
+ `novelty=${decision.metrics.novelty.toFixed(3)}`,
2072
+ `lex=${decision.metrics.lexicalDistance.toFixed(3)}`,
2073
+ `uniq=${decision.metrics.uniqueTokenRatio.toFixed(3)}`,
2074
+ `entropy=${decision.metrics.entropy.toFixed(3)}`,
2075
+ `sim=${typeof decision.metrics.similarity === "number" ? decision.metrics.similarity.toFixed(3) : "n/a"}`,
2076
+ `embed=${decision.metrics.usedEmbedding ? "1" : "0"}`,
2077
+ `pending=${state.pendingSoftSignals}`,
2078
+ `baseline=${baselineTokens.size}`,
2079
+ `textHash=${contentHash}`,
2080
+ `tokens=${maybeJson(tokenList.slice(0, DEBUG_LOG_TOKEN_PREVIEW_COUNT))}`,
2081
+ `text=${maybeJson(textPreview)}`,
2082
+ ];
2083
+ if (rawPreview !== textPreview) {
2084
+ debugFields.push(`raw=${maybeJson(rawPreview)}`);
2085
+ }
2086
+ api.logger.debug(debugFields.join(" "));
2077
2087
  }
2078
2088
 
2079
2089
  if (decision.kind === "warmup") {