- Move src/ → plugin/ with subdirectories: - plugin/core/ (business logic, models, store, permissions, utils, memory) - plugin/tools/ (query, resources) - plugin/commands/ (placeholder for slash commands) - plugin/hooks/ (placeholder for lifecycle hooks) - plugin/index.ts (wiring layer only, no business logic) - Add install.mjs with --install, --uninstall, --openclaw-profile-path - Add skills/ and docs/ root directories - Move planning docs (PLAN.md, FEAT.md, AGENT_TASKS.md) to docs/ - Remove old scripts/install.sh - Update tsconfig rootDir: src → plugin - Update README.md and README.zh.md with new layout - Bump version to 0.2.0 - All tests pass
157 lines
4.0 KiB
TypeScript
157 lines
4.0 KiB
TypeScript
import { DEFAULT_STATE } from "../config/defaults";
|
|
import type {
|
|
Agent,
|
|
Department,
|
|
Identity,
|
|
Organization,
|
|
StoreState,
|
|
Supervisor,
|
|
Team
|
|
} from "../models/types";
|
|
import { readJsonFile, writeJsonFile } from "../utils/fs";
|
|
|
|
export class JsonStore {
|
|
private state: StoreState;
|
|
|
|
constructor(private readonly filePath: string) {
|
|
this.state = readJsonFile<StoreState>(filePath, DEFAULT_STATE);
|
|
}
|
|
|
|
save(): void {
|
|
writeJsonFile(this.filePath, this.state);
|
|
}
|
|
|
|
snapshot(): StoreState {
|
|
return JSON.parse(JSON.stringify(this.state)) as StoreState;
|
|
}
|
|
|
|
replace(state: StoreState): void {
|
|
this.state = JSON.parse(JSON.stringify(state)) as StoreState;
|
|
this.save();
|
|
}
|
|
|
|
addOrganization(org: Organization): Organization {
|
|
this.state.organizations.push(org);
|
|
this.save();
|
|
return org;
|
|
}
|
|
|
|
addDepartment(dept: Department): Department {
|
|
this.state.departments.push(dept);
|
|
this.save();
|
|
return dept;
|
|
}
|
|
|
|
renameDepartment(deptId: string, name: string): Department | undefined {
|
|
const dept = this.findDepartment(deptId);
|
|
if (!dept) return undefined;
|
|
dept.name = name;
|
|
this.save();
|
|
return dept;
|
|
}
|
|
|
|
deleteDepartment(deptId: string): boolean {
|
|
const before = this.state.departments.length;
|
|
this.state.departments = this.state.departments.filter((d) => d.id !== deptId);
|
|
this.state.teams = this.state.teams.filter((t) => t.deptId !== deptId);
|
|
this.state.identities = this.state.identities.filter((i) => i.deptId !== deptId);
|
|
const changed = this.state.departments.length !== before;
|
|
if (changed) this.save();
|
|
return changed;
|
|
}
|
|
|
|
addTeam(team: Team): Team {
|
|
this.state.teams.push(team);
|
|
this.save();
|
|
return team;
|
|
}
|
|
|
|
renameTeam(teamId: string, name: string): Team | undefined {
|
|
const team = this.findTeam(teamId);
|
|
if (!team) return undefined;
|
|
team.name = name;
|
|
this.save();
|
|
return team;
|
|
}
|
|
|
|
migrateTeam(teamId: string, newDeptId: string): Team | undefined {
|
|
const team = this.findTeam(teamId);
|
|
if (!team) return undefined;
|
|
team.deptId = newDeptId;
|
|
for (const identity of this.state.identities) {
|
|
if (identity.teamId === teamId) identity.deptId = newDeptId;
|
|
}
|
|
this.save();
|
|
return team;
|
|
}
|
|
|
|
deleteTeam(teamId: string): boolean {
|
|
const before = this.state.teams.length;
|
|
this.state.teams = this.state.teams.filter((t) => t.id !== teamId);
|
|
this.state.identities = this.state.identities.filter((i) => i.teamId !== teamId);
|
|
const changed = before !== this.state.teams.length;
|
|
if (changed) this.save();
|
|
return changed;
|
|
}
|
|
|
|
addAgent(agent: Agent): Agent {
|
|
this.state.agents.push(agent);
|
|
this.save();
|
|
return agent;
|
|
}
|
|
|
|
addIdentity(identity: Identity): Identity {
|
|
this.state.identities.push(identity);
|
|
this.save();
|
|
return identity;
|
|
}
|
|
|
|
upsertSupervisor(rel: Supervisor): Supervisor {
|
|
const idx = this.state.supervisors.findIndex((x) => x.agentId === rel.agentId);
|
|
if (idx >= 0) this.state.supervisors[idx] = rel;
|
|
else this.state.supervisors.push(rel);
|
|
this.save();
|
|
return rel;
|
|
}
|
|
|
|
findAgent(agentId: string): Agent | undefined {
|
|
return this.state.agents.find((a) => a.id === agentId);
|
|
}
|
|
|
|
findOrganization(orgId: string): Organization | undefined {
|
|
return this.state.organizations.find((o) => o.id === orgId);
|
|
}
|
|
|
|
listOrganizations(): Organization[] {
|
|
return this.state.organizations;
|
|
}
|
|
|
|
findDepartment(deptId: string): Department | undefined {
|
|
return this.state.departments.find((d) => d.id === deptId);
|
|
}
|
|
|
|
listDepartments(): Department[] {
|
|
return this.state.departments;
|
|
}
|
|
|
|
findTeam(teamId: string): Team | undefined {
|
|
return this.state.teams.find((t) => t.id === teamId);
|
|
}
|
|
|
|
listTeams(): Team[] {
|
|
return this.state.teams;
|
|
}
|
|
|
|
listAgents(): Agent[] {
|
|
return this.state.agents;
|
|
}
|
|
|
|
listIdentities(): Identity[] {
|
|
return this.state.identities;
|
|
}
|
|
|
|
findSupervisor(agentId: string): Supervisor | undefined {
|
|
return this.state.supervisors.find((s) => s.agentId === agentId);
|
|
}
|
|
}
|