Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 4,917 Bytes
1778c9e d7cd63b e657b46 1778c9e d7cd63b dab40ed 52c6f5c dab40ed 1778c9e e657b46 1778c9e e657b46 1778c9e e657b46 1778c9e d7cd63b 1778c9e d7cd63b 1778c9e d7cd63b 1778c9e dab40ed 6dd3875 1778c9e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
import { idb } from "$lib/remult.js";
import { dequal } from "dequal";
import { Entity, Fields, repo, type MembersOnly } from "remult";
import { PersistedState } from "runed";
import { checkpoints } from "./checkpoints.svelte";
import { conversations } from "./conversations.svelte";
import { createInit } from "$lib/spells/create-init.svelte";
@Entity("project")
export class ProjectEntity {
@Fields.cuid()
id!: string;
@Fields.string()
name!: string;
@Fields.string()
systemMessage?: string;
@Fields.json()
enabledMCPs?: string[];
@Fields.string()
branchedFromId?: string | null;
@Fields.number()
branchedFromMessageIndex?: number | null;
}
export type ProjectEntityMembers = MembersOnly<ProjectEntity>;
const projectsRepo = repo(ProjectEntity, idb);
const LOCAL_STORAGE_KEY = "hf_inf_pg_active_pid";
export const DEFAULT_PROJECT_ID = "default";
const defaultProj = projectsRepo.create({ id: DEFAULT_PROJECT_ID, name: "Default" });
class Projects {
#projects: Record<ProjectEntity["id"], ProjectEntity> = $state({ default: defaultProj });
#activeId = new PersistedState(LOCAL_STORAGE_KEY, "default");
get activeId() {
return this.#activeId.current;
}
set activeId(id: string) {
this.#activeId.current = id;
}
init = createInit(async () => {
const res = await projectsRepo.find();
if (!res.some(p => p.id === this.activeId)) this.activeId === DEFAULT_PROJECT_ID;
res.forEach(p => {
if (dequal(this.#projects[p.id], p)) return;
this.#projects[p.id] = p;
});
});
async create(args: Omit<ProjectEntity, "id">): Promise<string> {
const p = await projectsRepo.save({ ...args });
this.#projects[p.id] = p;
return p.id;
}
saveProject = async (args: { name: string; moveCheckpoints?: boolean }) => {
const defaultProject = this.all.find(p => p.id === DEFAULT_PROJECT_ID);
if (!defaultProject) return;
const id = await this.create({ name: args.name, systemMessage: defaultProject.systemMessage });
if (args.moveCheckpoints) {
checkpoints.migrate(defaultProject.id, id);
}
// conversations.migrate(defaultProject.id, id).then(_ => (this.#activeId.current = id));
conversations.migrate(defaultProject.id, id).then(() => {
this.activeId = id;
});
return id;
};
get current() {
return this.#projects[this.activeId];
}
get all() {
return Object.values(this.#projects);
}
async update(data: ProjectEntity) {
if (!data.id) return;
await projectsRepo.upsert({ where: { id: data.id }, set: data });
this.#projects[data.id] = { ...data };
}
async delete(id: string) {
if (!id) return;
await projectsRepo.delete(id);
await conversations.deleteAllFrom(id);
delete this.#projects[id];
if (this.activeId === id) {
this.activeId = DEFAULT_PROJECT_ID;
}
}
branch = async (fromProjectId: string, messageIndex: number): Promise<string> => {
const fromProject = this.#projects[fromProjectId];
if (!fromProject) throw new Error("Source project not found");
// Create new project with branching info
const newProjectId = await this.create({
name: `${fromProject.name} (branch)`,
systemMessage: fromProject.systemMessage,
branchedFromId: fromProjectId,
branchedFromMessageIndex: messageIndex,
});
// Copy conversations up to the specified message index
await conversations.duplicateUpToMessage(fromProjectId, newProjectId, messageIndex);
// Switch to the new project
this.activeId = newProjectId;
return newProjectId;
};
getBranchedFromProject = (projectId: string) => {
const project = this.#projects[projectId];
if (!project?.branchedFromId) return null;
const originalProject = this.#projects[project.branchedFromId];
return originalProject;
};
clearBranchStatus = async (projectId: string) => {
const project = this.#projects[projectId];
if (!project?.branchedFromId) return;
await this.update({
...project,
branchedFromId: null,
branchedFromMessageIndex: null,
});
};
getBranchChildren = (projectId: string) => {
return this.all.filter(p => p.branchedFromId === projectId);
};
getBranchDepth = (projectId: string): number => {
const project = this.#projects[projectId];
if (!project?.branchedFromId) return 0;
return 1 + this.getBranchDepth(project.branchedFromId);
};
getBranchRoot = (projectId: string) => {
let current = this.#projects[projectId];
while (current?.branchedFromId) {
current = this.#projects[current.branchedFromId];
}
return current;
};
getAllBranchesInTree = (rootId: string): typeof this.all => {
const result: typeof this.all = [];
const root = this.#projects[rootId];
if (root) result.push(root);
const addChildren = (parentId: string) => {
const children = this.getBranchChildren(parentId);
children.forEach(child => {
result.push(child);
addChildren(child.id);
});
};
addChildren(rootId);
return result;
};
}
export const projects = new Projects();
|