chore: remove internal docs from repo, update public documentation

Remove docs/superpowers/, .claude/ config, and PRD.md from version
control (kept locally via .gitignore). Update README, CHANGELOG,
VitePress docs, and .env.example to reflect recent features: Files
page, teams, admin settings, persistent storage, and various API
improvements.
This commit is contained in:
Siddharth Kumar Sah
2026-03-26 01:11:40 +08:00
parent 3b4f522bf4
commit 627ff8a82c
99 changed files with 853 additions and 15277 deletions
+6 -1
View File
@@ -150,7 +150,12 @@ export async function registerPipelineRoutes(app: FastifyInstance): Promise<void
try {
for (let i = 0; i < pipeline.steps.length; i++) {
const step = pipeline.steps[i];
const toolConfig = getToolConfig(step.toolId)!;
const toolConfig = getToolConfig(step.toolId);
if (!toolConfig) {
return reply
.status(400)
.send({ error: `Step ${i + 1}: Tool "${step.toolId}" not found` });
}
// Parse settings through the schema to apply defaults
const settings = toolConfig.settingsSchema.parse(step.settings);
+2 -2
View File
@@ -57,7 +57,7 @@ export async function teamsRoutes(app: FastifyInstance): Promise<void> {
return reply.status(400).send({ error: nameError, code: "VALIDATION_ERROR" });
}
const trimmedName = (body!.name as string).trim();
const trimmedName = (body?.name ?? "").trim();
// Check for duplicate name (case-insensitive)
const existing = db
@@ -97,7 +97,7 @@ export async function teamsRoutes(app: FastifyInstance): Promise<void> {
return reply.status(400).send({ error: nameError, code: "VALIDATION_ERROR" });
}
const trimmedName = (body!.name as string).trim();
const trimmedName = (body?.name ?? "").trim();
// Check for duplicate name (case-insensitive), excluding current team
const duplicate = db
+15 -6
View File
@@ -24,18 +24,27 @@ export interface ToolRouteConfig<T> {
) => Promise<{ buffer: Buffer; filename: string; contentType: string }>;
}
/** Type-erased config stored in the registry (settings type is widened to avoid variance issues). */
export interface AnyToolRouteConfig {
toolId: string;
settingsSchema: z.ZodType<unknown, z.ZodTypeDef, unknown>;
process: (
inputBuffer: Buffer,
settings: unknown,
filename: string,
) => Promise<{ buffer: Buffer; filename: string; contentType: string }>;
}
/**
* In-memory registry of all tool configs, keyed by toolId.
* Populated by createToolRoute() calls; used by batch processing.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const toolRegistry = new Map<string, ToolRouteConfig<any>>();
const toolRegistry = new Map<string, AnyToolRouteConfig>();
/**
* Retrieve a registered tool config by its ID.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function getToolConfig(toolId: string): ToolRouteConfig<any> | undefined {
export function getToolConfig(toolId: string): AnyToolRouteConfig | undefined {
return toolRegistry.get(toolId);
}
@@ -55,8 +64,8 @@ export function getToolConfig(toolId: string): ToolRouteConfig<any> | undefined
* - Response formatting
*/
export function createToolRoute<T>(app: FastifyInstance, config: ToolRouteConfig<T>): void {
// Register in the tool registry for batch processing
toolRegistry.set(config.toolId, config);
// Register in the tool registry for batch processing (cast to type-erased form)
toolRegistry.set(config.toolId, config as AnyToolRouteConfig);
app.post(
`/api/v1/tools/${config.toolId}`,
+3 -2
View File
@@ -60,10 +60,11 @@ export function registerBlurFaces(app: FastifyInstance) {
await writeFile(inputPath, fileBuffer);
// Process
const onProgress = clientJobId
const jobIdForProgress = clientJobId;
const onProgress = jobIdForProgress
? (percent: number, stage: string) => {
updateSingleFileProgress({
jobId: clientJobId!,
jobId: jobIdForProgress,
phase: "processing",
stage,
percent,
+3 -2
View File
@@ -71,10 +71,11 @@ export function registerEraseObject(app: FastifyInstance) {
await writeFile(inputPath, imageBuffer);
// Process
const onProgress = clientJobId
const jobIdForProgress = clientJobId;
const onProgress = jobIdForProgress
? (percent: number, stage: string) => {
updateSingleFileProgress({
jobId: clientJobId!,
jobId: jobIdForProgress,
phase: "processing",
stage,
percent,
+3 -2
View File
@@ -73,10 +73,11 @@ export function registerOcr(app: FastifyInstance) {
const jobId = randomUUID();
const workspacePath = await createWorkspace(jobId);
const onProgress = clientJobId
const jobIdForProgress = clientJobId;
const onProgress = jobIdForProgress
? (percent: number, stage: string) => {
updateSingleFileProgress({
jobId: clientJobId!,
jobId: jobIdForProgress,
phase: "processing",
stage,
percent,
@@ -62,10 +62,11 @@ export function registerRemoveBackground(app: FastifyInstance) {
await writeFile(inputPath, fileBuffer);
// Process
const onProgress = clientJobId
const jobIdForProgress = clientJobId;
const onProgress = jobIdForProgress
? (percent: number, stage: string) => {
updateSingleFileProgress({
jobId: clientJobId!,
jobId: jobIdForProgress,
phase: "processing",
stage,
percent,
+1 -3
View File
@@ -75,9 +75,7 @@ function parseXmp(xmpBuffer: Buffer): Record<string, string> {
const xml = xmpBuffer.toString("utf-8");
const result: Record<string, string> = {};
const attrRegex = /(\w+:\w+)="([^"]+)"/g;
let match;
while ((match = attrRegex.exec(xml)) !== null) {
for (const match of xml.matchAll(/(\w+:\w+)="([^"]+)"/g)) {
const key = match[1];
if (key.startsWith("xmlns:") || key.startsWith("rdf:")) continue;
result[key] = match[2];
+3 -2
View File
@@ -62,10 +62,11 @@ export function registerUpscale(app: FastifyInstance) {
await writeFile(inputPath, fileBuffer);
// Process
const onProgress = clientJobId
const jobIdForProgress = clientJobId;
const onProgress = jobIdForProgress
? (percent: number, stage: string) => {
updateSingleFileProgress({
jobId: clientJobId!,
jobId: jobIdForProgress,
phase: "processing",
stage,
percent,