@@ -7,6 +7,7 @@
|
||||
- Memory: allow custom OpenAI-compatible embedding endpoints for memory search (remote baseUrl/apiKey/headers). (#819 — thanks @mukhtharcm)
|
||||
|
||||
### Fixes
|
||||
- System events: include local timestamps when events are injected into prompts. (#245 — thanks @thewilloftheshadow)
|
||||
- Cron: accept `jobId` aliases for cron update/run/remove params in gateway validation. (#252 — thanks @thewilloftheshadow)
|
||||
- Models/Google: normalize Gemini 3 model ids to preview variants before runtime selection. (#795 — thanks @thewilloftheshadow)
|
||||
- TUI: keep the last streamed response instead of replacing it with “(no output)”. (#747 — thanks @thewilloftheshadow)
|
||||
|
||||
43
src/auto-reply/reply/session-updates.test.ts
Normal file
43
src/auto-reply/reply/session-updates.test.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import {
|
||||
enqueueSystemEvent,
|
||||
resetSystemEventsForTest,
|
||||
} from "../../infra/system-events.js";
|
||||
import { prependSystemEvents } from "./session-updates.js";
|
||||
|
||||
describe("prependSystemEvents", () => {
|
||||
it("adds a local timestamp to queued system events", async () => {
|
||||
vi.useFakeTimers();
|
||||
const timestamp = new Date("2026-01-12T20:19:17");
|
||||
vi.setSystemTime(timestamp);
|
||||
|
||||
enqueueSystemEvent("Model switched.", { sessionKey: "agent:main:main" });
|
||||
|
||||
const result = await prependSystemEvents({
|
||||
cfg: {} as ClawdbotConfig,
|
||||
sessionKey: "agent:main:main",
|
||||
isMainSession: false,
|
||||
isNewSession: false,
|
||||
prefixedBodyBase: "User: hi",
|
||||
});
|
||||
|
||||
const expectedTimestamp = timestamp.toLocaleString("en-US", {
|
||||
hour12: false,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
});
|
||||
|
||||
expect(result).toContain(
|
||||
`System: [${expectedTimestamp}] Model switched.`,
|
||||
);
|
||||
|
||||
resetSystemEventsForTest();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@ import { buildWorkspaceSkillSnapshot } from "../../agents/skills.js";
|
||||
import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import { type SessionEntry, saveSessionStore } from "../../config/sessions.js";
|
||||
import { buildProviderSummary } from "../../infra/provider-summary.js";
|
||||
import { drainSystemEvents } from "../../infra/system-events.js";
|
||||
import { drainSystemEventEntries } from "../../infra/system-events.js";
|
||||
|
||||
export async function prependSystemEvents(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
@@ -25,10 +25,27 @@ export async function prependSystemEvents(params: {
|
||||
return trimmed;
|
||||
};
|
||||
|
||||
const formatSystemEventTimestamp = (ts: number) =>
|
||||
new Date(ts).toLocaleString("en-US", {
|
||||
hour12: false,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
});
|
||||
|
||||
const systemLines: string[] = [];
|
||||
const queued = drainSystemEvents(params.sessionKey);
|
||||
const queued = drainSystemEventEntries(params.sessionKey);
|
||||
systemLines.push(
|
||||
...queued.map(compactSystemEvent).filter((v): v is string => Boolean(v)),
|
||||
...queued
|
||||
.map((event) => {
|
||||
const compacted = compactSystemEvent(event.text);
|
||||
if (!compacted) return null;
|
||||
return `[${formatSystemEventTimestamp(event.ts)}] ${compacted}`;
|
||||
})
|
||||
.filter((v): v is string => Boolean(v)),
|
||||
);
|
||||
if (params.isMainSession && params.isNewSession) {
|
||||
const summary = await buildProviderSummary(params.cfg);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// prefixed to the next prompt. We intentionally avoid persistence to keep
|
||||
// events ephemeral. Events are session-scoped and require an explicit key.
|
||||
|
||||
type SystemEvent = { text: string; ts: number };
|
||||
export type SystemEvent = { text: string; ts: number };
|
||||
|
||||
const MAX_EVENTS = 20;
|
||||
|
||||
@@ -66,11 +66,11 @@ export function enqueueSystemEvent(text: string, options: SystemEventOptions) {
|
||||
if (entry.queue.length > MAX_EVENTS) entry.queue.shift();
|
||||
}
|
||||
|
||||
export function drainSystemEvents(sessionKey: string): string[] {
|
||||
export function drainSystemEventEntries(sessionKey: string): SystemEvent[] {
|
||||
const key = requireSessionKey(sessionKey);
|
||||
const entry = queues.get(key);
|
||||
if (!entry || entry.queue.length === 0) return [];
|
||||
const out = entry.queue.map((e) => e.text);
|
||||
const out = entry.queue.slice();
|
||||
entry.queue.length = 0;
|
||||
entry.lastText = null;
|
||||
entry.lastContextKey = null;
|
||||
@@ -78,6 +78,10 @@ export function drainSystemEvents(sessionKey: string): string[] {
|
||||
return out;
|
||||
}
|
||||
|
||||
export function drainSystemEvents(sessionKey: string): string[] {
|
||||
return drainSystemEventEntries(sessionKey).map((event) => event.text);
|
||||
}
|
||||
|
||||
export function peekSystemEvents(sessionKey: string): string[] {
|
||||
const key = requireSessionKey(sessionKey);
|
||||
return queues.get(key)?.queue.map((e) => e.text) ?? [];
|
||||
|
||||
Reference in New Issue
Block a user