Restored from commit 52be710 (checkpoint before qwen oauth + todo roller): Enhanced UI Features: - SMART FIX button with AI code analysis - APEX (Autonomous Programming EXecution) mode - SHIELD (Auto-approval) mode - MULTIX MODE multi-task pipeline interface - Live streaming token counter - Thinking indicator with bouncing dots animation Components restored: - packages/ui/src/components/chat/multi-task-chat.tsx - packages/ui/src/components/instance/instance-shell2.tsx - packages/ui/src/components/settings/OllamaCloudSettings.tsx - packages/ui/src/components/settings/QwenCodeSettings.tsx - packages/ui/src/stores/solo-store.ts - packages/ui/src/stores/task-actions.ts - packages/ui/src/stores/session-events.ts (autonomous mode) - packages/server/src/integrations/ollama-cloud.ts - packages/server/src/server/routes/ollama.ts - packages/server/src/server/routes/qwen.ts This ensures all custom features are preserved in source control.
66 lines
1.8 KiB
TypeScript
66 lines
1.8 KiB
TypeScript
import fs from "fs"
|
|
import { promises as fsp } from "fs"
|
|
import os from "os"
|
|
import path from "path"
|
|
import type { InstanceData } from "../api-types"
|
|
|
|
const DEFAULT_INSTANCE_DATA: InstanceData = {
|
|
messageHistory: [],
|
|
agentModelSelections: {},
|
|
sessionTasks: {},
|
|
}
|
|
|
|
export class InstanceStore {
|
|
private readonly instancesDir: string
|
|
|
|
constructor(baseDir = path.join(os.homedir(), ".config", "codenomad", "instances")) {
|
|
this.instancesDir = baseDir
|
|
fs.mkdirSync(this.instancesDir, { recursive: true })
|
|
}
|
|
|
|
async read(id: string): Promise<InstanceData> {
|
|
try {
|
|
const filePath = this.resolvePath(id)
|
|
const content = await fsp.readFile(filePath, "utf-8")
|
|
const parsed = JSON.parse(content)
|
|
return { ...DEFAULT_INSTANCE_DATA, ...parsed }
|
|
} catch (error) {
|
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
return DEFAULT_INSTANCE_DATA
|
|
}
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async write(id: string, data: InstanceData): Promise<void> {
|
|
const filePath = this.resolvePath(id)
|
|
await fsp.mkdir(path.dirname(filePath), { recursive: true })
|
|
await fsp.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8")
|
|
}
|
|
|
|
async delete(id: string): Promise<void> {
|
|
try {
|
|
const filePath = this.resolvePath(id)
|
|
await fsp.unlink(filePath)
|
|
} catch (error) {
|
|
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
throw error
|
|
}
|
|
}
|
|
}
|
|
|
|
private resolvePath(id: string): string {
|
|
const filename = this.sanitizeId(id)
|
|
return path.join(this.instancesDir, `${filename}.json`)
|
|
}
|
|
|
|
private sanitizeId(id: string): string {
|
|
return id
|
|
.replace(/[\\/]/g, "_")
|
|
.replace(/[^a-zA-Z0-9_.-]/g, "_")
|
|
.replace(/_{2,}/g, "_")
|
|
.replace(/^_|_$/g, "")
|
|
.toLowerCase()
|
|
}
|
|
}
|