mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 20:43:36 +00:00
feat: introduce marketing mode and update sidebar display
- Added a new configuration flag `IS_MARKETING` to toggle marketing mode. - Updated the sidebar component to conditionally display the marketing URL when in marketing mode. - Refactored event type naming for consistency in the sidebar logic. - Cleaned up formatting in the HttpApiClient for improved readability.
This commit is contained in:
@@ -4,6 +4,7 @@ import { useState, useMemo, useEffect, useCallback, useRef } from "react";
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { useAppStore, formatShortcut } from "@/store/app-store";
|
import { useAppStore, formatShortcut } from "@/store/app-store";
|
||||||
import { CoursePromoBadge } from "@/components/ui/course-promo-badge";
|
import { CoursePromoBadge } from "@/components/ui/course-promo-badge";
|
||||||
|
import { IS_MARKETING } from "@/config/app-config";
|
||||||
import {
|
import {
|
||||||
FolderOpen,
|
FolderOpen,
|
||||||
Plus,
|
Plus,
|
||||||
@@ -366,7 +367,7 @@ export function Sidebar() {
|
|||||||
if (
|
if (
|
||||||
event.type === "auto_mode_feature_complete" ||
|
event.type === "auto_mode_feature_complete" ||
|
||||||
event.type === "auto_mode_error" ||
|
event.type === "auto_mode_error" ||
|
||||||
event.type === "auto_mode_feature_started"
|
event.type === "auto_mode_feature_start"
|
||||||
) {
|
) {
|
||||||
const fetchRunningAgentsCount = async () => {
|
const fetchRunningAgentsCount = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -853,7 +854,15 @@ export function Sidebar() {
|
|||||||
sidebarOpen ? "hidden lg:block" : "hidden"
|
sidebarOpen ? "hidden lg:block" : "hidden"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
Auto<span className="text-brand-500">maker</span>
|
{IS_MARKETING ? (
|
||||||
|
<>
|
||||||
|
https://<span className="text-brand-500">automaker</span>.app
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
Auto<span className="text-brand-500">maker</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{/* Bug Report Button */}
|
{/* Bug Report Button */}
|
||||||
|
|||||||
6
apps/app/src/config/app-config.ts
Normal file
6
apps/app/src/config/app-config.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Marketing mode flag
|
||||||
|
* When set to true, displays "https://automaker.app" with "maker" in theme color
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const IS_MARKETING = process.env.NEXT_PUBLIC_IS_MARKETING === "true";
|
||||||
@@ -33,7 +33,6 @@ import type {
|
|||||||
} from "@/types/electron";
|
} from "@/types/electron";
|
||||||
import { getGlobalFileBrowser } from "@/contexts/file-browser-context";
|
import { getGlobalFileBrowser } from "@/contexts/file-browser-context";
|
||||||
|
|
||||||
|
|
||||||
// Server URL - configurable via environment variable
|
// Server URL - configurable via environment variable
|
||||||
const getServerUrl = (): string => {
|
const getServerUrl = (): string => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
@@ -43,7 +42,6 @@ const getServerUrl = (): string => {
|
|||||||
return "http://localhost:3008";
|
return "http://localhost:3008";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Get API key from environment variable
|
// Get API key from environment variable
|
||||||
const getApiKey = (): string | null => {
|
const getApiKey = (): string | null => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
@@ -76,7 +74,10 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private connectWebSocket(): void {
|
private connectWebSocket(): void {
|
||||||
if (this.isConnecting || (this.ws && this.ws.readyState === WebSocket.OPEN)) {
|
if (
|
||||||
|
this.isConnecting ||
|
||||||
|
(this.ws && this.ws.readyState === WebSocket.OPEN)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +104,10 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
callbacks.forEach((cb) => cb(data.payload));
|
callbacks.forEach((cb) => cb(data.payload));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[HttpApiClient] Failed to parse WebSocket message:", error);
|
console.error(
|
||||||
|
"[HttpApiClient] Failed to parse WebSocket message:",
|
||||||
|
error
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,7 +134,10 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private subscribeToEvent(type: EventType, callback: EventCallback): () => void {
|
private subscribeToEvent(
|
||||||
|
type: EventType,
|
||||||
|
callback: EventCallback
|
||||||
|
): () => void {
|
||||||
if (!this.eventCallbacks.has(type)) {
|
if (!this.eventCallbacks.has(type)) {
|
||||||
this.eventCallbacks.set(type, new Set());
|
this.eventCallbacks.set(type, new Set());
|
||||||
}
|
}
|
||||||
@@ -196,7 +203,9 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
return result.status === "ok" ? "pong" : "error";
|
return result.status === "ok" ? "pong" : "error";
|
||||||
}
|
}
|
||||||
|
|
||||||
async openExternalLink(url: string): Promise<{ success: boolean; error?: string }> {
|
async openExternalLink(
|
||||||
|
url: string
|
||||||
|
): Promise<{ success: boolean; error?: string }> {
|
||||||
// Open in new tab
|
// Open in new tab
|
||||||
window.open(url, "_blank", "noopener,noreferrer");
|
window.open(url, "_blank", "noopener,noreferrer");
|
||||||
return { success: true };
|
return { success: true };
|
||||||
@@ -301,7 +310,9 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
async getPath(name: string): Promise<string> {
|
async getPath(name: string): Promise<string> {
|
||||||
// Server provides data directory
|
// Server provides data directory
|
||||||
if (name === "userData") {
|
if (name === "userData") {
|
||||||
const result = await this.get<{ dataDir: string }>("/api/health/detailed");
|
const result = await this.get<{ dataDir: string }>(
|
||||||
|
"/api/health/detailed"
|
||||||
|
);
|
||||||
return result.dataDir || "/data";
|
return result.dataDir || "/data";
|
||||||
}
|
}
|
||||||
return `/data/${name}`;
|
return `/data/${name}`;
|
||||||
@@ -313,7 +324,12 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
mimeType: string,
|
mimeType: string,
|
||||||
projectPath?: string
|
projectPath?: string
|
||||||
): Promise<SaveImageResult> {
|
): Promise<SaveImageResult> {
|
||||||
return this.post("/api/fs/save-image", { data, filename, mimeType, projectPath });
|
return this.post("/api/fs/save-image", {
|
||||||
|
data,
|
||||||
|
filename,
|
||||||
|
mimeType,
|
||||||
|
projectPath,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveBoardBackground(
|
async saveBoardBackground(
|
||||||
@@ -464,14 +480,19 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
output?: string;
|
output?: string;
|
||||||
}> => this.post("/api/setup/auth-claude"),
|
}> => this.post("/api/setup/auth-claude"),
|
||||||
|
|
||||||
authCodex: (apiKey?: string): Promise<{
|
authCodex: (
|
||||||
|
apiKey?: string
|
||||||
|
): Promise<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
requiresManualAuth?: boolean;
|
requiresManualAuth?: boolean;
|
||||||
command?: string;
|
command?: string;
|
||||||
error?: string;
|
error?: string;
|
||||||
}> => this.post("/api/setup/auth-codex", { apiKey }),
|
}> => this.post("/api/setup/auth-codex", { apiKey }),
|
||||||
|
|
||||||
storeApiKey: (provider: string, apiKey: string): Promise<{
|
storeApiKey: (
|
||||||
|
provider: string,
|
||||||
|
apiKey: string
|
||||||
|
): Promise<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
error?: string;
|
error?: string;
|
||||||
}> => this.post("/api/setup/store-api-key", { provider, apiKey }),
|
}> => this.post("/api/setup/store-api-key", { provider, apiKey }),
|
||||||
@@ -483,7 +504,9 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
hasGoogleKey: boolean;
|
hasGoogleKey: boolean;
|
||||||
}> => this.get("/api/setup/api-keys"),
|
}> => this.get("/api/setup/api-keys"),
|
||||||
|
|
||||||
configureCodexMcp: (projectPath: string): Promise<{
|
configureCodexMcp: (
|
||||||
|
projectPath: string
|
||||||
|
): Promise<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
configPath?: string;
|
configPath?: string;
|
||||||
error?: string;
|
error?: string;
|
||||||
@@ -516,8 +539,11 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
this.post("/api/features/get", { projectPath, featureId }),
|
this.post("/api/features/get", { projectPath, featureId }),
|
||||||
create: (projectPath: string, feature: Feature) =>
|
create: (projectPath: string, feature: Feature) =>
|
||||||
this.post("/api/features/create", { projectPath, feature }),
|
this.post("/api/features/create", { projectPath, feature }),
|
||||||
update: (projectPath: string, featureId: string, updates: Partial<Feature>) =>
|
update: (
|
||||||
this.post("/api/features/update", { projectPath, featureId, updates }),
|
projectPath: string,
|
||||||
|
featureId: string,
|
||||||
|
updates: Partial<Feature>
|
||||||
|
) => this.post("/api/features/update", { projectPath, featureId, updates }),
|
||||||
delete: (projectPath: string, featureId: string) =>
|
delete: (projectPath: string, featureId: string) =>
|
||||||
this.post("/api/features/delete", { projectPath, featureId }),
|
this.post("/api/features/delete", { projectPath, featureId }),
|
||||||
getAgentOutput: (projectPath: string, featureId: string) =>
|
getAgentOutput: (projectPath: string, featureId: string) =>
|
||||||
@@ -534,8 +560,16 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
this.post("/api/auto-mode/stop-feature", { featureId }),
|
this.post("/api/auto-mode/stop-feature", { featureId }),
|
||||||
status: (projectPath?: string) =>
|
status: (projectPath?: string) =>
|
||||||
this.post("/api/auto-mode/status", { projectPath }),
|
this.post("/api/auto-mode/status", { projectPath }),
|
||||||
runFeature: (projectPath: string, featureId: string, useWorktrees?: boolean) =>
|
runFeature: (
|
||||||
this.post("/api/auto-mode/run-feature", { projectPath, featureId, useWorktrees }),
|
projectPath: string,
|
||||||
|
featureId: string,
|
||||||
|
useWorktrees?: boolean
|
||||||
|
) =>
|
||||||
|
this.post("/api/auto-mode/run-feature", {
|
||||||
|
projectPath,
|
||||||
|
featureId,
|
||||||
|
useWorktrees,
|
||||||
|
}),
|
||||||
verifyFeature: (projectPath: string, featureId: string) =>
|
verifyFeature: (projectPath: string, featureId: string) =>
|
||||||
this.post("/api/auto-mode/verify-feature", { projectPath, featureId }),
|
this.post("/api/auto-mode/verify-feature", { projectPath, featureId }),
|
||||||
resumeFeature: (projectPath: string, featureId: string) =>
|
resumeFeature: (projectPath: string, featureId: string) =>
|
||||||
@@ -559,7 +593,10 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
commitFeature: (projectPath: string, featureId: string) =>
|
commitFeature: (projectPath: string, featureId: string) =>
|
||||||
this.post("/api/auto-mode/commit-feature", { projectPath, featureId }),
|
this.post("/api/auto-mode/commit-feature", { projectPath, featureId }),
|
||||||
onEvent: (callback: (event: AutoModeEvent) => void) => {
|
onEvent: (callback: (event: AutoModeEvent) => void) => {
|
||||||
return this.subscribeToEvent("auto-mode:event", callback as EventCallback);
|
return this.subscribeToEvent(
|
||||||
|
"auto-mode:event",
|
||||||
|
callback as EventCallback
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -578,7 +615,11 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
getDiffs: (projectPath: string, featureId: string) =>
|
getDiffs: (projectPath: string, featureId: string) =>
|
||||||
this.post("/api/worktree/diffs", { projectPath, featureId }),
|
this.post("/api/worktree/diffs", { projectPath, featureId }),
|
||||||
getFileDiff: (projectPath: string, featureId: string, filePath: string) =>
|
getFileDiff: (projectPath: string, featureId: string, filePath: string) =>
|
||||||
this.post("/api/worktree/file-diff", { projectPath, featureId, filePath }),
|
this.post("/api/worktree/file-diff", {
|
||||||
|
projectPath,
|
||||||
|
featureId,
|
||||||
|
filePath,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Git API
|
// Git API
|
||||||
@@ -596,20 +637,30 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
stop: () => this.post("/api/suggestions/stop"),
|
stop: () => this.post("/api/suggestions/stop"),
|
||||||
status: () => this.get("/api/suggestions/status"),
|
status: () => this.get("/api/suggestions/status"),
|
||||||
onEvent: (callback: (event: SuggestionsEvent) => void) => {
|
onEvent: (callback: (event: SuggestionsEvent) => void) => {
|
||||||
return this.subscribeToEvent("suggestions:event", callback as EventCallback);
|
return this.subscribeToEvent(
|
||||||
|
"suggestions:event",
|
||||||
|
callback as EventCallback
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Spec Regeneration API
|
// Spec Regeneration API
|
||||||
specRegeneration: SpecRegenerationAPI = {
|
specRegeneration: SpecRegenerationAPI = {
|
||||||
create: (projectPath: string, projectOverview: string, generateFeatures?: boolean) =>
|
create: (
|
||||||
|
projectPath: string,
|
||||||
|
projectOverview: string,
|
||||||
|
generateFeatures?: boolean
|
||||||
|
) =>
|
||||||
this.post("/api/spec-regeneration/create", {
|
this.post("/api/spec-regeneration/create", {
|
||||||
projectPath,
|
projectPath,
|
||||||
projectOverview,
|
projectOverview,
|
||||||
generateFeatures,
|
generateFeatures,
|
||||||
}),
|
}),
|
||||||
generate: (projectPath: string, projectDefinition: string) =>
|
generate: (projectPath: string, projectDefinition: string) =>
|
||||||
this.post("/api/spec-regeneration/generate", { projectPath, projectDefinition }),
|
this.post("/api/spec-regeneration/generate", {
|
||||||
|
projectPath,
|
||||||
|
projectDefinition,
|
||||||
|
}),
|
||||||
generateFeatures: (projectPath: string) =>
|
generateFeatures: (projectPath: string) =>
|
||||||
this.post("/api/spec-regeneration/generate-features", { projectPath }),
|
this.post("/api/spec-regeneration/generate-features", { projectPath }),
|
||||||
stop: () => this.post("/api/spec-regeneration/stop"),
|
stop: () => this.post("/api/spec-regeneration/stop"),
|
||||||
@@ -656,7 +707,10 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
|
|
||||||
// Agent API
|
// Agent API
|
||||||
agent = {
|
agent = {
|
||||||
start: (sessionId: string, workingDirectory?: string): Promise<{
|
start: (
|
||||||
|
sessionId: string,
|
||||||
|
workingDirectory?: string
|
||||||
|
): Promise<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
messages?: Message[];
|
messages?: Message[];
|
||||||
error?: string;
|
error?: string;
|
||||||
@@ -668,9 +722,16 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
workingDirectory?: string,
|
workingDirectory?: string,
|
||||||
imagePaths?: string[]
|
imagePaths?: string[]
|
||||||
): Promise<{ success: boolean; error?: string }> =>
|
): Promise<{ success: boolean; error?: string }> =>
|
||||||
this.post("/api/agent/send", { sessionId, message, workingDirectory, imagePaths }),
|
this.post("/api/agent/send", {
|
||||||
|
sessionId,
|
||||||
|
message,
|
||||||
|
workingDirectory,
|
||||||
|
imagePaths,
|
||||||
|
}),
|
||||||
|
|
||||||
getHistory: (sessionId: string): Promise<{
|
getHistory: (
|
||||||
|
sessionId: string
|
||||||
|
): Promise<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
messages?: Message[];
|
messages?: Message[];
|
||||||
isRunning?: boolean;
|
isRunning?: boolean;
|
||||||
@@ -690,17 +751,24 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
|
|
||||||
// Templates API
|
// Templates API
|
||||||
templates = {
|
templates = {
|
||||||
clone: (repoUrl: string, projectName: string, parentDir: string): Promise<{
|
clone: (
|
||||||
|
repoUrl: string,
|
||||||
|
projectName: string,
|
||||||
|
parentDir: string
|
||||||
|
): Promise<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
projectPath?: string;
|
projectPath?: string;
|
||||||
projectName?: string;
|
projectName?: string;
|
||||||
error?: string;
|
error?: string;
|
||||||
}> => this.post("/api/templates/clone", { repoUrl, projectName, parentDir }),
|
}> =>
|
||||||
|
this.post("/api/templates/clone", { repoUrl, projectName, parentDir }),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sessions API
|
// Sessions API
|
||||||
sessions = {
|
sessions = {
|
||||||
list: (includeArchived?: boolean): Promise<{
|
list: (
|
||||||
|
includeArchived?: boolean
|
||||||
|
): Promise<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
sessions?: SessionListItem[];
|
sessions?: SessionListItem[];
|
||||||
error?: string;
|
error?: string;
|
||||||
@@ -730,13 +798,19 @@ export class HttpApiClient implements ElectronAPI {
|
|||||||
): Promise<{ success: boolean; error?: string }> =>
|
): Promise<{ success: boolean; error?: string }> =>
|
||||||
this.put(`/api/sessions/${sessionId}`, { name, tags }),
|
this.put(`/api/sessions/${sessionId}`, { name, tags }),
|
||||||
|
|
||||||
archive: (sessionId: string): Promise<{ success: boolean; error?: string }> =>
|
archive: (
|
||||||
|
sessionId: string
|
||||||
|
): Promise<{ success: boolean; error?: string }> =>
|
||||||
this.post(`/api/sessions/${sessionId}/archive`, {}),
|
this.post(`/api/sessions/${sessionId}/archive`, {}),
|
||||||
|
|
||||||
unarchive: (sessionId: string): Promise<{ success: boolean; error?: string }> =>
|
unarchive: (
|
||||||
|
sessionId: string
|
||||||
|
): Promise<{ success: boolean; error?: string }> =>
|
||||||
this.post(`/api/sessions/${sessionId}/unarchive`, {}),
|
this.post(`/api/sessions/${sessionId}/unarchive`, {}),
|
||||||
|
|
||||||
delete: (sessionId: string): Promise<{ success: boolean; error?: string }> =>
|
delete: (
|
||||||
|
sessionId: string
|
||||||
|
): Promise<{ success: boolean; error?: string }> =>
|
||||||
this.httpDelete(`/api/sessions/${sessionId}`),
|
this.httpDelete(`/api/sessions/${sessionId}`),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user