mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-20 21:23:23 +00:00
fix(memory): accept embedded dreaming heartbeat tokens
This commit is contained in:
@@ -34,11 +34,11 @@ import type {
|
||||
MemoryRemHarnessOptions,
|
||||
MemorySearchCommandOptions,
|
||||
} from "./cli.types.js";
|
||||
import { previewRemDreaming, seedHistoricalDailyMemorySignals } from "./dreaming-phases.js";
|
||||
import { removeBackfillDiaryEntries, writeBackfillDiaryEntries } from "./dreaming-narrative.js";
|
||||
import { previewGroundedRemMarkdown } from "./rem-evidence.js";
|
||||
import { previewRemDreaming, seedHistoricalDailyMemorySignals } from "./dreaming-phases.js";
|
||||
import { asRecord } from "./dreaming-shared.js";
|
||||
import { resolveShortTermPromotionDreamingConfig } from "./dreaming.js";
|
||||
import { previewGroundedRemMarkdown } from "./rem-evidence.js";
|
||||
import {
|
||||
applyShortTermPromotions,
|
||||
auditShortTermPromotionArtifacts,
|
||||
@@ -154,7 +154,9 @@ async function createHistoricalRemHarnessWorkspace(params: {
|
||||
for (const filePath of sourceFiles) {
|
||||
await fs.copyFile(filePath, path.join(memoryDir, path.basename(filePath)));
|
||||
}
|
||||
const workspaceSourceFiles = sourceFiles.map((entry) => path.join(memoryDir, path.basename(entry)));
|
||||
const workspaceSourceFiles = sourceFiles.map((entry) =>
|
||||
path.join(memoryDir, path.basename(entry)),
|
||||
);
|
||||
const seeded = await seedHistoricalDailyMemorySignals({
|
||||
workspaceDir,
|
||||
filePaths: workspaceSourceFiles,
|
||||
@@ -1422,14 +1424,13 @@ export async function runMemoryRemHarness(opts: MemoryRemHarnessOptions) {
|
||||
workspaceDir,
|
||||
sourcePath: opts.path ? path.resolve(opts.path) : null,
|
||||
sourceFiles,
|
||||
historicalImport:
|
||||
opts.path
|
||||
? {
|
||||
importedFileCount,
|
||||
importedSignalCount,
|
||||
skippedPaths,
|
||||
}
|
||||
: null,
|
||||
historicalImport: opts.path
|
||||
? {
|
||||
importedFileCount,
|
||||
importedSignalCount,
|
||||
skippedPaths,
|
||||
}
|
||||
: null,
|
||||
remConfig,
|
||||
deepConfig: {
|
||||
minScore: deep.minScore,
|
||||
@@ -1497,7 +1498,7 @@ export async function runMemoryRemHarness(opts: MemoryRemHarnessOptions) {
|
||||
"",
|
||||
colorize(rich, theme.heading, "Grounded REM"),
|
||||
...groundedPreview.files.flatMap((file) => [
|
||||
colorize(rich, theme.label, file.path),
|
||||
colorize(rich, theme.muted, file.path),
|
||||
file.renderedMarkdown,
|
||||
"",
|
||||
]),
|
||||
@@ -1570,7 +1571,9 @@ export async function runMemoryRemBackfill(opts: MemoryRemBackfillOptions) {
|
||||
}
|
||||
|
||||
if (!opts.path) {
|
||||
defaultRuntime.error("Memory rem-backfill requires --path <file-or-dir> unless using --rollback.");
|
||||
defaultRuntime.error(
|
||||
"Memory rem-backfill requires --path <file-or-dir> unless using --rollback.",
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
@@ -1636,7 +1639,11 @@ export async function runMemoryRemBackfill(opts: MemoryRemBackfillOptions) {
|
||||
`${colorize(rich, theme.heading, "REM Backfill")} ${colorize(rich, theme.muted, `(${agentId})`)}`,
|
||||
colorize(rich, theme.muted, `workspace=${shortenHomePath(workspaceDir)}`),
|
||||
colorize(rich, theme.muted, `sourcePath=${shortenHomePath(path.resolve(opts.path))}`),
|
||||
colorize(rich, theme.muted, `historicalFiles=${sourceFiles.length} writtenEntries=${written.written} replacedEntries=${written.replaced}`),
|
||||
colorize(
|
||||
rich,
|
||||
theme.muted,
|
||||
`historicalFiles=${sourceFiles.length} writtenEntries=${written.written} replacedEntries=${written.replaced}`,
|
||||
),
|
||||
colorize(rich, theme.muted, `dreamsPath=${shortenHomePath(written.dreamsPath)}`),
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
@@ -1110,6 +1110,7 @@ describe("memory cli", () => {
|
||||
grounded?: {
|
||||
files?: Array<{
|
||||
renderedMarkdown?: string;
|
||||
reflections?: Array<{ text: string }>;
|
||||
}>;
|
||||
} | null;
|
||||
}>(writeJson);
|
||||
@@ -1162,6 +1163,7 @@ describe("memory cli", () => {
|
||||
grounded?: {
|
||||
files?: Array<{
|
||||
renderedMarkdown?: string;
|
||||
reflections?: Array<{ text: string }>;
|
||||
}>;
|
||||
} | null;
|
||||
}>(writeJson);
|
||||
@@ -1206,6 +1208,7 @@ describe("memory cli", () => {
|
||||
grounded?: {
|
||||
files?: Array<{
|
||||
renderedMarkdown?: string;
|
||||
reflections?: Array<{ text: string }>;
|
||||
}>;
|
||||
} | null;
|
||||
}>(writeJson);
|
||||
|
||||
@@ -29,6 +29,28 @@ import {
|
||||
} from "./short-term-promotion.js";
|
||||
|
||||
type Logger = Pick<OpenClawPluginApi["logger"], "info" | "warn" | "error">;
|
||||
type DreamingPhaseStorageConfig = {
|
||||
timezone?: string;
|
||||
storage: { mode: "inline" | "separate" | "both"; separateReports: boolean };
|
||||
};
|
||||
type RunPhaseIfTriggeredParams = {
|
||||
cleanedBody: string;
|
||||
trigger?: string;
|
||||
workspaceDir?: string;
|
||||
cfg?: OpenClawConfig;
|
||||
logger: Logger;
|
||||
subagent?: Parameters<typeof generateAndAppendDreamNarrative>[0]["subagent"];
|
||||
eventText: string;
|
||||
} & (
|
||||
| {
|
||||
phase: "light";
|
||||
config: MemoryLightDreamingConfig & DreamingPhaseStorageConfig;
|
||||
}
|
||||
| {
|
||||
phase: "rem";
|
||||
config: MemoryRemDreamingConfig & DreamingPhaseStorageConfig;
|
||||
}
|
||||
);
|
||||
const LIGHT_SLEEP_EVENT_TEXT = "__openclaw_memory_core_light_sleep__";
|
||||
const REM_SLEEP_EVENT_TEXT = "__openclaw_memory_core_rem_sleep__";
|
||||
const DAILY_MEMORY_FILENAME_RE = /^(\d{4}-\d{2}-\d{2})\.md$/;
|
||||
@@ -1102,7 +1124,9 @@ export async function seedHistoricalDailyMemorySignals(params: {
|
||||
importedSignalCount: number;
|
||||
skippedPaths: string[];
|
||||
}> {
|
||||
const normalizedPaths = [...new Set(params.filePaths.map((entry) => entry.trim()).filter(Boolean))];
|
||||
const normalizedPaths = [
|
||||
...new Set(params.filePaths.map((entry) => entry.trim()).filter(Boolean)),
|
||||
];
|
||||
if (normalizedPaths.length === 0) {
|
||||
return {
|
||||
importedFileCount: 0,
|
||||
@@ -1133,7 +1157,9 @@ export async function seedHistoricalDailyMemorySignals(params: {
|
||||
return a.filePath.localeCompare(b.filePath);
|
||||
});
|
||||
|
||||
const valid = resolved.filter((entry): entry is { filePath: string; day: string } => Boolean(entry.day));
|
||||
const valid = resolved.filter((entry): entry is { filePath: string; day: string } =>
|
||||
Boolean(entry.day),
|
||||
);
|
||||
const skippedPaths = resolved.filter((entry) => !entry.day).map((entry) => entry.filePath);
|
||||
const totalCap = Math.max(20, params.limit * 4);
|
||||
const perFileCap = Math.max(6, Math.ceil(totalCap / Math.max(1, valid.length)));
|
||||
@@ -1605,26 +1631,11 @@ export async function runDreamingSweepPhases(params: {
|
||||
}
|
||||
}
|
||||
|
||||
async function runPhaseIfTriggered(params: {
|
||||
cleanedBody: string;
|
||||
trigger?: string;
|
||||
workspaceDir?: string;
|
||||
cfg?: OpenClawConfig;
|
||||
logger: Logger;
|
||||
subagent?: Parameters<typeof generateAndAppendDreamNarrative>[0]["subagent"];
|
||||
phase: "light" | "rem";
|
||||
eventText: string;
|
||||
config:
|
||||
| (MemoryLightDreamingConfig & {
|
||||
timezone?: string;
|
||||
storage: { mode: "inline" | "separate" | "both"; separateReports: boolean };
|
||||
})
|
||||
| (MemoryRemDreamingConfig & {
|
||||
timezone?: string;
|
||||
storage: { mode: "inline" | "separate" | "both"; separateReports: boolean };
|
||||
});
|
||||
}): Promise<{ handled: true; reason: string } | undefined> {
|
||||
if (params.trigger !== "heartbeat" || params.cleanedBody.trim() !== params.eventText) {
|
||||
async function runPhaseIfTriggered(
|
||||
params: RunPhaseIfTriggeredParams,
|
||||
): Promise<{ handled: true; reason: string } | undefined> {
|
||||
const hasEventToken = params.cleanedBody.trim().split(/\s+/).includes(params.eventText);
|
||||
if (params.trigger !== "heartbeat" || !hasEventToken) {
|
||||
return undefined;
|
||||
}
|
||||
if (!params.config.enabled) {
|
||||
|
||||
@@ -70,6 +70,7 @@ type SettingsHost = {
|
||||
dreamingStatus: null;
|
||||
dreamingModeSaving: boolean;
|
||||
dreamDiaryLoading: boolean;
|
||||
dreamDiaryActionLoading: boolean;
|
||||
dreamDiaryError: string | null;
|
||||
dreamDiaryPath: string | null;
|
||||
dreamDiaryContent: string | null;
|
||||
|
||||
Reference in New Issue
Block a user