mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-13 07:54:49 +02:00
feat: design binary core — generate, check, compare commands
Stateless CLI (design/dist/design) wrapping OpenAI Responses API for UI mockup generation. Three working commands: - generate: brief -> PNG mockup via gpt-4o + image_generation tool - check: vision-based quality gate via GPT-4o (text readability, layout completeness, visual coherence) - compare: generates self-contained HTML comparison board with star ratings, radio Pick, per-variant feedback, regenerate controls, and Submit button that writes structured JSON for agent polling Auth reads from ~/.gstack/openai.json (0600), falls back to OPENAI_API_KEY env var. Compiled separately from browse binary (openai added to devDependencies, not runtime deps). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Session state management for multi-turn design iteration.
|
||||
* Session files are JSON in /tmp, keyed by PID + timestamp.
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
export interface DesignSession {
|
||||
id: string;
|
||||
lastResponseId: string;
|
||||
originalBrief: string;
|
||||
feedbackHistory: string[];
|
||||
outputPaths: string[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique session ID from PID + timestamp.
|
||||
*/
|
||||
export function createSessionId(): string {
|
||||
return `${process.pid}-${Date.now()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file path for a session.
|
||||
*/
|
||||
export function sessionPath(sessionId: string): string {
|
||||
return path.join("/tmp", `design-session-${sessionId}.json`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new session after initial generation.
|
||||
*/
|
||||
export function createSession(
|
||||
responseId: string,
|
||||
brief: string,
|
||||
outputPath: string,
|
||||
): DesignSession {
|
||||
const id = createSessionId();
|
||||
const session: DesignSession = {
|
||||
id,
|
||||
lastResponseId: responseId,
|
||||
originalBrief: brief,
|
||||
feedbackHistory: [],
|
||||
outputPaths: [outputPath],
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
fs.writeFileSync(sessionPath(id), JSON.stringify(session, null, 2));
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an existing session from disk.
|
||||
*/
|
||||
export function readSession(sessionFilePath: string): DesignSession {
|
||||
const content = fs.readFileSync(sessionFilePath, "utf-8");
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a session with new iteration data.
|
||||
*/
|
||||
export function updateSession(
|
||||
session: DesignSession,
|
||||
responseId: string,
|
||||
feedback: string,
|
||||
outputPath: string,
|
||||
): void {
|
||||
session.lastResponseId = responseId;
|
||||
session.feedbackHistory.push(feedback);
|
||||
session.outputPaths.push(outputPath);
|
||||
session.updatedAt = new Date().toISOString();
|
||||
|
||||
fs.writeFileSync(sessionPath(session.id), JSON.stringify(session, null, 2));
|
||||
}
|
||||
Reference in New Issue
Block a user