agenr 0.9.73 → 0.9.75
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 +35 -0
- package/dist/{chunk-6IJXCW2J.js → chunk-AQN6BP74.js} +192 -190
- package/dist/{chunk-PAO647AF.js → chunk-HEE4JOTJ.js} +1 -1
- package/dist/{chunk-JH355OHS.js → chunk-PUBBITKQ.js} +2 -2
- package/dist/{chunk-Z7MN65K2.js → chunk-UGIJJOPV.js} +7 -0
- package/dist/cli-main.js +1204 -400
- package/dist/{co-recall-MOA5R4D6.js → co-recall-VWYTWS7P.js} +1 -1
- package/dist/{maintain-CKA7EVOW.js → maintain-QRHVQ45A.js} +3 -3
- package/dist/openclaw-plugin/index.js +753 -65
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.75] - 2026-03-07
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- OpenClaw session-start memory injection now runs browse/core recall through a dedicated startup selector that favors continuity utility over raw browse ordering, suppresses overlap with `Recent session`, and applies hard section caps before rendering.
|
|
8
|
+
- Session-start startup memory now treats `fact`, `event`, `lesson`, `relationship`, and `reflection` intentionally instead of sending all residual non-core entries into one broad startup bucket.
|
|
9
|
+
- The session-start composer now reserves space for `Memory Index` before rendering `Recent memory`, so aggressive char trimming keeps recovery breadcrumbs whenever they still fit.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- OpenClaw session-start dedupe now records only the entry IDs that actually survive selector filtering and prompt rendering, so startup-trimmed entries remain eligible for later mid-session recall.
|
|
14
|
+
- Session-start selector freshness now treats missing or malformed `updated_at` values conservatively as stale instead of accidentally boosting them as fresh.
|
|
15
|
+
- Tightened session-start exact-state detection to require structured operational state such as active branch/worktree/cwd, numbered PR or issue references, concrete path or file state, or explicit config/env/version state.
|
|
16
|
+
- Added a narrow older-continuity escape hatch so importance-7 lessons, relationships, and exact-state or open-thread facts can survive beyond the freshness window when they still materially affect current work.
|
|
17
|
+
- OpenClaw session-start browse candidate assembly now prefetches a small larger pool, caps `reflection` entries before the final 10-slot cutoff, and backfills remaining slots by existing browse score so durable non-reflection entries are not starved upstream of the selector.
|
|
18
|
+
- Tightened OpenClaw session-start selector admission for historical decisions and preferences so high importance now boosts ranking only after current behavioral, exact-state, or real continuity evidence is present.
|
|
19
|
+
- Made session-start `openThread` detection more precise by treating weak narrative words like `next`, `continue`, and `fix` as continuity signals only when they are very recent, while preserving stronger unfinished-work cues.
|
|
20
|
+
- Removed a redundant post-classification cosmetic-preference filter from session-start selection and added regression coverage for stale high-importance decisions and weak versus strong continuity wording.
|
|
21
|
+
|
|
22
|
+
## [0.9.74] - 2026-03-07
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Added a shared extractor-side valuation layer with source-aware priors for coding-agent transcripts and README/AGENTS/INSTALL-style repo docs, plus lightweight reason-coded tracing in verbose runs.
|
|
27
|
+
- Added mixed-signal benchmark fixtures for README, AGENTS, INSTALL, repo cartography, and Codex transcript chatter so precision-first ingest regressions can be measured against real traps.
|
|
28
|
+
- Added focused regression coverage for valuation punch-through and suppression behavior, including adversarial setup keyword traps, architecture-keyword cartography traps, release-rationale noise, and plain durable doc-rule fixtures.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Extraction-driven ingest now shares the same valuation semantics across watcher and bulk ingest by gating entries centrally before downstream dedup/store cleanup.
|
|
33
|
+
- Tightened extractor valuation so durable constraints, rationale, conventions, and concrete architecture boundaries can still punch through, while weak cues no longer beat doc/profile demotions and procedural or transient negatives on their own.
|
|
34
|
+
- Broadened doc source-profile detection to catch README/AGENTS/INSTALL/runbook/playbook-style filename variants, including benchmark fixture names, so doc-like priors apply consistently instead of falling back to the default profile.
|
|
35
|
+
- Tightened the extraction system prompt to reject source paraphrase, setup/onboarding replay, repo cartography, and operational chatter while still extracting buried durable signal.
|
|
36
|
+
- `agenr benchmark` fixture discovery now includes `.md`, `.markdown`, and `.txt` sources alongside `.jsonl` sessions.
|
|
37
|
+
|
|
3
38
|
## [0.9.73] - 2026-03-06
|
|
4
39
|
|
|
5
40
|
### Added
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
getDb,
|
|
4
4
|
initDb,
|
|
5
5
|
normalizeProject
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HEE4JOTJ.js";
|
|
7
7
|
import {
|
|
8
8
|
toNumber,
|
|
9
9
|
toRowsAffected,
|
|
10
10
|
toStringValue
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-UGIJJOPV.js";
|
|
12
12
|
|
|
13
13
|
// src/openclaw-plugin/plugin-db.ts
|
|
14
14
|
var CREATE_SEEN_SESSIONS_TABLE_SQL = `
|
|
@@ -36,7 +36,7 @@ var ADD_SESSION_PROJECT_STATE_COLUMN_SQL = `
|
|
|
36
36
|
var pluginDb = null;
|
|
37
37
|
var pluginDbInit = null;
|
|
38
38
|
var didRegisterDbShutdown = false;
|
|
39
|
-
async function
|
|
39
|
+
async function ensurePluginDbTables(client) {
|
|
40
40
|
await initDb(client);
|
|
41
41
|
await client.execute(CREATE_SEEN_SESSIONS_TABLE_SQL);
|
|
42
42
|
await client.execute(CREATE_SEEN_SESSIONS_SEEN_AT_INDEX_SQL);
|
|
@@ -70,7 +70,7 @@ async function ensurePluginDb(config) {
|
|
|
70
70
|
registerDbShutdown();
|
|
71
71
|
}
|
|
72
72
|
if (!pluginDbInit) {
|
|
73
|
-
pluginDbInit =
|
|
73
|
+
pluginDbInit = ensurePluginDbTables(pluginDb).catch((err) => {
|
|
74
74
|
pluginDbInit = null;
|
|
75
75
|
throw err;
|
|
76
76
|
});
|
|
@@ -87,6 +87,184 @@ function clearPluginDbState() {
|
|
|
87
87
|
didRegisterDbShutdown = false;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
// src/openclaw-plugin/session-project-state.ts
|
|
91
|
+
function readProjectState(row) {
|
|
92
|
+
if (!row || typeof row !== "object") {
|
|
93
|
+
return { kind: "unset" };
|
|
94
|
+
}
|
|
95
|
+
const record = row;
|
|
96
|
+
const normalizedProject = typeof record.project === "string" ? normalizeProject(record.project) : null;
|
|
97
|
+
const rawState = typeof record.state === "string" ? record.state.trim().toLowerCase() : "";
|
|
98
|
+
if (rawState === "cleared") {
|
|
99
|
+
return { kind: "cleared" };
|
|
100
|
+
}
|
|
101
|
+
if (normalizedProject) {
|
|
102
|
+
return { kind: "set", project: normalizedProject };
|
|
103
|
+
}
|
|
104
|
+
return rawState === "set" ? { kind: "cleared" } : { kind: "unset" };
|
|
105
|
+
}
|
|
106
|
+
async function getSessionProjectState(sessionKey, config) {
|
|
107
|
+
const db = await ensurePluginDb(config);
|
|
108
|
+
const result = await db.execute({
|
|
109
|
+
sql: "SELECT project, state FROM session_projects WHERE session_key = ? LIMIT 1",
|
|
110
|
+
args: [sessionKey]
|
|
111
|
+
});
|
|
112
|
+
return readProjectState(result.rows[0]);
|
|
113
|
+
}
|
|
114
|
+
async function getSessionProject(sessionKey, config) {
|
|
115
|
+
const state = await getSessionProjectState(sessionKey, config);
|
|
116
|
+
return state.kind === "set" ? state.project : null;
|
|
117
|
+
}
|
|
118
|
+
async function setSessionProject(sessionKey, project, config) {
|
|
119
|
+
const normalizedProject = normalizeProject(project);
|
|
120
|
+
if (!normalizedProject) {
|
|
121
|
+
throw new Error("Session project must not be empty after normalization.");
|
|
122
|
+
}
|
|
123
|
+
const db = await ensurePluginDb(config);
|
|
124
|
+
await db.execute({
|
|
125
|
+
sql: `
|
|
126
|
+
INSERT OR REPLACE INTO session_projects (session_key, project, state, updated_at)
|
|
127
|
+
VALUES (?, ?, 'set', ?)
|
|
128
|
+
`,
|
|
129
|
+
args: [sessionKey, normalizedProject, (/* @__PURE__ */ new Date()).toISOString()]
|
|
130
|
+
});
|
|
131
|
+
return normalizedProject;
|
|
132
|
+
}
|
|
133
|
+
async function clearSessionProject(sessionKey, config) {
|
|
134
|
+
const db = await ensurePluginDb(config);
|
|
135
|
+
await db.execute({
|
|
136
|
+
sql: `
|
|
137
|
+
INSERT OR REPLACE INTO session_projects (session_key, project, state, updated_at)
|
|
138
|
+
VALUES (?, '', 'cleared', ?)
|
|
139
|
+
`,
|
|
140
|
+
args: [sessionKey, (/* @__PURE__ */ new Date()).toISOString()]
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/openclaw-plugin/project-attribution.ts
|
|
145
|
+
var PROJECT_WORTHY_TYPES = /* @__PURE__ */ new Set(["fact", "decision", "lesson", "todo"]);
|
|
146
|
+
var PROJECT_SIGNAL_TAGS = /* @__PURE__ */ new Set([
|
|
147
|
+
"architecture",
|
|
148
|
+
"codebase",
|
|
149
|
+
"issue",
|
|
150
|
+
"issues",
|
|
151
|
+
"pr",
|
|
152
|
+
"pull request",
|
|
153
|
+
"pull-request",
|
|
154
|
+
"pullrequest",
|
|
155
|
+
"repo",
|
|
156
|
+
"repository",
|
|
157
|
+
"ticket",
|
|
158
|
+
"tickets"
|
|
159
|
+
]);
|
|
160
|
+
var TECHNICAL_SOURCE_PATTERNS = [
|
|
161
|
+
/(^|[^a-z0-9])(repo|repository|codebase|github)([^a-z0-9]|$)/i,
|
|
162
|
+
/(^|[^a-z0-9])(issue|ticket|pr)(\s*#\d+|[^a-z0-9]|$)/i,
|
|
163
|
+
/(^|[^a-z0-9])pull request(\s*#\d+|[^a-z0-9]|$)/i,
|
|
164
|
+
/(^|[^a-z0-9])(src|tests|docs|packages)\/[^\s]+/i,
|
|
165
|
+
/(^|[^a-z0-9])(package\.json|pnpm-lock\.yaml|tsconfig\.json|vitest\.config)([^a-z0-9]|$)/i,
|
|
166
|
+
/\.(ts|tsx|js|jsx|mjs|cjs|sql|toml|yaml|yml)([^a-z0-9]|$)/i
|
|
167
|
+
];
|
|
168
|
+
function asTrimmedString(value) {
|
|
169
|
+
if (typeof value !== "string") {
|
|
170
|
+
return void 0;
|
|
171
|
+
}
|
|
172
|
+
const trimmed = value.trim();
|
|
173
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
174
|
+
}
|
|
175
|
+
function normalizeSignalText(value) {
|
|
176
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim().replace(/\s+/g, " ");
|
|
177
|
+
}
|
|
178
|
+
function containsNormalizedPhrase(text, phrase) {
|
|
179
|
+
const normalizedText = normalizeSignalText(text);
|
|
180
|
+
const normalizedPhrase = normalizeSignalText(phrase);
|
|
181
|
+
if (!normalizedText || !normalizedPhrase) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return ` ${normalizedText} `.includes(` ${normalizedPhrase} `);
|
|
185
|
+
}
|
|
186
|
+
function getSourceText(entry) {
|
|
187
|
+
const source = entry.source;
|
|
188
|
+
if (typeof source === "string") {
|
|
189
|
+
return asTrimmedString(source);
|
|
190
|
+
}
|
|
191
|
+
if (!source || typeof source !== "object") {
|
|
192
|
+
return void 0;
|
|
193
|
+
}
|
|
194
|
+
const sourceRecord = source;
|
|
195
|
+
const file = asTrimmedString(sourceRecord.file);
|
|
196
|
+
const context = asTrimmedString(sourceRecord.context);
|
|
197
|
+
const text = [file, context].filter((value) => value !== void 0).join(" ");
|
|
198
|
+
return text.length > 0 ? text : void 0;
|
|
199
|
+
}
|
|
200
|
+
function getTags(entry) {
|
|
201
|
+
if (!Array.isArray(entry.tags)) {
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
204
|
+
return entry.tags.map((value) => asTrimmedString(value)).filter((value) => value !== void 0);
|
|
205
|
+
}
|
|
206
|
+
function hasProjectSlugSignal(entry, sessionProject) {
|
|
207
|
+
const texts = [
|
|
208
|
+
asTrimmedString(entry.subject),
|
|
209
|
+
asTrimmedString(entry.content),
|
|
210
|
+
getSourceText(entry),
|
|
211
|
+
...getTags(entry)
|
|
212
|
+
];
|
|
213
|
+
return texts.some((text) => text !== void 0 && containsNormalizedPhrase(text, sessionProject));
|
|
214
|
+
}
|
|
215
|
+
function hasProjectWorkflowTag(entry) {
|
|
216
|
+
return getTags(entry).some((tag) => PROJECT_SIGNAL_TAGS.has(normalizeSignalText(tag)));
|
|
217
|
+
}
|
|
218
|
+
function hasTechnicalSourceSignal(entry) {
|
|
219
|
+
const sourceText = getSourceText(entry);
|
|
220
|
+
if (!sourceText) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
return TECHNICAL_SOURCE_PATTERNS.some((pattern) => pattern.test(sourceText));
|
|
224
|
+
}
|
|
225
|
+
function isProjectWorthyOpenClawStoreEntry(entry, sessionProject) {
|
|
226
|
+
const candidate = entry && typeof entry === "object" ? entry : {};
|
|
227
|
+
const type = asTrimmedString(candidate.type)?.toLowerCase();
|
|
228
|
+
if (!type || !PROJECT_WORTHY_TYPES.has(type)) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
return hasProjectSlugSignal(candidate, sessionProject) || hasProjectWorkflowTag(candidate) || hasTechnicalSourceSignal(candidate);
|
|
232
|
+
}
|
|
233
|
+
function resolveProjectWorthySessionProject(entries, sessionProject) {
|
|
234
|
+
const project = asTrimmedString(sessionProject);
|
|
235
|
+
if (!project || !Array.isArray(entries) || entries.length === 0) {
|
|
236
|
+
return void 0;
|
|
237
|
+
}
|
|
238
|
+
for (const entry of entries) {
|
|
239
|
+
if (!isProjectWorthyOpenClawStoreEntry(entry, project)) {
|
|
240
|
+
return void 0;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return project;
|
|
244
|
+
}
|
|
245
|
+
async function resolveOpenClawWatcherSessionProjectState(sessionId, config) {
|
|
246
|
+
const normalizedSessionId = asTrimmedString(sessionId);
|
|
247
|
+
if (!normalizedSessionId) {
|
|
248
|
+
return { kind: "unset" };
|
|
249
|
+
}
|
|
250
|
+
return getSessionProjectState(normalizedSessionId, config);
|
|
251
|
+
}
|
|
252
|
+
function applyOpenClawWatcherProjectAttribution(entries, sessionProjectState, fallbackProject) {
|
|
253
|
+
const projectFallback = asTrimmedString(fallbackProject);
|
|
254
|
+
return entries.map((entry) => {
|
|
255
|
+
if (entry.project) {
|
|
256
|
+
return entry;
|
|
257
|
+
}
|
|
258
|
+
if (sessionProjectState.kind === "set") {
|
|
259
|
+
return isProjectWorthyOpenClawStoreEntry(entry, sessionProjectState.project) ? { ...entry, project: sessionProjectState.project } : entry;
|
|
260
|
+
}
|
|
261
|
+
if (sessionProjectState.kind === "cleared" || !projectFallback) {
|
|
262
|
+
return entry;
|
|
263
|
+
}
|
|
264
|
+
return { ...entry, project: projectFallback };
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
90
268
|
// src/db/review-queue.ts
|
|
91
269
|
import { randomUUID } from "crypto";
|
|
92
270
|
var REVIEW_REASONS = ["low_quality", "contradicted", "stale", "manual"];
|
|
@@ -286,199 +464,23 @@ async function rehabilitateEntry(db, entryId, floor = 0.3) {
|
|
|
286
464
|
});
|
|
287
465
|
}
|
|
288
466
|
|
|
289
|
-
// src/openclaw-plugin/session-project-state.ts
|
|
290
|
-
function readProjectState(row) {
|
|
291
|
-
if (!row || typeof row !== "object") {
|
|
292
|
-
return { kind: "unset" };
|
|
293
|
-
}
|
|
294
|
-
const record = row;
|
|
295
|
-
const normalizedProject = typeof record.project === "string" ? normalizeProject(record.project) : null;
|
|
296
|
-
const rawState = typeof record.state === "string" ? record.state.trim().toLowerCase() : "";
|
|
297
|
-
if (rawState === "cleared") {
|
|
298
|
-
return { kind: "cleared" };
|
|
299
|
-
}
|
|
300
|
-
if (normalizedProject) {
|
|
301
|
-
return { kind: "set", project: normalizedProject };
|
|
302
|
-
}
|
|
303
|
-
return rawState === "set" ? { kind: "cleared" } : { kind: "unset" };
|
|
304
|
-
}
|
|
305
|
-
async function getSessionProjectState(sessionKey, config) {
|
|
306
|
-
const db = await ensurePluginDb(config);
|
|
307
|
-
const result = await db.execute({
|
|
308
|
-
sql: "SELECT project, state FROM session_projects WHERE session_key = ? LIMIT 1",
|
|
309
|
-
args: [sessionKey]
|
|
310
|
-
});
|
|
311
|
-
return readProjectState(result.rows[0]);
|
|
312
|
-
}
|
|
313
|
-
async function getSessionProject(sessionKey, config) {
|
|
314
|
-
const state = await getSessionProjectState(sessionKey, config);
|
|
315
|
-
return state.kind === "set" ? state.project : null;
|
|
316
|
-
}
|
|
317
|
-
async function setSessionProject(sessionKey, project, config) {
|
|
318
|
-
const normalizedProject = normalizeProject(project);
|
|
319
|
-
if (!normalizedProject) {
|
|
320
|
-
throw new Error("Session project must not be empty after normalization.");
|
|
321
|
-
}
|
|
322
|
-
const db = await ensurePluginDb(config);
|
|
323
|
-
await db.execute({
|
|
324
|
-
sql: `
|
|
325
|
-
INSERT OR REPLACE INTO session_projects (session_key, project, state, updated_at)
|
|
326
|
-
VALUES (?, ?, 'set', ?)
|
|
327
|
-
`,
|
|
328
|
-
args: [sessionKey, normalizedProject, (/* @__PURE__ */ new Date()).toISOString()]
|
|
329
|
-
});
|
|
330
|
-
return normalizedProject;
|
|
331
|
-
}
|
|
332
|
-
async function clearSessionProject(sessionKey, config) {
|
|
333
|
-
const db = await ensurePluginDb(config);
|
|
334
|
-
await db.execute({
|
|
335
|
-
sql: `
|
|
336
|
-
INSERT OR REPLACE INTO session_projects (session_key, project, state, updated_at)
|
|
337
|
-
VALUES (?, '', 'cleared', ?)
|
|
338
|
-
`,
|
|
339
|
-
args: [sessionKey, (/* @__PURE__ */ new Date()).toISOString()]
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// src/openclaw-plugin/project-attribution.ts
|
|
344
|
-
var PROJECT_WORTHY_TYPES = /* @__PURE__ */ new Set(["fact", "decision", "lesson", "todo"]);
|
|
345
|
-
var PROJECT_SIGNAL_TAGS = /* @__PURE__ */ new Set([
|
|
346
|
-
"architecture",
|
|
347
|
-
"codebase",
|
|
348
|
-
"issue",
|
|
349
|
-
"issues",
|
|
350
|
-
"pr",
|
|
351
|
-
"pull request",
|
|
352
|
-
"pull-request",
|
|
353
|
-
"pullrequest",
|
|
354
|
-
"repo",
|
|
355
|
-
"repository",
|
|
356
|
-
"ticket",
|
|
357
|
-
"tickets"
|
|
358
|
-
]);
|
|
359
|
-
var TECHNICAL_SOURCE_PATTERNS = [
|
|
360
|
-
/(^|[^a-z0-9])(repo|repository|codebase|github)([^a-z0-9]|$)/i,
|
|
361
|
-
/(^|[^a-z0-9])(issue|ticket|pr)(\s*#\d+|[^a-z0-9]|$)/i,
|
|
362
|
-
/(^|[^a-z0-9])pull request(\s*#\d+|[^a-z0-9]|$)/i,
|
|
363
|
-
/(^|[^a-z0-9])(src|tests|docs|packages)\/[^\s]+/i,
|
|
364
|
-
/(^|[^a-z0-9])(package\.json|pnpm-lock\.yaml|tsconfig\.json|vitest\.config)([^a-z0-9]|$)/i,
|
|
365
|
-
/\.(ts|tsx|js|jsx|mjs|cjs|sql|toml|yaml|yml)([^a-z0-9]|$)/i
|
|
366
|
-
];
|
|
367
|
-
function asTrimmedString(value) {
|
|
368
|
-
if (typeof value !== "string") {
|
|
369
|
-
return void 0;
|
|
370
|
-
}
|
|
371
|
-
const trimmed = value.trim();
|
|
372
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
373
|
-
}
|
|
374
|
-
function normalizeSignalText(value) {
|
|
375
|
-
return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim().replace(/\s+/g, " ");
|
|
376
|
-
}
|
|
377
|
-
function containsNormalizedPhrase(text, phrase) {
|
|
378
|
-
const normalizedText = normalizeSignalText(text);
|
|
379
|
-
const normalizedPhrase = normalizeSignalText(phrase);
|
|
380
|
-
if (!normalizedText || !normalizedPhrase) {
|
|
381
|
-
return false;
|
|
382
|
-
}
|
|
383
|
-
return ` ${normalizedText} `.includes(` ${normalizedPhrase} `);
|
|
384
|
-
}
|
|
385
|
-
function getSourceText(entry) {
|
|
386
|
-
const source = entry.source;
|
|
387
|
-
if (typeof source === "string") {
|
|
388
|
-
return asTrimmedString(source);
|
|
389
|
-
}
|
|
390
|
-
if (!source || typeof source !== "object") {
|
|
391
|
-
return void 0;
|
|
392
|
-
}
|
|
393
|
-
const sourceRecord = source;
|
|
394
|
-
const file = asTrimmedString(sourceRecord.file);
|
|
395
|
-
const context = asTrimmedString(sourceRecord.context);
|
|
396
|
-
const text = [file, context].filter((value) => value !== void 0).join(" ");
|
|
397
|
-
return text.length > 0 ? text : void 0;
|
|
398
|
-
}
|
|
399
|
-
function getTags(entry) {
|
|
400
|
-
if (!Array.isArray(entry.tags)) {
|
|
401
|
-
return [];
|
|
402
|
-
}
|
|
403
|
-
return entry.tags.map((value) => asTrimmedString(value)).filter((value) => value !== void 0);
|
|
404
|
-
}
|
|
405
|
-
function hasProjectSlugSignal(entry, sessionProject) {
|
|
406
|
-
const texts = [
|
|
407
|
-
asTrimmedString(entry.subject),
|
|
408
|
-
asTrimmedString(entry.content),
|
|
409
|
-
getSourceText(entry),
|
|
410
|
-
...getTags(entry)
|
|
411
|
-
];
|
|
412
|
-
return texts.some((text) => text !== void 0 && containsNormalizedPhrase(text, sessionProject));
|
|
413
|
-
}
|
|
414
|
-
function hasProjectWorkflowTag(entry) {
|
|
415
|
-
return getTags(entry).some((tag) => PROJECT_SIGNAL_TAGS.has(normalizeSignalText(tag)));
|
|
416
|
-
}
|
|
417
|
-
function hasTechnicalSourceSignal(entry) {
|
|
418
|
-
const sourceText = getSourceText(entry);
|
|
419
|
-
if (!sourceText) {
|
|
420
|
-
return false;
|
|
421
|
-
}
|
|
422
|
-
return TECHNICAL_SOURCE_PATTERNS.some((pattern) => pattern.test(sourceText));
|
|
423
|
-
}
|
|
424
|
-
function isProjectWorthyOpenClawStoreEntry(entry, sessionProject) {
|
|
425
|
-
const candidate = entry && typeof entry === "object" ? entry : {};
|
|
426
|
-
const type = asTrimmedString(candidate.type)?.toLowerCase();
|
|
427
|
-
if (!type || !PROJECT_WORTHY_TYPES.has(type)) {
|
|
428
|
-
return false;
|
|
429
|
-
}
|
|
430
|
-
return hasProjectSlugSignal(candidate, sessionProject) || hasProjectWorkflowTag(candidate) || hasTechnicalSourceSignal(candidate);
|
|
431
|
-
}
|
|
432
|
-
function resolveProjectWorthySessionProject(entries, sessionProject) {
|
|
433
|
-
const project = asTrimmedString(sessionProject);
|
|
434
|
-
if (!project || !Array.isArray(entries) || entries.length === 0) {
|
|
435
|
-
return void 0;
|
|
436
|
-
}
|
|
437
|
-
for (const entry of entries) {
|
|
438
|
-
if (!isProjectWorthyOpenClawStoreEntry(entry, project)) {
|
|
439
|
-
return void 0;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
return project;
|
|
443
|
-
}
|
|
444
|
-
async function resolveOpenClawWatcherSessionProjectState(sessionId, config) {
|
|
445
|
-
const normalizedSessionId = asTrimmedString(sessionId);
|
|
446
|
-
if (!normalizedSessionId) {
|
|
447
|
-
return { kind: "unset" };
|
|
448
|
-
}
|
|
449
|
-
return getSessionProjectState(normalizedSessionId, config);
|
|
450
|
-
}
|
|
451
|
-
function applyOpenClawWatcherProjectAttribution(entries, sessionProjectState, fallbackProject) {
|
|
452
|
-
const projectFallback = asTrimmedString(fallbackProject);
|
|
453
|
-
return entries.map((entry) => {
|
|
454
|
-
if (entry.project) {
|
|
455
|
-
return entry;
|
|
456
|
-
}
|
|
457
|
-
if (sessionProjectState.kind === "set") {
|
|
458
|
-
return isProjectWorthyOpenClawStoreEntry(entry, sessionProjectState.project) ? { ...entry, project: sessionProjectState.project } : entry;
|
|
459
|
-
}
|
|
460
|
-
if (sessionProjectState.kind === "cleared" || !projectFallback) {
|
|
461
|
-
return entry;
|
|
462
|
-
}
|
|
463
|
-
return { ...entry, project: projectFallback };
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
|
|
467
467
|
export {
|
|
468
|
-
|
|
469
|
-
resolveReview,
|
|
470
|
-
checkAndFlagLowQuality,
|
|
471
|
-
getPendingReviewById,
|
|
472
|
-
getPendingReviewCountsByReason,
|
|
473
|
-
getOldestPendingReviewCreatedAt,
|
|
474
|
-
rehabilitateEntry,
|
|
468
|
+
ensurePluginDbTables,
|
|
475
469
|
ensurePluginDb,
|
|
476
470
|
clearPluginDbState,
|
|
477
471
|
getSessionProjectState,
|
|
478
472
|
getSessionProject,
|
|
479
473
|
setSessionProject,
|
|
480
474
|
clearSessionProject,
|
|
475
|
+
isProjectWorthyOpenClawStoreEntry,
|
|
481
476
|
resolveProjectWorthySessionProject,
|
|
482
477
|
resolveOpenClawWatcherSessionProjectState,
|
|
483
|
-
applyOpenClawWatcherProjectAttribution
|
|
478
|
+
applyOpenClawWatcherProjectAttribution,
|
|
479
|
+
getPendingReviews,
|
|
480
|
+
resolveReview,
|
|
481
|
+
checkAndFlagLowQuality,
|
|
482
|
+
getPendingReviewById,
|
|
483
|
+
getPendingReviewCountsByReason,
|
|
484
|
+
getOldestPendingReviewCreatedAt,
|
|
485
|
+
rehabilitateEntry
|
|
484
486
|
};
|
|
@@ -17,14 +17,14 @@ import {
|
|
|
17
17
|
runSimpleStream,
|
|
18
18
|
toErrorMessage,
|
|
19
19
|
walCheckpoint
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-HEE4JOTJ.js";
|
|
21
21
|
import {
|
|
22
22
|
MILLISECONDS_PER_DAY,
|
|
23
23
|
getCoRecallNeighbors,
|
|
24
24
|
parseDaysBetween,
|
|
25
25
|
toNumber,
|
|
26
26
|
toStringValue
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-UGIJJOPV.js";
|
|
28
28
|
|
|
29
29
|
// src/utils/parse.ts
|
|
30
30
|
function parsePositiveInt(value, fallback, label) {
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
1
7
|
// src/utils/entry-utils.ts
|
|
2
8
|
var MILLISECONDS_PER_DAY = 1e3 * 60 * 60 * 24;
|
|
3
9
|
function toNumber(value) {
|
|
@@ -321,6 +327,7 @@ async function getTopCoRecallEdges(db, limit = 20) {
|
|
|
321
327
|
}
|
|
322
328
|
|
|
323
329
|
export {
|
|
330
|
+
__export,
|
|
324
331
|
MILLISECONDS_PER_DAY,
|
|
325
332
|
toNumber,
|
|
326
333
|
toStringValue,
|