VIBN Frontend for Coolify deployment
This commit is contained in:
14
lib/types/chat-extraction.ts
Normal file
14
lib/types/chat-extraction.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { ChatExtractionData } from '@/lib/ai/chat-extraction-types';
|
||||
|
||||
export interface ChatExtractionRecord<TData = ChatExtractionData> {
|
||||
id: string;
|
||||
projectId: string;
|
||||
knowledgeItemId: string;
|
||||
data: TData;
|
||||
overallCompletion: number;
|
||||
overallConfidence: number;
|
||||
createdAt: FirebaseFirestore.Timestamp;
|
||||
updatedAt: FirebaseFirestore.Timestamp;
|
||||
}
|
||||
|
||||
|
||||
43
lib/types/extraction-output.ts
Normal file
43
lib/types/extraction-output.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Backend Extraction Output Types
|
||||
*
|
||||
* These types define the structured JSON returned by the backend extractor.
|
||||
* Used ONLY by backend extraction, not by chat.
|
||||
*/
|
||||
|
||||
// Structured item returned by Gemini for each category
|
||||
export interface StructuredExtractedItem {
|
||||
id?: string;
|
||||
sourceText: string;
|
||||
label?: string;
|
||||
description?: string;
|
||||
confidence: number;
|
||||
importance: "primary" | "supporting";
|
||||
}
|
||||
|
||||
export interface ExtractedInsight {
|
||||
id: string;
|
||||
type: "problem" | "user" | "feature" | "constraint" | "opportunity" | "other";
|
||||
title: string;
|
||||
description: string;
|
||||
sourceText: string;
|
||||
sourceKnowledgeItemId: string;
|
||||
importance: "primary" | "supporting";
|
||||
confidence: number;
|
||||
}
|
||||
|
||||
export interface ExtractionOutput {
|
||||
// Gemini returns rich objects, not just strings
|
||||
problems: StructuredExtractedItem[];
|
||||
targetUsers: StructuredExtractedItem[];
|
||||
features: StructuredExtractedItem[];
|
||||
constraints: StructuredExtractedItem[];
|
||||
opportunities: StructuredExtractedItem[];
|
||||
|
||||
// These can remain as arrays (empty arrays OK)
|
||||
insights: ExtractedInsight[];
|
||||
uncertainties: string[];
|
||||
missingInformation: string[];
|
||||
overallConfidence: number;
|
||||
}
|
||||
|
||||
51
lib/types/knowledge.ts
Normal file
51
lib/types/knowledge.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
export type KnowledgeSourceType =
|
||||
| 'user_chat'
|
||||
| 'imported_chat'
|
||||
| 'imported_ai_chat'
|
||||
| 'imported_document'
|
||||
| 'doc'
|
||||
| 'note'
|
||||
| 'spec'
|
||||
| 'research'
|
||||
| 'other';
|
||||
|
||||
export type KnowledgeSourceOrigin =
|
||||
| 'chatgpt'
|
||||
| 'gemini'
|
||||
| 'claude'
|
||||
| 'cursor'
|
||||
| 'vibn'
|
||||
| 'other';
|
||||
|
||||
export type KnowledgeImportance = 'primary' | 'supporting' | 'irrelevant';
|
||||
|
||||
export interface ChunkMetadata {
|
||||
chunkIndex: number;
|
||||
totalChunks: number;
|
||||
startChar: number;
|
||||
endChar: number;
|
||||
tokenCount: number;
|
||||
}
|
||||
|
||||
export interface KnowledgeSourceMeta {
|
||||
origin?: KnowledgeSourceOrigin;
|
||||
url?: string | null;
|
||||
filename?: string | null;
|
||||
createdAtOriginal?: string | null;
|
||||
importance?: KnowledgeImportance;
|
||||
tags?: string[];
|
||||
chunkMetadata?: ChunkMetadata;
|
||||
}
|
||||
|
||||
export interface KnowledgeItem {
|
||||
id: string;
|
||||
projectId: string;
|
||||
sourceType: KnowledgeSourceType;
|
||||
title?: string | null;
|
||||
content: string;
|
||||
sourceMeta?: KnowledgeSourceMeta;
|
||||
createdAt: FirebaseFirestore.Timestamp;
|
||||
updatedAt: FirebaseFirestore.Timestamp;
|
||||
}
|
||||
|
||||
|
||||
102
lib/types/logs.ts
Normal file
102
lib/types/logs.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Logging types for monitoring and debugging
|
||||
*/
|
||||
|
||||
import type { ChatMode } from '@/lib/ai/chat-modes';
|
||||
|
||||
/**
|
||||
* Log entry for project-related events
|
||||
*
|
||||
* Stored in Firestore `project_logs` collection for monitoring,
|
||||
* debugging, and prompt iteration.
|
||||
*/
|
||||
export interface ProjectLogEntry {
|
||||
/** Firestore document ID */
|
||||
id: string;
|
||||
|
||||
/** Project this log belongs to */
|
||||
projectId: string;
|
||||
|
||||
/** User who triggered the event (if available) */
|
||||
userId: string | null;
|
||||
|
||||
/** Event type for filtering */
|
||||
eventType:
|
||||
| 'chat_interaction'
|
||||
| 'extraction'
|
||||
| 'vision_generation'
|
||||
| 'mvp_generation'
|
||||
| 'marketing_generation'
|
||||
| 'knowledge_import'
|
||||
| 'batch_extraction'
|
||||
| 'mode_transition'
|
||||
| 'error';
|
||||
|
||||
/** Chat mode (if applicable) */
|
||||
mode: ChatMode | null;
|
||||
|
||||
/** Project phase (if applicable) */
|
||||
phase: string | null;
|
||||
|
||||
/** Which artifacts were used in this interaction */
|
||||
artifactsUsed: string[];
|
||||
|
||||
/** Whether vector search was used */
|
||||
usedVectorSearch: boolean;
|
||||
|
||||
/** Number of vector chunks retrieved (if applicable) */
|
||||
vectorChunkCount?: number;
|
||||
|
||||
/** Prompt version identifier (for A/B testing) */
|
||||
promptVersion: string | null;
|
||||
|
||||
/** Model used (e.g., 'gemini-2.0-flash-exp') */
|
||||
modelUsed: string | null;
|
||||
|
||||
/** Whether the operation succeeded */
|
||||
success: boolean;
|
||||
|
||||
/** Error message (if failed) */
|
||||
errorMessage: string | null;
|
||||
|
||||
/** Additional metadata (flexible for future use) */
|
||||
metadata?: Record<string, any>;
|
||||
|
||||
/** When this log was created */
|
||||
createdAt: Date | string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input for creating a new log entry
|
||||
* (id and createdAt are auto-generated)
|
||||
*/
|
||||
export type CreateProjectLogInput = Omit<ProjectLogEntry, 'id' | 'createdAt'>;
|
||||
|
||||
/**
|
||||
* Filters for querying logs
|
||||
*/
|
||||
export interface ProjectLogFilters {
|
||||
projectId?: string;
|
||||
userId?: string;
|
||||
eventType?: ProjectLogEntry['eventType'];
|
||||
mode?: ChatMode;
|
||||
phase?: string;
|
||||
success?: boolean;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregated log stats for monitoring
|
||||
*/
|
||||
export interface ProjectLogStats {
|
||||
totalLogs: number;
|
||||
successCount: number;
|
||||
errorCount: number;
|
||||
byEventType: Record<string, number>;
|
||||
byMode: Record<string, number>;
|
||||
avgVectorChunks: number;
|
||||
vectorSearchUsageRate: number;
|
||||
}
|
||||
|
||||
17
lib/types/marketing.ts
Normal file
17
lib/types/marketing.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface HomepageMessaging {
|
||||
headline: string | null;
|
||||
subheadline: string | null;
|
||||
bullets: string[];
|
||||
}
|
||||
|
||||
export interface MarketingModel {
|
||||
projectId: string;
|
||||
icp: string[];
|
||||
positioning: string | null;
|
||||
homepageMessaging: HomepageMessaging;
|
||||
initialChannels: string[];
|
||||
launchAngles: string[];
|
||||
overallConfidence: number;
|
||||
}
|
||||
|
||||
|
||||
122
lib/types/mvp-plan.ts
Normal file
122
lib/types/mvp-plan.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Type definitions for AI-generated MVP Plan
|
||||
* Based on the Vibn MVP Planner agent spec
|
||||
*/
|
||||
|
||||
// Project-level
|
||||
export type Project = {
|
||||
id: string;
|
||||
ownerUserId: string;
|
||||
name: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
summary: string; // final summary text from planner
|
||||
};
|
||||
|
||||
// Raw vision answers
|
||||
export type VisionInput = {
|
||||
projectId: string;
|
||||
q1_who_and_problem: string;
|
||||
q2_story: string;
|
||||
q3_improvement: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
// Optional work-to-date summary
|
||||
export type WorkToDate = {
|
||||
projectId: string;
|
||||
codeSummary?: string;
|
||||
githubSummary?: string;
|
||||
docsLinksOrText?: string[]; // or JSON
|
||||
existingAssetsNotes?: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
// Trees (Journey / Touchpoints / System)
|
||||
export type TreeType = "journey" | "touchpoints" | "system";
|
||||
|
||||
export type Tree = {
|
||||
id: string;
|
||||
projectId: string;
|
||||
type: TreeType;
|
||||
label: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
// Asset types from agent spec
|
||||
export type AssetType =
|
||||
| "web_page"
|
||||
| "app_screen"
|
||||
| "flow"
|
||||
| "component"
|
||||
| "email"
|
||||
| "notification"
|
||||
| "document"
|
||||
| "social_post"
|
||||
| "data_model"
|
||||
| "api_endpoint"
|
||||
| "service"
|
||||
| "integration"
|
||||
| "job"
|
||||
| "infrastructure"
|
||||
| "automation"
|
||||
| "other";
|
||||
|
||||
// Each node in any tree
|
||||
export type AssetNode = {
|
||||
id: string;
|
||||
projectId: string;
|
||||
treeId: string;
|
||||
parentId: string | null;
|
||||
name: string;
|
||||
assetType: AssetType;
|
||||
mustHaveForV1: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
children?: AssetNode[]; // For nested structure
|
||||
};
|
||||
|
||||
// Node metadata (reasoning, mapping back to vision)
|
||||
export type AssetMetadata = {
|
||||
assetNodeId: string;
|
||||
whyItExists: string;
|
||||
whichUserItServes?: string;
|
||||
problemItHelpsWith?: string;
|
||||
connectionToMagicMoment: string;
|
||||
valueContribution?: string;
|
||||
journeyStage?: string;
|
||||
messagingTone?: string;
|
||||
visualStyleNotes?: string;
|
||||
dependencies?: string[]; // other AssetNode IDs
|
||||
implementationNotes?: string;
|
||||
};
|
||||
|
||||
// Context memory events
|
||||
export type ContextEvent = {
|
||||
id: string;
|
||||
projectId: string;
|
||||
sourceType: "chat" | "commit" | "file" | "doc" | "manual_note";
|
||||
sourceId?: string; // e.g. commit hash, file path
|
||||
timestamp: string;
|
||||
title: string;
|
||||
body: string; // raw text or JSON
|
||||
};
|
||||
|
||||
// Full AI response from agent
|
||||
export type AIAgentResponse = {
|
||||
journey_tree: {
|
||||
label: string;
|
||||
nodes: Array<AssetNode & { asset_metadata: AssetMetadata }>;
|
||||
};
|
||||
touchpoints_tree: {
|
||||
label: string;
|
||||
nodes: Array<AssetNode & { asset_metadata: AssetMetadata }>;
|
||||
};
|
||||
system_tree: {
|
||||
label: string;
|
||||
nodes: Array<AssetNode & { asset_metadata: AssetMetadata }>;
|
||||
};
|
||||
summary: string;
|
||||
};
|
||||
|
||||
12
lib/types/mvp.ts
Normal file
12
lib/types/mvp.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface MvpPlan {
|
||||
projectId: string;
|
||||
coreFlows: string[];
|
||||
coreFeatures: string[];
|
||||
supportingFeatures: string[];
|
||||
outOfScope: string[];
|
||||
technicalTasks: string[];
|
||||
blockers: string[];
|
||||
overallConfidence: number;
|
||||
}
|
||||
|
||||
|
||||
257
lib/types/phase-handoff.ts
Normal file
257
lib/types/phase-handoff.ts
Normal file
@@ -0,0 +1,257 @@
|
||||
/**
|
||||
* Phase Handoff Protocol
|
||||
*
|
||||
* Defines the structured handoff between phases in the Vibn workflow.
|
||||
* Each phase (extraction, vision, mvp, marketing) produces a handoff that:
|
||||
* - Declares confidence and readiness for next phase
|
||||
* - Separates confirmed facts from uncertain/missing items
|
||||
* - Provides questions to resolve ambiguity
|
||||
* - References source evidence
|
||||
*/
|
||||
|
||||
/**
|
||||
* Phase identifier for handoffs
|
||||
*/
|
||||
export type PhaseType = 'collector' | 'extraction' | 'vision' | 'mvp' | 'marketing';
|
||||
|
||||
/**
|
||||
* Structured handoff between phases
|
||||
*
|
||||
* Produced by each phase agent to communicate confidence, gaps, and questions
|
||||
* to the next phase or back to the user.
|
||||
*/
|
||||
export interface PhaseHandoff {
|
||||
/** Which phase produced this handoff */
|
||||
phase: PhaseType;
|
||||
|
||||
/** Is this phase ready to hand off to the next one? */
|
||||
readyForNextPhase: boolean;
|
||||
|
||||
/** Overall confidence score (0-1) for this phase's outputs */
|
||||
confidence: number;
|
||||
|
||||
/** Items that are confirmed and high-confidence */
|
||||
confirmed: Record<string, any>;
|
||||
|
||||
/** Items that are uncertain or low-confidence */
|
||||
uncertain: Record<string, any>;
|
||||
|
||||
/** Items that are completely missing or unknown */
|
||||
missing: string[];
|
||||
|
||||
/** Questions for the user to resolve gaps or ambiguity */
|
||||
questionsForUser: string[];
|
||||
|
||||
/** References to source knowledge items or extractions that support this handoff */
|
||||
sourceEvidence: string[];
|
||||
|
||||
/** Version of the handoff schema (for future evolution) */
|
||||
version: string;
|
||||
|
||||
/** When this handoff was created */
|
||||
timestamp: string;
|
||||
|
||||
/** Optional metadata specific to this phase */
|
||||
metadata?: Record<string, any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handoff from the Collector phase
|
||||
*
|
||||
* After gathering project materials, confirm readiness for extraction.
|
||||
*/
|
||||
export interface CollectorPhaseHandoff extends PhaseHandoff {
|
||||
phase: 'collector';
|
||||
|
||||
/** Checklist status */
|
||||
confirmed: {
|
||||
/** Has user uploaded documents? */
|
||||
hasDocuments?: boolean;
|
||||
|
||||
/** Number of documents uploaded */
|
||||
documentCount?: number;
|
||||
|
||||
/** Has user connected GitHub repo? */
|
||||
githubConnected?: boolean;
|
||||
|
||||
/** GitHub repo full name (e.g., 'user/repo') */
|
||||
githubRepo?: string;
|
||||
|
||||
/** Has user installed browser extension and linked to project? */
|
||||
extensionLinked?: boolean;
|
||||
};
|
||||
|
||||
/** Items the user said "no" or "not yet" to */
|
||||
uncertain: {
|
||||
/** User declined or hasn't set up extension */
|
||||
extensionDeclined?: boolean;
|
||||
|
||||
/** User doesn't have a GitHub repo yet */
|
||||
noGithubYet?: boolean;
|
||||
};
|
||||
|
||||
/** What's missing before moving to extraction */
|
||||
missing: string[]; // e.g., ["documents", "github repo", "extension"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Handoff from the Extraction phase
|
||||
*
|
||||
* After analyzing all chat_extractions, summarize what's known about the product.
|
||||
*/
|
||||
export interface ExtractionPhaseHandoff extends PhaseHandoff {
|
||||
phase: 'extraction';
|
||||
|
||||
/** High-confidence product signals */
|
||||
confirmed: {
|
||||
/** Product one-liner (if clear) */
|
||||
oneLiner?: string;
|
||||
|
||||
/** Core problem statement */
|
||||
problemStatement?: string;
|
||||
|
||||
/** Target user personas */
|
||||
targetUsers?: string[];
|
||||
|
||||
/** Confirmed features */
|
||||
features?: string[];
|
||||
|
||||
/** Known tech stack */
|
||||
techStack?: string[];
|
||||
};
|
||||
|
||||
/** Low-confidence or conflicting signals */
|
||||
uncertain: {
|
||||
/** Ambiguous or conflicting features */
|
||||
features?: string[];
|
||||
|
||||
/** Unclear business model */
|
||||
businessModel?: string;
|
||||
};
|
||||
|
||||
/** What's missing to build a solid product model */
|
||||
missing: string[]; // e.g., ["target market size", "pricing strategy"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Handoff from the Vision phase
|
||||
*
|
||||
* After creating canonicalProductModel, declare what's locked vs tentative.
|
||||
*/
|
||||
export interface VisionPhaseHandoff extends PhaseHandoff {
|
||||
phase: 'vision';
|
||||
|
||||
confirmed: {
|
||||
/** Core value proposition (locked) */
|
||||
valueProposition?: string;
|
||||
|
||||
/** Primary user persona (locked) */
|
||||
primaryPersona?: string;
|
||||
|
||||
/** Must-have features for MVP */
|
||||
mustHaveFeatures?: string[];
|
||||
};
|
||||
|
||||
uncertain: {
|
||||
/** Nice-to-have features (not decided for MVP) */
|
||||
niceToHaveFeatures?: string[];
|
||||
|
||||
/** Unclear scope decisions */
|
||||
scopeDecisions?: string[];
|
||||
};
|
||||
|
||||
missing: string[]; // e.g., ["competitive analysis", "pricing model"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Handoff from the MVP phase
|
||||
*
|
||||
* After creating mvpPlan, declare what's ready to build vs needs clarification.
|
||||
*/
|
||||
export interface MVPPhaseHandoff extends PhaseHandoff {
|
||||
phase: 'mvp';
|
||||
|
||||
confirmed: {
|
||||
/** Locked feature scope */
|
||||
featureScope?: string[];
|
||||
|
||||
/** Tech stack decisions */
|
||||
techStack?: string[];
|
||||
|
||||
/** Build timeline estimate */
|
||||
timelineEstimate?: string;
|
||||
};
|
||||
|
||||
uncertain: {
|
||||
/** Features with unclear requirements */
|
||||
unclearFeatures?: string[];
|
||||
|
||||
/** Technical risks or unknowns */
|
||||
technicalRisks?: string[];
|
||||
};
|
||||
|
||||
missing: string[]; // e.g., ["API design", "database schema"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Handoff from the Marketing phase
|
||||
*
|
||||
* After creating marketingPlan, declare launch readiness.
|
||||
*/
|
||||
export interface MarketingPhaseHandoff extends PhaseHandoff {
|
||||
phase: 'marketing';
|
||||
|
||||
confirmed: {
|
||||
/** Launch channels */
|
||||
launchChannels?: string[];
|
||||
|
||||
/** Target launch date */
|
||||
launchDate?: string;
|
||||
|
||||
/** Marketing messaging */
|
||||
messaging?: string;
|
||||
};
|
||||
|
||||
uncertain: {
|
||||
/** Unconfirmed distribution channels */
|
||||
uncertainChannels?: string[];
|
||||
|
||||
/** Budget constraints */
|
||||
budgetConstraints?: string;
|
||||
};
|
||||
|
||||
missing: string[]; // e.g., ["landing page copy", "email sequences"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Union type for all phase handoffs
|
||||
*/
|
||||
export type AnyPhaseHandoff =
|
||||
| CollectorPhaseHandoff
|
||||
| ExtractionPhaseHandoff
|
||||
| VisionPhaseHandoff
|
||||
| MVPPhaseHandoff
|
||||
| MarketingPhaseHandoff;
|
||||
|
||||
/**
|
||||
* Helper to create a minimal phase handoff
|
||||
*/
|
||||
export function createPhaseHandoff(
|
||||
phase: PhaseType,
|
||||
partial: Partial<PhaseHandoff>
|
||||
): PhaseHandoff {
|
||||
return {
|
||||
phase,
|
||||
readyForNextPhase: false,
|
||||
confidence: 0.5,
|
||||
confirmed: {},
|
||||
uncertain: {},
|
||||
missing: [],
|
||||
questionsForUser: [],
|
||||
sourceEvidence: [],
|
||||
version: '1.0',
|
||||
timestamp: new Date().toISOString(),
|
||||
...partial,
|
||||
};
|
||||
}
|
||||
|
||||
96
lib/types/phases.ts
Normal file
96
lib/types/phases.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Phase Tracking for Vibn Projects
|
||||
*
|
||||
* Projects progress through phases with specific agents:
|
||||
* 1. Gathering → Collect and analyze all project materials
|
||||
* 2. Vision → Extract and validate Product Vision Board
|
||||
* 3. Scope → Define V1 MVP features
|
||||
* 4. Blueprint → Technical architecture design
|
||||
* 5. Build → Implementation (future)
|
||||
*/
|
||||
|
||||
export type ProjectPhase =
|
||||
| 'gathering' // Phase 1: Collecting context and analyzing materials
|
||||
| 'vision' // Phase 2: Extracting vision board
|
||||
| 'scope' // Phase 3: Defining V1 features
|
||||
| 'blueprint' // Phase 4: Technical design
|
||||
| 'build'; // Phase 5: Implementation
|
||||
|
||||
export type PhaseStatus =
|
||||
| 'not_started'
|
||||
| 'in_progress'
|
||||
| 'completed';
|
||||
|
||||
export interface PhaseProgress {
|
||||
phase: ProjectPhase;
|
||||
status: PhaseStatus;
|
||||
startedAt?: FirebaseFirestore.Timestamp;
|
||||
completedAt?: FirebaseFirestore.Timestamp;
|
||||
insights?: GatheringInsight[]; // For gathering phase
|
||||
visionBoard?: VisionBoardData; // For vision phase
|
||||
scope?: ScopeData; // For scope phase
|
||||
blueprint?: BlueprintData; // For blueprint phase
|
||||
}
|
||||
|
||||
export interface GatheringInsight {
|
||||
id: string;
|
||||
source: string; // "Patient History Overview"
|
||||
sourceType: 'document' | 'github' | 'session' | 'conversation';
|
||||
sourceId: string; // Document/session ID
|
||||
insight: string; // "Using evidence-based diagnostic methods"
|
||||
extractedAt: FirebaseFirestore.Timestamp;
|
||||
confirmed: boolean; // User validated this
|
||||
confirmedAt?: FirebaseFirestore.Timestamp;
|
||||
usedInVision: boolean; // Phase 2 marked this as used
|
||||
category?: 'feature' | 'user' | 'problem' | 'competitor' | 'tech' | 'progress';
|
||||
}
|
||||
|
||||
export interface VisionBoardData {
|
||||
vision: string; // One-sentence vision
|
||||
who: string; // Target users
|
||||
need: string; // Problem they face
|
||||
product: string; // Solution features
|
||||
validation: string; // Go-to-market strategy
|
||||
completedAt?: FirebaseFirestore.Timestamp;
|
||||
approved: boolean;
|
||||
approvedAt?: FirebaseFirestore.Timestamp;
|
||||
}
|
||||
|
||||
export interface ScopeData {
|
||||
v1Features: string[];
|
||||
timeline: string;
|
||||
priorities: {
|
||||
mustHave: string[];
|
||||
shouldHave: string[];
|
||||
niceToHave: string[];
|
||||
};
|
||||
completedAt?: FirebaseFirestore.Timestamp;
|
||||
}
|
||||
|
||||
export interface BlueprintData {
|
||||
techStack: string[];
|
||||
architecture: string;
|
||||
database: string;
|
||||
apis: string[];
|
||||
completedAt?: FirebaseFirestore.Timestamp;
|
||||
}
|
||||
|
||||
// Helper to determine which agent to use
|
||||
export function getAgentForPhase(phase: ProjectPhase): string {
|
||||
const agentMap: Record<ProjectPhase, string> = {
|
||||
gathering: 'GATHERING_AGENT',
|
||||
vision: 'VISION_AGENT',
|
||||
scope: 'SCOPE_AGENT',
|
||||
blueprint: 'BLUEPRINT_AGENT',
|
||||
build: 'BUILD_AGENT'
|
||||
};
|
||||
return agentMap[phase];
|
||||
}
|
||||
|
||||
// Helper to get next phase
|
||||
export function getNextPhase(currentPhase: ProjectPhase): ProjectPhase | null {
|
||||
const phaseOrder: ProjectPhase[] = ['gathering', 'vision', 'scope', 'blueprint', 'build'];
|
||||
const currentIndex = phaseOrder.indexOf(currentPhase);
|
||||
return currentIndex < phaseOrder.length - 1 ? phaseOrder[currentIndex + 1] : null;
|
||||
}
|
||||
|
||||
37
lib/types/product-model.ts
Normal file
37
lib/types/product-model.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export type ProjectStage =
|
||||
| 'idea'
|
||||
| 'prototype'
|
||||
| 'mvp_in_progress'
|
||||
| 'live_beta'
|
||||
| 'live_paid'
|
||||
| 'unknown';
|
||||
|
||||
export interface CanonicalProductModel {
|
||||
projectId: string;
|
||||
workingTitle: string | null;
|
||||
oneLiner: string | null;
|
||||
|
||||
problem: string | null;
|
||||
targetUser: string | null;
|
||||
desiredOutcome: string | null;
|
||||
coreSolution: string | null;
|
||||
|
||||
coreFeatures: string[];
|
||||
niceToHaveFeatures: string[];
|
||||
|
||||
marketCategory: string | null;
|
||||
competitors: string[];
|
||||
|
||||
techStack: string[];
|
||||
constraints: string[];
|
||||
|
||||
currentStage: ProjectStage;
|
||||
|
||||
shortTermGoals: string[];
|
||||
longTermGoals: string[];
|
||||
|
||||
overallCompletion: number;
|
||||
overallConfidence: number;
|
||||
}
|
||||
|
||||
|
||||
40
lib/types/project-artifacts.ts
Normal file
40
lib/types/project-artifacts.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import type { CanonicalProductModel, ProjectStage } from '@/lib/types/product-model';
|
||||
import type { MvpPlan } from '@/lib/types/mvp';
|
||||
import type { MarketingModel, HomepageMessaging } from '@/lib/types/marketing';
|
||||
import type { PhaseHandoff } from '@/lib/types/phase-handoff';
|
||||
export type { CanonicalProductModel, ProjectStage } from '@/lib/types/product-model';
|
||||
export type { MvpPlan } from '@/lib/types/mvp';
|
||||
export type { MarketingModel, HomepageMessaging } from '@/lib/types/marketing';
|
||||
export type { PhaseHandoff } from '@/lib/types/phase-handoff';
|
||||
|
||||
export type ProjectPhase =
|
||||
| 'collector'
|
||||
| 'analyzed'
|
||||
| 'vision_ready'
|
||||
| 'mvp_ready'
|
||||
| 'marketing_ready'
|
||||
| 'complete';
|
||||
|
||||
export interface ProjectPhaseData {
|
||||
canonicalProductModel?: CanonicalProductModel;
|
||||
mvpPlan?: MvpPlan;
|
||||
marketingPlan?: MarketingModel;
|
||||
|
||||
/** Phase handoffs for smart transitions */
|
||||
phaseHandoffs?: Partial<Record<'collector' | 'extraction' | 'vision' | 'mvp' | 'marketing', PhaseHandoff>>;
|
||||
}
|
||||
|
||||
export interface PhaseScore {
|
||||
overallCompletion: number;
|
||||
overallConfidence: number;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ProjectPhaseScores {
|
||||
extractor?: PhaseScore & { knowledgeItemId?: string };
|
||||
vision?: PhaseScore;
|
||||
mvp?: PhaseScore;
|
||||
marketing?: PhaseScore;
|
||||
}
|
||||
|
||||
|
||||
107
lib/types/vector-memory.ts
Normal file
107
lib/types/vector-memory.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Types for AlloyDB vector memory (knowledge_chunks table)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A semantic chunk of a knowledge_item with vector embedding
|
||||
*/
|
||||
export interface KnowledgeChunk {
|
||||
/** UUID primary key */
|
||||
id: string;
|
||||
|
||||
/** Firestore project ID */
|
||||
projectId: string;
|
||||
|
||||
/** Firestore knowledge_item ID */
|
||||
knowledgeItemId: string;
|
||||
|
||||
/** Index of this chunk within the parent knowledge_item (0-based) */
|
||||
chunkIndex: number;
|
||||
|
||||
/** Text content of this chunk */
|
||||
content: string;
|
||||
|
||||
/** Source type (e.g., 'imported_ai_chat', 'imported_document', etc.) */
|
||||
sourceType: string | null;
|
||||
|
||||
/** Importance classification (for filtering) */
|
||||
importance: 'primary' | 'supporting' | 'irrelevant' | null;
|
||||
|
||||
/** When this chunk was created */
|
||||
createdAt: string;
|
||||
|
||||
/** When this chunk was last updated */
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Database row shape (snake_case from PostgreSQL)
|
||||
*/
|
||||
export interface KnowledgeChunkRow {
|
||||
id: string;
|
||||
project_id: string;
|
||||
knowledge_item_id: string;
|
||||
chunk_index: number;
|
||||
content: string;
|
||||
source_type: string | null;
|
||||
importance: 'primary' | 'supporting' | 'irrelevant' | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result of a vector similarity search, includes similarity score
|
||||
*/
|
||||
export interface KnowledgeChunkSearchResult extends KnowledgeChunk {
|
||||
/** Similarity score (0-1, higher = more similar) */
|
||||
similarity: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for vector search
|
||||
*/
|
||||
export interface VectorSearchOptions {
|
||||
/** Maximum number of results to return */
|
||||
limit?: number;
|
||||
|
||||
/** Minimum similarity threshold (0-1) */
|
||||
minSimilarity?: number;
|
||||
|
||||
/** Filter by source type(s) */
|
||||
sourceTypes?: string[];
|
||||
|
||||
/** Filter by importance level(s) */
|
||||
importanceLevels?: ('primary' | 'supporting' | 'irrelevant')[];
|
||||
|
||||
/** Whether to include embedding in results (default: false) */
|
||||
includeEmbedding?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input for creating a new knowledge chunk
|
||||
*/
|
||||
export interface CreateKnowledgeChunkInput {
|
||||
projectId: string;
|
||||
knowledgeItemId: string;
|
||||
chunkIndex: number;
|
||||
content: string;
|
||||
embedding: number[];
|
||||
sourceType?: string | null;
|
||||
importance?: 'primary' | 'supporting' | 'irrelevant' | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch input for creating multiple chunks at once
|
||||
*/
|
||||
export interface BatchCreateKnowledgeChunksInput {
|
||||
projectId: string;
|
||||
knowledgeItemId: string;
|
||||
chunks: {
|
||||
chunkIndex: number;
|
||||
content: string;
|
||||
embedding: number[];
|
||||
sourceType?: string | null;
|
||||
importance?: 'primary' | 'supporting' | 'irrelevant' | null;
|
||||
}[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user