Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687import type { Agent } from "agents";import { defaultSkillPermissions, skillPermissionChoices, skillPermissionRevision, type SkillPermissionSnapshot, type SkillPermissionAudit,} from "../shared/skill-permissions";import type { SkillIdentity } from "../shared/skill-management";import type { SkillListing } from "../shared/skills";import { OperationFailure } from "./operation-result";
export interface SkillPermissionSubject { skill: SkillListing; installationId: string;}
export class SkillPermissionStore { constructor( private readonly sql: Agent["sql"], private readonly storage: Pick<DurableObjectStorage, "transactionSync">, private readonly current: ( identity: SkillIdentity, ) => SkillPermissionSubject, ) {}
initialize() { this .sql`CREATE TABLE IF NOT EXISTS flarebot_skill_permissions (source TEXT NOT NULL, name TEXT NOT NULL, installation TEXT NOT NULL, fingerprint TEXT NOT NULL, revision INTEGER NOT NULL, choices TEXT NOT NULL, PRIMARY KEY(source, name))`; this .sql`CREATE TABLE IF NOT EXISTS flarebot_skill_permission_audit (revision INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL, name TEXT NOT NULL, installation TEXT NOT NULL, fingerprint TEXT NOT NULL, timestamp TEXT NOT NULL, before_choices TEXT NOT NULL, after_choices TEXT NOT NULL)`; }
read(identity: SkillIdentity): SkillPermissionSnapshot { const subject = this.current(identity); const [row] = this.sql<{ revision: number; choices: string; }>`SELECT revision, choices FROM flarebot_skill_permissions WHERE source = ${identity.source} AND name = ${identity.name} AND installation = ${subject.installationId} AND fingerprint = ${identity.fingerprint}`; const audit = this.sql<{ revision: number; timestamp: string; before_choices: string; after_choices: string; }>`SELECT revision, timestamp, before_choices, after_choices FROM flarebot_skill_permission_audit WHERE source = ${identity.source} AND name = ${identity.name} AND installation = ${subject.installationId} AND fingerprint = ${identity.fingerprint} ORDER BY revision DESC LIMIT 20`; return { revision: row?.revision ?? 0, choices: row ? skillPermissionChoices.parse(JSON.parse(row.choices)) : { ...defaultSkillPermissions }, audit: audit.map((entry): SkillPermissionAudit => ({ revision: entry.revision, timestamp: entry.timestamp, before: skillPermissionChoices.parse(JSON.parse(entry.before_choices)), after: skillPermissionChoices.parse(JSON.parse(entry.after_choices)), })), }; }
update(identity: SkillIdentity, revision: number, value: unknown) { const choices = skillPermissionChoices.parse(value); skillPermissionRevision.parse(revision); return this.storage.transactionSync(() => { const subject = this.current(identity); const before = this.read(identity); if (before.revision !== revision) throw new OperationFailure("skill_permissions_changed"); if (JSON.stringify(before.choices) === JSON.stringify(choices)) return before; const [entry] = this.sql<{ revision: number; }>`INSERT INTO flarebot_skill_permission_audit (source, name, installation, fingerprint, timestamp, before_choices, after_choices) VALUES (${identity.source}, ${identity.name}, ${subject.installationId}, ${identity.fingerprint}, ${new Date().toISOString()}, ${JSON.stringify(before.choices)}, ${JSON.stringify(choices)}) RETURNING revision`; skillPermissionRevision.parse(entry.revision); this .sql`INSERT INTO flarebot_skill_permissions VALUES (${identity.source}, ${identity.name}, ${subject.installationId}, ${identity.fingerprint}, ${entry.revision}, ${JSON.stringify(choices)}) ON CONFLICT(source, name) DO UPDATE SET installation = excluded.installation, fingerprint = excluded.fingerprint, revision = excluded.revision, choices = excluded.choices`; this .sql`DELETE FROM flarebot_skill_permission_audit WHERE revision NOT IN (SELECT revision FROM flarebot_skill_permission_audit ORDER BY revision DESC LIMIT 256)`; return this.read(identity); }); }
remove(identity: SkillIdentity, installationId: string) { this .sql`DELETE FROM flarebot_skill_permissions WHERE source = ${identity.source} AND name = ${identity.name} AND installation = ${installationId}`; }}