agenr 0.8.12 → 0.8.14

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.13] - 2026-02-23
4
+
5
+ ### Fixed
6
+ - fix(openclaw-plugin): session-start recall now falls back to reading the most recent archived OpenClaw session file (`*.reset.*`) when webchat `/new` bypasses `before_reset`. If stash-based seeding is unavailable and the opening prompt is short (< 40 characters), recall query text is built from the last 3 user messages in the archived session.
7
+
3
8
  ## [0.8.12]
4
9
 
5
10
  ### Fixed
@@ -8,6 +8,7 @@ type BeforeAgentStartEvent = {
8
8
  type PluginHookAgentContext = {
9
9
  sessionKey?: string;
10
10
  sessionId?: string;
11
+ agentId?: string;
11
12
  workspaceDir?: string;
12
13
  [key: string]: unknown;
13
14
  };
@@ -7,6 +7,8 @@ import {
7
7
  } from "../chunk-L7VVZDWF.js";
8
8
 
9
9
  // src/openclaw-plugin/index.ts
10
+ import os from "os";
11
+ import path3 from "path";
10
12
  import { Type } from "@sinclair/typebox";
11
13
 
12
14
  // src/openclaw-plugin/recall.ts
@@ -140,8 +142,11 @@ function formatRecallAsMarkdown(result) {
140
142
  }
141
143
 
142
144
  // src/openclaw-plugin/session-query.ts
145
+ import { readFile, readdir, stat } from "fs/promises";
146
+ import path2 from "path";
143
147
  var SESSION_TOPIC_TTL_MS = 60 * 60 * 1e3;
144
148
  var SESSION_TOPIC_MIN_LENGTH = 40;
149
+ var ARCHIVED_SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
145
150
  var SESSION_QUERY_LOOKBACK = 3;
146
151
  var sessionTopicStash = /* @__PURE__ */ new Map();
147
152
  function isRecord(value) {
@@ -216,6 +221,58 @@ function extractLastUserText(messages) {
216
221
  return "";
217
222
  }
218
223
  }
224
+ async function readLatestArchivedUserMessages(sessionsDir, maxAgeMs = ARCHIVED_SESSION_MAX_AGE_MS) {
225
+ try {
226
+ const now = Date.now();
227
+ const archivedFiles = [];
228
+ const entries = await readdir(sessionsDir, { withFileTypes: true });
229
+ for (const entry of entries) {
230
+ if (!entry.isFile() || !entry.name.includes(".reset.")) {
231
+ continue;
232
+ }
233
+ const filePath = path2.join(sessionsDir, entry.name);
234
+ const fileStats = await stat(filePath);
235
+ if (now - fileStats.mtimeMs > maxAgeMs) {
236
+ continue;
237
+ }
238
+ archivedFiles.push({ filePath, mtimeMs: fileStats.mtimeMs });
239
+ }
240
+ if (archivedFiles.length === 0) {
241
+ return [];
242
+ }
243
+ archivedFiles.sort((a, b) => b.mtimeMs - a.mtimeMs);
244
+ for (const candidate of archivedFiles) {
245
+ const raw = await readFile(candidate.filePath, "utf8");
246
+ const userMessages = [];
247
+ for (const line of raw.split(/\r?\n/)) {
248
+ const trimmed = line.trim();
249
+ if (!trimmed) {
250
+ continue;
251
+ }
252
+ let parsed;
253
+ try {
254
+ parsed = JSON.parse(trimmed);
255
+ } catch {
256
+ continue;
257
+ }
258
+ if (!isRecord(parsed) || parsed["type"] !== "message") {
259
+ continue;
260
+ }
261
+ const text = extractTextFromUserMessage(parsed["message"]);
262
+ if (!text) {
263
+ continue;
264
+ }
265
+ userMessages.push(text);
266
+ }
267
+ if (userMessages.length > 0) {
268
+ return userMessages.slice(-SESSION_QUERY_LOOKBACK);
269
+ }
270
+ }
271
+ return [];
272
+ } catch {
273
+ return [];
274
+ }
275
+ }
219
276
  function shouldStashTopic(text) {
220
277
  if (text.length < SESSION_TOPIC_MIN_LENGTH) {
221
278
  return false;
@@ -890,7 +947,28 @@ var plugin = {
890
947
  const project = config?.project?.trim() || void 0;
891
948
  const userPrompt = stripPromptMetadata(event.prompt ?? "");
892
949
  const queryText = resolveSessionQuery(userPrompt, ctx.sessionKey);
893
- const recallResult = await runRecall(agenrPath, budget, project, queryText);
950
+ let recallQueryText = queryText;
951
+ if (isFirstInSession && queryText === userPrompt && userPrompt.length < SESSION_TOPIC_MIN_LENGTH) {
952
+ const agentId = ctx.agentId?.trim() || "main";
953
+ if (!ctx.agentId?.trim()) {
954
+ api.logger.debug?.("[agenr] session-start: agentId not provided, defaulting to 'main'");
955
+ }
956
+ const sessionsDir = path3.join(
957
+ os.homedir(),
958
+ ".openclaw",
959
+ "agents",
960
+ agentId,
961
+ "sessions"
962
+ );
963
+ const archivedMessages = await readLatestArchivedUserMessages(sessionsDir);
964
+ if (archivedMessages.length > 0) {
965
+ recallQueryText = `${archivedMessages.join(" ")} ${userPrompt}`;
966
+ api.logger.info?.(
967
+ `[agenr] session-start: archived session fallback applied, ${archivedMessages.length} messages`
968
+ );
969
+ }
970
+ }
971
+ const recallResult = await runRecall(agenrPath, budget, project, recallQueryText);
894
972
  if (recallResult) {
895
973
  const formatted = formatRecallAsMarkdown(recallResult);
896
974
  if (formatted.trim()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agenr",
3
- "version": "0.8.12",
3
+ "version": "0.8.14",
4
4
  "openclaw": {
5
5
  "extensions": [
6
6
  "dist/openclaw-plugin/index.js"
@@ -11,13 +11,6 @@
11
11
  "bin": {
12
12
  "agenr": "dist/cli.js"
13
13
  },
14
- "scripts": {
15
- "build": "tsup src/cli.ts src/cli-main.ts src/openclaw-plugin/index.ts --format esm --dts",
16
- "dev": "tsup src/cli.ts src/cli-main.ts --format esm --watch",
17
- "test": "vitest run",
18
- "test:watch": "vitest",
19
- "typecheck": "tsc --noEmit"
20
- },
21
14
  "dependencies": {
22
15
  "@clack/prompts": "^1.0.1",
23
16
  "@libsql/client": "^0.17.0",
@@ -61,9 +54,11 @@
61
54
  "README.md"
62
55
  ],
63
56
  "author": "agenr-ai",
64
- "pnpm": {
65
- "overrides": {
66
- "fast-xml-parser": "^5.3.6"
67
- }
57
+ "scripts": {
58
+ "build": "tsup src/cli.ts src/cli-main.ts src/openclaw-plugin/index.ts --format esm --dts",
59
+ "dev": "tsup src/cli.ts src/cli-main.ts --format esm --watch",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest",
62
+ "typecheck": "tsc --noEmit"
68
63
  }
69
- }
64
+ }