feat: add scoped history and artifacts
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { join } from "node:path";
|
||||
|
||||
import { SessionTopicStore } from "./topic-store.js";
|
||||
import { config } from "../config.js";
|
||||
import { type SessionWorkspaceStore } from "./workspace-store.js";
|
||||
import {
|
||||
@@ -30,6 +31,7 @@ export type SessionRecord = {
|
||||
requestId?: string;
|
||||
modelId?: string;
|
||||
title?: string;
|
||||
topicId?: string | null;
|
||||
triggerId?: string;
|
||||
triggerSource?: string;
|
||||
triggerSubjectType?: string;
|
||||
@@ -63,14 +65,17 @@ type EnsureSessionMetadataInput = SessionMetadataContext & {
|
||||
runId?: string;
|
||||
requestId?: string;
|
||||
modelId?: string;
|
||||
topicId?: string;
|
||||
};
|
||||
|
||||
export class SessionMetadataStore {
|
||||
readonly topics: SessionTopicStore;
|
||||
private readonly ensureQueues = new Map<string, Promise<void>>();
|
||||
private index?: Map<string, Map<string, SessionRecord>>;
|
||||
private indexLoading?: Promise<void>;
|
||||
private indexVersion = 0;
|
||||
constructor(private readonly baseDir = config.SESSION_METADATA_STORAGE_DIR, private readonly workspaces?: SessionWorkspaceStore) {
|
||||
this.topics = new SessionTopicStore(join(baseDir, "topics"));
|
||||
workspaces?.setDeletionCheck(async (context) => Boolean((await this.get(context, context.sessionId, { includeDeleted: true }))?.deletedAt));
|
||||
}
|
||||
|
||||
@@ -133,6 +138,7 @@ export class SessionMetadataStore {
|
||||
runId: input.runId?.trim(),
|
||||
requestId: input.requestId?.trim(),
|
||||
modelId: input.modelId?.trim(),
|
||||
topicId: input.topicId,
|
||||
...(input.trigger ? {
|
||||
triggerId: input.trigger.triggerId,
|
||||
triggerSource: input.trigger.source,
|
||||
@@ -175,7 +181,7 @@ export class SessionMetadataStore {
|
||||
|
||||
async touch(
|
||||
record: SessionRecord,
|
||||
updates: Partial<Pick<SessionRecord, "title" | "status">> = {},
|
||||
updates: Partial<Pick<SessionRecord, "title" | "status" | "topicId">> = {},
|
||||
) {
|
||||
return this.serialize(record.sessionId, async () => {
|
||||
const current = await this.get({ ...record, userId: record.ownerUserId }, record.sessionId);
|
||||
@@ -314,12 +320,13 @@ const matchesContext = (record: SessionRecord, context: SessionMetadataContext)
|
||||
(context.projectId === undefined || record.projectId === context.projectId);
|
||||
|
||||
const normalizeSessionUpdates = (
|
||||
updates: Partial<Pick<SessionRecord, "title" | "status">>,
|
||||
updates: Partial<Pick<SessionRecord, "title" | "status" | "topicId">>,
|
||||
) => {
|
||||
const normalized: Partial<Pick<SessionRecord, "title" | "status">> = {};
|
||||
const normalized: Partial<Pick<SessionRecord, "title" | "status" | "topicId">> = {};
|
||||
if (updates.status === "active" || updates.status === "archived") {
|
||||
normalized.status = updates.status;
|
||||
}
|
||||
if (updates.topicId === null || typeof updates.topicId === "string") normalized.topicId = updates.topicId;
|
||||
if (typeof updates.title === "string") {
|
||||
const trimmed = updates.title.trim();
|
||||
if (trimmed) {
|
||||
|
||||
Reference in New Issue
Block a user