mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 21:23:07 +00:00
Merge remote-tracking branch 'upstream/v0.11.0rc' into patchcraft
This commit is contained in:
@@ -129,10 +129,30 @@ export const TOOL_PRESETS = {
|
|||||||
specGeneration: ['Read', 'Glob', 'Grep'] as const,
|
specGeneration: ['Read', 'Glob', 'Grep'] as const,
|
||||||
|
|
||||||
/** Full tool access for feature implementation */
|
/** Full tool access for feature implementation */
|
||||||
fullAccess: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'WebSearch', 'WebFetch', 'TodoWrite'] as const,
|
fullAccess: [
|
||||||
|
'Read',
|
||||||
|
'Write',
|
||||||
|
'Edit',
|
||||||
|
'Glob',
|
||||||
|
'Grep',
|
||||||
|
'Bash',
|
||||||
|
'WebSearch',
|
||||||
|
'WebFetch',
|
||||||
|
'TodoWrite',
|
||||||
|
] as const,
|
||||||
|
|
||||||
/** Tools for chat/interactive mode */
|
/** Tools for chat/interactive mode */
|
||||||
chat: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'WebSearch', 'WebFetch', 'TodoWrite'] as const,
|
chat: [
|
||||||
|
'Read',
|
||||||
|
'Write',
|
||||||
|
'Edit',
|
||||||
|
'Glob',
|
||||||
|
'Grep',
|
||||||
|
'Bash',
|
||||||
|
'WebSearch',
|
||||||
|
'WebFetch',
|
||||||
|
'TodoWrite',
|
||||||
|
] as const,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ const eslintConfig = defineConfig([
|
|||||||
AbortSignal: 'readonly',
|
AbortSignal: 'readonly',
|
||||||
Audio: 'readonly',
|
Audio: 'readonly',
|
||||||
ScrollBehavior: 'readonly',
|
ScrollBehavior: 'readonly',
|
||||||
|
URL: 'readonly',
|
||||||
|
URLSearchParams: 'readonly',
|
||||||
// Timers
|
// Timers
|
||||||
setTimeout: 'readonly',
|
setTimeout: 'readonly',
|
||||||
setInterval: 'readonly',
|
setInterval: 'readonly',
|
||||||
|
|||||||
@@ -422,6 +422,31 @@ export function BoardView() {
|
|||||||
const selectedWorktreeBranch =
|
const selectedWorktreeBranch =
|
||||||
currentWorktreeBranch || worktrees.find((w) => w.isMain)?.branch || 'main';
|
currentWorktreeBranch || worktrees.find((w) => w.isMain)?.branch || 'main';
|
||||||
|
|
||||||
|
// Helper function to add and select a worktree
|
||||||
|
const addAndSelectWorktree = useCallback(
|
||||||
|
(worktreeResult: { path: string; branch: string }) => {
|
||||||
|
if (!currentProject) return;
|
||||||
|
|
||||||
|
const currentWorktrees = getWorktrees(currentProject.path);
|
||||||
|
const existingWorktree = currentWorktrees.find((w) => w.branch === worktreeResult.branch);
|
||||||
|
|
||||||
|
// Only add if it doesn't already exist (to avoid duplicates)
|
||||||
|
if (!existingWorktree) {
|
||||||
|
const newWorktreeInfo = {
|
||||||
|
path: worktreeResult.path,
|
||||||
|
branch: worktreeResult.branch,
|
||||||
|
isMain: false,
|
||||||
|
isCurrent: false,
|
||||||
|
hasWorktree: true,
|
||||||
|
};
|
||||||
|
setWorktrees(currentProject.path, [...currentWorktrees, newWorktreeInfo]);
|
||||||
|
}
|
||||||
|
// Select the worktree (whether it existed or was just added)
|
||||||
|
setCurrentWorktree(currentProject.path, worktreeResult.path, worktreeResult.branch);
|
||||||
|
},
|
||||||
|
[currentProject, getWorktrees, setWorktrees, setCurrentWorktree]
|
||||||
|
);
|
||||||
|
|
||||||
// Extract all action handlers into a hook
|
// Extract all action handlers into a hook
|
||||||
const {
|
const {
|
||||||
handleAddFeature,
|
handleAddFeature,
|
||||||
@@ -467,43 +492,90 @@ export function BoardView() {
|
|||||||
outputFeature,
|
outputFeature,
|
||||||
projectPath: currentProject?.path || null,
|
projectPath: currentProject?.path || null,
|
||||||
onWorktreeCreated: () => setWorktreeRefreshKey((k) => k + 1),
|
onWorktreeCreated: () => setWorktreeRefreshKey((k) => k + 1),
|
||||||
onWorktreeAutoSelect: (newWorktree) => {
|
onWorktreeAutoSelect: addAndSelectWorktree,
|
||||||
if (!currentProject) return;
|
|
||||||
// Check if worktree already exists in the store (by branch name)
|
|
||||||
const currentWorktrees = getWorktrees(currentProject.path);
|
|
||||||
const existingWorktree = currentWorktrees.find((w) => w.branch === newWorktree.branch);
|
|
||||||
|
|
||||||
// Only add if it doesn't already exist (to avoid duplicates)
|
|
||||||
if (!existingWorktree) {
|
|
||||||
const newWorktreeInfo = {
|
|
||||||
path: newWorktree.path,
|
|
||||||
branch: newWorktree.branch,
|
|
||||||
isMain: false,
|
|
||||||
isCurrent: false,
|
|
||||||
hasWorktree: true,
|
|
||||||
};
|
|
||||||
setWorktrees(currentProject.path, [...currentWorktrees, newWorktreeInfo]);
|
|
||||||
}
|
|
||||||
// Select the worktree (whether it existed or was just added)
|
|
||||||
setCurrentWorktree(currentProject.path, newWorktree.path, newWorktree.branch);
|
|
||||||
},
|
|
||||||
currentWorktreeBranch,
|
currentWorktreeBranch,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handler for bulk updating multiple features
|
// Handler for bulk updating multiple features
|
||||||
const handleBulkUpdate = useCallback(
|
const handleBulkUpdate = useCallback(
|
||||||
async (updates: Partial<Feature>) => {
|
async (updates: Partial<Feature>, workMode: 'current' | 'auto' | 'custom') => {
|
||||||
if (!currentProject || selectedFeatureIds.size === 0) return;
|
if (!currentProject || selectedFeatureIds.size === 0) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Determine final branch name based on work mode:
|
||||||
|
// - 'current': Empty string to clear branch assignment (work on main/current branch)
|
||||||
|
// - 'auto': Auto-generate branch name based on current branch
|
||||||
|
// - 'custom': Use the provided branch name
|
||||||
|
let finalBranchName: string | undefined;
|
||||||
|
|
||||||
|
if (workMode === 'current') {
|
||||||
|
// Empty string clears the branch assignment, moving features to main/current branch
|
||||||
|
finalBranchName = '';
|
||||||
|
} else if (workMode === 'auto') {
|
||||||
|
// Auto-generate a branch name based on current branch and timestamp
|
||||||
|
const baseBranch =
|
||||||
|
currentWorktreeBranch || getPrimaryWorktreeBranch(currentProject.path) || 'main';
|
||||||
|
const timestamp = Date.now();
|
||||||
|
const randomSuffix = Math.random().toString(36).substring(2, 6);
|
||||||
|
finalBranchName = `feature/${baseBranch}-${timestamp}-${randomSuffix}`;
|
||||||
|
} else {
|
||||||
|
// Custom mode - use provided branch name
|
||||||
|
finalBranchName = updates.branchName || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create worktree for 'auto' or 'custom' modes when we have a branch name
|
||||||
|
if ((workMode === 'auto' || workMode === 'custom') && finalBranchName) {
|
||||||
|
try {
|
||||||
|
const electronApi = getElectronAPI();
|
||||||
|
if (electronApi?.worktree?.create) {
|
||||||
|
const result = await electronApi.worktree.create(
|
||||||
|
currentProject.path,
|
||||||
|
finalBranchName
|
||||||
|
);
|
||||||
|
if (result.success && result.worktree) {
|
||||||
|
logger.info(
|
||||||
|
`Worktree for branch "${finalBranchName}" ${
|
||||||
|
result.worktree?.isNew ? 'created' : 'already exists'
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
// Auto-select the worktree when creating/using it for bulk update
|
||||||
|
addAndSelectWorktree(result.worktree);
|
||||||
|
// Refresh worktree list in UI
|
||||||
|
setWorktreeRefreshKey((k) => k + 1);
|
||||||
|
} else if (!result.success) {
|
||||||
|
logger.error(
|
||||||
|
`Failed to create worktree for branch "${finalBranchName}":`,
|
||||||
|
result.error
|
||||||
|
);
|
||||||
|
toast.error('Failed to create worktree', {
|
||||||
|
description: result.error || 'An error occurred',
|
||||||
|
});
|
||||||
|
return; // Don't proceed with update if worktree creation failed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error creating worktree:', error);
|
||||||
|
toast.error('Failed to create worktree', {
|
||||||
|
description: error instanceof Error ? error.message : 'An error occurred',
|
||||||
|
});
|
||||||
|
return; // Don't proceed with update if worktree creation failed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the final branch name in updates
|
||||||
|
const finalUpdates = {
|
||||||
|
...updates,
|
||||||
|
branchName: finalBranchName,
|
||||||
|
};
|
||||||
|
|
||||||
const api = getHttpApiClient();
|
const api = getHttpApiClient();
|
||||||
const featureIds = Array.from(selectedFeatureIds);
|
const featureIds = Array.from(selectedFeatureIds);
|
||||||
const result = await api.features.bulkUpdate(currentProject.path, featureIds, updates);
|
const result = await api.features.bulkUpdate(currentProject.path, featureIds, finalUpdates);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
// Update local state
|
// Update local state
|
||||||
featureIds.forEach((featureId) => {
|
featureIds.forEach((featureId) => {
|
||||||
updateFeature(featureId, updates);
|
updateFeature(featureId, finalUpdates);
|
||||||
});
|
});
|
||||||
toast.success(`Updated ${result.updatedCount} features`);
|
toast.success(`Updated ${result.updatedCount} features`);
|
||||||
exitSelectionMode();
|
exitSelectionMode();
|
||||||
@@ -517,7 +589,16 @@ export function BoardView() {
|
|||||||
toast.error('Failed to update features');
|
toast.error('Failed to update features');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[currentProject, selectedFeatureIds, updateFeature, exitSelectionMode]
|
[
|
||||||
|
currentProject,
|
||||||
|
selectedFeatureIds,
|
||||||
|
updateFeature,
|
||||||
|
exitSelectionMode,
|
||||||
|
currentWorktreeBranch,
|
||||||
|
getPrimaryWorktreeBranch,
|
||||||
|
addAndSelectWorktree,
|
||||||
|
setWorktreeRefreshKey,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handler for bulk deleting multiple features
|
// Handler for bulk deleting multiple features
|
||||||
@@ -1325,6 +1406,9 @@ export function BoardView() {
|
|||||||
onClose={() => setShowMassEditDialog(false)}
|
onClose={() => setShowMassEditDialog(false)}
|
||||||
selectedFeatures={selectedFeatures}
|
selectedFeatures={selectedFeatures}
|
||||||
onApply={handleBulkUpdate}
|
onApply={handleBulkUpdate}
|
||||||
|
branchSuggestions={branchSuggestions}
|
||||||
|
branchCardCounts={branchCardCounts}
|
||||||
|
currentBranch={currentWorktreeBranch || undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Board Background Modal */}
|
{/* Board Background Modal */}
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ export function BoardHeader({
|
|||||||
<div className={controlContainerClass} data-testid="worktrees-toggle-container">
|
<div className={controlContainerClass} data-testid="worktrees-toggle-container">
|
||||||
<GitBranch className="w-4 h-4 text-muted-foreground" />
|
<GitBranch className="w-4 h-4 text-muted-foreground" />
|
||||||
<Label htmlFor="worktrees-toggle" className="text-sm font-medium cursor-pointer">
|
<Label htmlFor="worktrees-toggle" className="text-sm font-medium cursor-pointer">
|
||||||
Worktrees
|
Worktree Bar
|
||||||
</Label>
|
</Label>
|
||||||
<Switch
|
<Switch
|
||||||
id="worktrees-toggle"
|
id="worktrees-toggle"
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ interface AddFeatureDialogProps {
|
|||||||
selectedNonMainWorktreeBranch?: string;
|
selectedNonMainWorktreeBranch?: string;
|
||||||
/**
|
/**
|
||||||
* When true, forces the dialog to default to 'current' work mode (work on current branch).
|
* When true, forces the dialog to default to 'current' work mode (work on current branch).
|
||||||
* This is used when the "Use selected worktree branch" setting is disabled.
|
* This is used when the "Default to worktree mode" setting is disabled.
|
||||||
*/
|
*/
|
||||||
forceCurrentBranchMode?: boolean;
|
forceCurrentBranchMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ export function BacklogPlanDialog({
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="py-4">{renderContent()}</div>
|
<div className="py-4 overflow-y-auto">{renderContent()}</div>
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
{mode === 'input' && (
|
{mode === 'input' && (
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export function CreatePRDialog({
|
|||||||
description: `PR already exists for ${result.result.branch}`,
|
description: `PR already exists for ${result.result.branch}`,
|
||||||
action: {
|
action: {
|
||||||
label: 'View PR',
|
label: 'View PR',
|
||||||
onClick: () => window.open(result.result!.prUrl!, '_blank'),
|
onClick: () => window.open(result.result!.prUrl!, '_blank', 'noopener,noreferrer'),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -125,7 +125,7 @@ export function CreatePRDialog({
|
|||||||
description: `PR created from ${result.result.branch}`,
|
description: `PR created from ${result.result.branch}`,
|
||||||
action: {
|
action: {
|
||||||
label: 'View PR',
|
label: 'View PR',
|
||||||
onClick: () => window.open(result.result!.prUrl!, '_blank'),
|
onClick: () => window.open(result.result!.prUrl!, '_blank', 'noopener,noreferrer'),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,10 @@ export function CreatePRDialog({
|
|||||||
<p className="text-sm text-muted-foreground mt-1">Your PR is ready for review</p>
|
<p className="text-sm text-muted-foreground mt-1">Your PR is ready for review</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 justify-center">
|
<div className="flex gap-2 justify-center">
|
||||||
<Button onClick={() => window.open(prUrl, '_blank')} className="gap-2">
|
<Button
|
||||||
|
onClick={() => window.open(prUrl, '_blank', 'noopener,noreferrer')}
|
||||||
|
className="gap-2"
|
||||||
|
>
|
||||||
<ExternalLink className="w-4 h-4" />
|
<ExternalLink className="w-4 h-4" />
|
||||||
View Pull Request
|
View Pull Request
|
||||||
</Button>
|
</Button>
|
||||||
@@ -277,7 +280,7 @@ export function CreatePRDialog({
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (browserUrl) {
|
if (browserUrl) {
|
||||||
window.open(browserUrl, '_blank');
|
window.open(browserUrl, '_blank', 'noopener,noreferrer');
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="gap-2 w-full"
|
className="gap-2 w-full"
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { AlertCircle } from 'lucide-react';
|
import { AlertCircle } from 'lucide-react';
|
||||||
import { modelSupportsThinking } from '@/lib/utils';
|
import { modelSupportsThinking } from '@/lib/utils';
|
||||||
import { Feature, ModelAlias, ThinkingLevel, PlanningMode } from '@/store/app-store';
|
import { Feature, ModelAlias, ThinkingLevel, PlanningMode } from '@/store/app-store';
|
||||||
import { TestingTabContent, PrioritySelect, PlanningModeSelect } from '../shared';
|
import { TestingTabContent, PrioritySelect, PlanningModeSelect, WorkModeSelector } from '../shared';
|
||||||
|
import type { WorkMode } from '../shared';
|
||||||
import { PhaseModelSelector } from '@/components/views/settings-view/model-defaults/phase-model-selector';
|
import { PhaseModelSelector } from '@/components/views/settings-view/model-defaults/phase-model-selector';
|
||||||
import { isCursorModel, isClaudeModel, type PhaseModelEntry } from '@automaker/types';
|
import { isCursorModel, isClaudeModel, type PhaseModelEntry } from '@automaker/types';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
@@ -23,7 +24,10 @@ interface MassEditDialogProps {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
selectedFeatures: Feature[];
|
selectedFeatures: Feature[];
|
||||||
onApply: (updates: Partial<Feature>) => Promise<void>;
|
onApply: (updates: Partial<Feature>, workMode: WorkMode) => Promise<void>;
|
||||||
|
branchSuggestions: string[];
|
||||||
|
branchCardCounts?: Record<string, number>;
|
||||||
|
currentBranch?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ApplyState {
|
interface ApplyState {
|
||||||
@@ -33,6 +37,7 @@ interface ApplyState {
|
|||||||
requirePlanApproval: boolean;
|
requirePlanApproval: boolean;
|
||||||
priority: boolean;
|
priority: boolean;
|
||||||
skipTests: boolean;
|
skipTests: boolean;
|
||||||
|
branchName: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMixedValues(features: Feature[]): Record<string, boolean> {
|
function getMixedValues(features: Feature[]): Record<string, boolean> {
|
||||||
@@ -47,6 +52,7 @@ function getMixedValues(features: Feature[]): Record<string, boolean> {
|
|||||||
),
|
),
|
||||||
priority: !features.every((f) => f.priority === first.priority),
|
priority: !features.every((f) => f.priority === first.priority),
|
||||||
skipTests: !features.every((f) => f.skipTests === first.skipTests),
|
skipTests: !features.every((f) => f.skipTests === first.skipTests),
|
||||||
|
branchName: !features.every((f) => f.branchName === first.branchName),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +103,15 @@ function FieldWrapper({ label, isMixed, willApply, onApplyChange, children }: Fi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: MassEditDialogProps) {
|
export function MassEditDialog({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
selectedFeatures,
|
||||||
|
onApply,
|
||||||
|
branchSuggestions,
|
||||||
|
branchCardCounts,
|
||||||
|
currentBranch,
|
||||||
|
}: MassEditDialogProps) {
|
||||||
const [isApplying, setIsApplying] = useState(false);
|
const [isApplying, setIsApplying] = useState(false);
|
||||||
|
|
||||||
// Track which fields to apply
|
// Track which fields to apply
|
||||||
@@ -108,6 +122,7 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
|
|||||||
requirePlanApproval: false,
|
requirePlanApproval: false,
|
||||||
priority: false,
|
priority: false,
|
||||||
skipTests: false,
|
skipTests: false,
|
||||||
|
branchName: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Field values
|
// Field values
|
||||||
@@ -118,6 +133,18 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
|
|||||||
const [priority, setPriority] = useState(2);
|
const [priority, setPriority] = useState(2);
|
||||||
const [skipTests, setSkipTests] = useState(false);
|
const [skipTests, setSkipTests] = useState(false);
|
||||||
|
|
||||||
|
// Work mode and branch name state
|
||||||
|
const [workMode, setWorkMode] = useState<WorkMode>(() => {
|
||||||
|
// Derive initial work mode from first selected feature's branchName
|
||||||
|
if (selectedFeatures.length > 0 && selectedFeatures[0].branchName) {
|
||||||
|
return 'custom';
|
||||||
|
}
|
||||||
|
return 'current';
|
||||||
|
});
|
||||||
|
const [branchName, setBranchName] = useState(() => {
|
||||||
|
return getInitialValue(selectedFeatures, 'branchName', '') as string;
|
||||||
|
});
|
||||||
|
|
||||||
// Calculate mixed values
|
// Calculate mixed values
|
||||||
const mixedValues = useMemo(() => getMixedValues(selectedFeatures), [selectedFeatures]);
|
const mixedValues = useMemo(() => getMixedValues(selectedFeatures), [selectedFeatures]);
|
||||||
|
|
||||||
@@ -131,6 +158,7 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
|
|||||||
requirePlanApproval: false,
|
requirePlanApproval: false,
|
||||||
priority: false,
|
priority: false,
|
||||||
skipTests: false,
|
skipTests: false,
|
||||||
|
branchName: false,
|
||||||
});
|
});
|
||||||
setModel(getInitialValue(selectedFeatures, 'model', 'sonnet') as ModelAlias);
|
setModel(getInitialValue(selectedFeatures, 'model', 'sonnet') as ModelAlias);
|
||||||
setThinkingLevel(getInitialValue(selectedFeatures, 'thinkingLevel', 'none') as ThinkingLevel);
|
setThinkingLevel(getInitialValue(selectedFeatures, 'thinkingLevel', 'none') as ThinkingLevel);
|
||||||
@@ -138,6 +166,10 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
|
|||||||
setRequirePlanApproval(getInitialValue(selectedFeatures, 'requirePlanApproval', false));
|
setRequirePlanApproval(getInitialValue(selectedFeatures, 'requirePlanApproval', false));
|
||||||
setPriority(getInitialValue(selectedFeatures, 'priority', 2));
|
setPriority(getInitialValue(selectedFeatures, 'priority', 2));
|
||||||
setSkipTests(getInitialValue(selectedFeatures, 'skipTests', false));
|
setSkipTests(getInitialValue(selectedFeatures, 'skipTests', false));
|
||||||
|
// Reset work mode and branch name
|
||||||
|
const initialBranchName = getInitialValue(selectedFeatures, 'branchName', '') as string;
|
||||||
|
setBranchName(initialBranchName);
|
||||||
|
setWorkMode(initialBranchName ? 'custom' : 'current');
|
||||||
}
|
}
|
||||||
}, [open, selectedFeatures]);
|
}, [open, selectedFeatures]);
|
||||||
|
|
||||||
@@ -150,6 +182,12 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
|
|||||||
if (applyState.requirePlanApproval) updates.requirePlanApproval = requirePlanApproval;
|
if (applyState.requirePlanApproval) updates.requirePlanApproval = requirePlanApproval;
|
||||||
if (applyState.priority) updates.priority = priority;
|
if (applyState.priority) updates.priority = priority;
|
||||||
if (applyState.skipTests) updates.skipTests = skipTests;
|
if (applyState.skipTests) updates.skipTests = skipTests;
|
||||||
|
if (applyState.branchName) {
|
||||||
|
// For 'current' mode, use empty string (work on current branch)
|
||||||
|
// For 'auto' mode, use empty string (will be auto-generated)
|
||||||
|
// For 'custom' mode, use the specified branch name
|
||||||
|
updates.branchName = workMode === 'custom' ? branchName : '';
|
||||||
|
}
|
||||||
|
|
||||||
if (Object.keys(updates).length === 0) {
|
if (Object.keys(updates).length === 0) {
|
||||||
onClose();
|
onClose();
|
||||||
@@ -158,7 +196,7 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
|
|||||||
|
|
||||||
setIsApplying(true);
|
setIsApplying(true);
|
||||||
try {
|
try {
|
||||||
await onApply(updates);
|
await onApply(updates, workMode);
|
||||||
onClose();
|
onClose();
|
||||||
} finally {
|
} finally {
|
||||||
setIsApplying(false);
|
setIsApplying(false);
|
||||||
@@ -293,6 +331,25 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
|
|||||||
testIdPrefix="mass-edit"
|
testIdPrefix="mass-edit"
|
||||||
/>
|
/>
|
||||||
</FieldWrapper>
|
</FieldWrapper>
|
||||||
|
|
||||||
|
{/* Branch / Work Mode */}
|
||||||
|
<FieldWrapper
|
||||||
|
label="Branch / Work Mode"
|
||||||
|
isMixed={mixedValues.branchName}
|
||||||
|
willApply={applyState.branchName}
|
||||||
|
onApplyChange={(apply) => setApplyState((prev) => ({ ...prev, branchName: apply }))}
|
||||||
|
>
|
||||||
|
<WorkModeSelector
|
||||||
|
workMode={workMode}
|
||||||
|
onWorkModeChange={setWorkMode}
|
||||||
|
branchName={branchName}
|
||||||
|
onBranchNameChange={setBranchName}
|
||||||
|
branchSuggestions={branchSuggestions}
|
||||||
|
branchCardCounts={branchCardCounts}
|
||||||
|
currentBranch={currentBranch}
|
||||||
|
testIdPrefix="mass-edit-work-mode"
|
||||||
|
/>
|
||||||
|
</FieldWrapper>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function PlanSettingsDialog({
|
|||||||
className="text-sm font-medium cursor-pointer flex items-center gap-2"
|
className="text-sm font-medium cursor-pointer flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<GitBranch className="w-4 h-4 text-brand-500" />
|
<GitBranch className="w-4 h-4 text-brand-500" />
|
||||||
Use selected worktree branch
|
Default to worktree mode
|
||||||
</Label>
|
</Label>
|
||||||
<Switch
|
<Switch
|
||||||
id="plan-worktree-branch-toggle"
|
id="plan-worktree-branch-toggle"
|
||||||
@@ -55,8 +55,8 @@ export function PlanSettingsDialog({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||||
When enabled, features created via the Plan dialog will be assigned to the currently
|
Planned features will automatically use isolated worktrees, keeping changes separate
|
||||||
selected worktree branch. When disabled, features will be added to the main branch.
|
from your main branch until you're ready to merge.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function WorktreeSettingsDialog({
|
|||||||
className="text-sm font-medium cursor-pointer flex items-center gap-2"
|
className="text-sm font-medium cursor-pointer flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<GitBranch className="w-4 h-4 text-brand-500" />
|
<GitBranch className="w-4 h-4 text-brand-500" />
|
||||||
Use selected worktree branch
|
Default to worktree mode
|
||||||
</Label>
|
</Label>
|
||||||
<Switch
|
<Switch
|
||||||
id="worktree-branch-toggle"
|
id="worktree-branch-toggle"
|
||||||
@@ -55,8 +55,8 @@ export function WorktreeSettingsDialog({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||||
When enabled, the Add Feature dialog will default to custom branch mode with the
|
New features will automatically use isolated worktrees, keeping changes separate
|
||||||
currently selected worktree branch pre-filled.
|
from your main branch until you're ready to merge.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Badge } from '@/components/ui/badge';
|
|||||||
import { Brain, AlertTriangle } from 'lucide-react';
|
import { Brain, AlertTriangle } from 'lucide-react';
|
||||||
import { AnthropicIcon, CursorIcon, OpenAIIcon } from '@/components/ui/provider-icon';
|
import { AnthropicIcon, CursorIcon, OpenAIIcon } from '@/components/ui/provider-icon';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import type { ModelAlias } from '@/store/app-store';
|
||||||
import { useAppStore } from '@/store/app-store';
|
import { useAppStore } from '@/store/app-store';
|
||||||
import { useSetupStore } from '@/store/setup-store';
|
import { useSetupStore } from '@/store/setup-store';
|
||||||
import { getModelProvider, PROVIDER_PREFIXES, stripProviderPrefix } from '@automaker/types';
|
import { getModelProvider, PROVIDER_PREFIXES, stripProviderPrefix } from '@automaker/types';
|
||||||
@@ -18,10 +19,6 @@ interface ModelSelectorProps {
|
|||||||
testIdPrefix?: string;
|
testIdPrefix?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CODEX_EMPTY_AVAILABLE_MESSAGE = 'No Codex models available';
|
|
||||||
const CODEX_EMPTY_ENABLED_MESSAGE =
|
|
||||||
'No Codex models enabled. Enable models in Settings → AI Providers.';
|
|
||||||
|
|
||||||
export function ModelSelector({
|
export function ModelSelector({
|
||||||
selectedModel,
|
selectedModel,
|
||||||
onModelSelect,
|
onModelSelect,
|
||||||
@@ -30,8 +27,6 @@ export function ModelSelector({
|
|||||||
const {
|
const {
|
||||||
enabledCursorModels,
|
enabledCursorModels,
|
||||||
cursorDefaultModel,
|
cursorDefaultModel,
|
||||||
enabledCodexModels,
|
|
||||||
codexDefaultModel,
|
|
||||||
codexModels,
|
codexModels,
|
||||||
codexModelsLoading,
|
codexModelsLoading,
|
||||||
codexModelsError,
|
codexModelsError,
|
||||||
@@ -54,10 +49,8 @@ export function ModelSelector({
|
|||||||
}
|
}
|
||||||
}, [isCodexAvailable, codexModels.length, codexModelsLoading, fetchCodexModels]);
|
}, [isCodexAvailable, codexModels.length, codexModelsLoading, fetchCodexModels]);
|
||||||
|
|
||||||
const enabledCodexModelIds = new Set(enabledCodexModels);
|
|
||||||
|
|
||||||
// Transform codex models from store to ModelOption format
|
// Transform codex models from store to ModelOption format
|
||||||
const codexModelOptions: ModelOption[] = codexModels.map((model) => {
|
const dynamicCodexModels: ModelOption[] = codexModels.map((model) => {
|
||||||
// Infer badge based on tier
|
// Infer badge based on tier
|
||||||
let badge: string | undefined;
|
let badge: string | undefined;
|
||||||
if (model.tier === 'premium') badge = 'Premium';
|
if (model.tier === 'premium') badge = 'Premium';
|
||||||
@@ -74,10 +67,6 @@ export function ModelSelector({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const enabledCodexModelOptions = codexModelOptions.filter((model) =>
|
|
||||||
enabledCodexModelIds.has(model.id)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter Cursor models based on enabled models from global settings
|
// Filter Cursor models based on enabled models from global settings
|
||||||
const filteredCursorModels = CURSOR_MODELS.filter((model) => {
|
const filteredCursorModels = CURSOR_MODELS.filter((model) => {
|
||||||
// Extract the cursor model ID from the prefixed ID (e.g., "cursor-auto" -> "auto")
|
// Extract the cursor model ID from the prefixed ID (e.g., "cursor-auto" -> "auto")
|
||||||
@@ -85,36 +74,21 @@ export function ModelSelector({
|
|||||||
return enabledCursorModels.includes(cursorModelId as any);
|
return enabledCursorModels.includes(cursorModelId as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasEnabledCodexModels = enabledCodexModelOptions.length > 0;
|
|
||||||
const codexDefaultSelection =
|
|
||||||
codexModelOptions.find((model) => model.id === codexDefaultModel)?.id ||
|
|
||||||
enabledCodexModelOptions[0]?.id ||
|
|
||||||
codexModelOptions[0]?.id;
|
|
||||||
|
|
||||||
const handleProviderChange = (provider: ModelProvider) => {
|
const handleProviderChange = (provider: ModelProvider) => {
|
||||||
if (provider === 'cursor' && selectedProvider !== 'cursor') {
|
if (provider === 'cursor' && selectedProvider !== 'cursor') {
|
||||||
// Switch to Cursor's default model (from global settings)
|
// Switch to Cursor's default model (from global settings)
|
||||||
onModelSelect(`${PROVIDER_PREFIXES.cursor}${cursorDefaultModel}`);
|
onModelSelect(`${PROVIDER_PREFIXES.cursor}${cursorDefaultModel}`);
|
||||||
} else if (provider === 'codex' && selectedProvider !== 'codex') {
|
} else if (provider === 'codex' && selectedProvider !== 'codex') {
|
||||||
// Switch to Codex's default model (from global settings)
|
// Switch to Codex's default model (use isDefault flag from dynamic models)
|
||||||
if (codexDefaultSelection) {
|
const defaultModel = codexModels.find((m) => m.isDefault);
|
||||||
onModelSelect(codexDefaultSelection);
|
const defaultModelId = defaultModel?.id || codexModels[0]?.id || 'codex-gpt-5.2-codex';
|
||||||
}
|
onModelSelect(defaultModelId);
|
||||||
} else if (provider === 'claude' && selectedProvider !== 'claude') {
|
} else if (provider === 'claude' && selectedProvider !== 'claude') {
|
||||||
// Switch to Claude's default model
|
// Switch to Claude's default model
|
||||||
onModelSelect('sonnet');
|
onModelSelect('sonnet');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const showCodexAvailableEmpty =
|
|
||||||
!codexModelsLoading && !codexModelsError && codexModelOptions.length === 0;
|
|
||||||
const showCodexEnabledEmpty =
|
|
||||||
!codexModelsLoading &&
|
|
||||||
!codexModelsError &&
|
|
||||||
codexModelOptions.length > 0 &&
|
|
||||||
!hasEnabledCodexModels;
|
|
||||||
const showCodexList = !codexModelsLoading && !codexModelsError && hasEnabledCodexModels;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Provider Selection */}
|
{/* Provider Selection */}
|
||||||
@@ -298,7 +272,7 @@ export function ModelSelector({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Loading state */}
|
{/* Loading state */}
|
||||||
{codexModelsLoading && codexModelOptions.length === 0 && (
|
{codexModelsLoading && dynamicCodexModels.length === 0 && (
|
||||||
<div className="flex items-center justify-center gap-2 p-6 text-sm text-muted-foreground">
|
<div className="flex items-center justify-center gap-2 p-6 text-sm text-muted-foreground">
|
||||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||||
Loading models...
|
Loading models...
|
||||||
@@ -323,21 +297,15 @@ export function ModelSelector({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Model list */}
|
{/* Model list */}
|
||||||
{showCodexAvailableEmpty && (
|
{!codexModelsLoading && !codexModelsError && dynamicCodexModels.length === 0 && (
|
||||||
<div className="text-sm text-muted-foreground p-3 border border-dashed rounded-md text-center">
|
<div className="text-sm text-muted-foreground p-3 border border-dashed rounded-md text-center">
|
||||||
{CODEX_EMPTY_AVAILABLE_MESSAGE}
|
No Codex models available
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{showCodexEnabledEmpty && (
|
{!codexModelsLoading && dynamicCodexModels.length > 0 && (
|
||||||
<div className="text-sm text-muted-foreground p-3 border border-dashed rounded-md text-center">
|
|
||||||
{CODEX_EMPTY_ENABLED_MESSAGE}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{showCodexList && (
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{enabledCodexModelOptions.map((option) => {
|
{dynamicCodexModels.map((option) => {
|
||||||
const isSelected = selectedModel === option.id;
|
const isSelected = selectedModel === option.id;
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -143,8 +143,12 @@ export function WorktreeActionsDropdown({
|
|||||||
<span className="w-2 h-2 rounded-full bg-green-500 animate-pulse" />
|
<span className="w-2 h-2 rounded-full bg-green-500 animate-pulse" />
|
||||||
Dev Server Running (:{devServerInfo?.port})
|
Dev Server Running (:{devServerInfo?.port})
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
<DropdownMenuItem onClick={() => onOpenDevServerUrl(worktree)} className="text-xs">
|
<DropdownMenuItem
|
||||||
<Globe className="w-3.5 h-3.5 mr-2" />
|
onClick={() => onOpenDevServerUrl(worktree)}
|
||||||
|
className="text-xs"
|
||||||
|
aria-label={`Open dev server on port ${devServerInfo?.port} in browser`}
|
||||||
|
>
|
||||||
|
<Globe className="w-3.5 h-3.5 mr-2" aria-hidden="true" />
|
||||||
Open in Browser
|
Open in Browser
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
@@ -320,7 +324,7 @@ export function WorktreeActionsDropdown({
|
|||||||
<>
|
<>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open(worktree.pr!.url, '_blank');
|
window.open(worktree.pr!.url, '_blank', 'noopener,noreferrer');
|
||||||
}}
|
}}
|
||||||
className="text-xs"
|
className="text-xs"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -298,20 +298,29 @@ export function WorktreeTab({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{isDevServerRunning && (
|
{isDevServerRunning && (
|
||||||
<Button
|
<TooltipProvider>
|
||||||
variant={isSelected ? 'default' : 'outline'}
|
<Tooltip>
|
||||||
size="sm"
|
<TooltipTrigger asChild>
|
||||||
className={cn(
|
<Button
|
||||||
'h-7 w-7 p-0 rounded-none border-r-0',
|
variant={isSelected ? 'default' : 'outline'}
|
||||||
isSelected && 'bg-primary text-primary-foreground',
|
size="sm"
|
||||||
!isSelected && 'bg-secondary/50 hover:bg-secondary',
|
className={cn(
|
||||||
'text-green-500'
|
'h-7 w-7 p-0 rounded-none border-r-0',
|
||||||
)}
|
isSelected && 'bg-primary text-primary-foreground',
|
||||||
onClick={() => onOpenDevServerUrl(worktree)}
|
!isSelected && 'bg-secondary/50 hover:bg-secondary',
|
||||||
title={`Open dev server (port ${devServerInfo?.port})`}
|
'text-green-500'
|
||||||
>
|
)}
|
||||||
<Globe className="w-3 h-3" />
|
onClick={() => onOpenDevServerUrl(worktree)}
|
||||||
</Button>
|
aria-label={`Open dev server on port ${devServerInfo?.port} in browser`}
|
||||||
|
>
|
||||||
|
<Globe className="w-3 h-3" aria-hidden="true" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Open dev server (:{devServerInfo?.port})</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<WorktreeActionsDropdown
|
<WorktreeActionsDropdown
|
||||||
|
|||||||
@@ -118,8 +118,37 @@ export function useDevServers({ projectPath }: UseDevServersOptions) {
|
|||||||
const handleOpenDevServerUrl = useCallback(
|
const handleOpenDevServerUrl = useCallback(
|
||||||
(worktree: WorktreeInfo) => {
|
(worktree: WorktreeInfo) => {
|
||||||
const serverInfo = runningDevServers.get(getWorktreeKey(worktree));
|
const serverInfo = runningDevServers.get(getWorktreeKey(worktree));
|
||||||
if (serverInfo) {
|
if (!serverInfo) {
|
||||||
window.open(serverInfo.url, '_blank');
|
logger.warn('No dev server info found for worktree:', getWorktreeKey(worktree));
|
||||||
|
toast.error('Dev server not found', {
|
||||||
|
description: 'The dev server may have stopped. Try starting it again.',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Rewrite URL hostname to match the current browser's hostname.
|
||||||
|
// This ensures dev server URLs work when accessing Automaker from
|
||||||
|
// remote machines (e.g., 192.168.x.x or hostname.local instead of localhost).
|
||||||
|
const devServerUrl = new URL(serverInfo.url);
|
||||||
|
|
||||||
|
// Security: Only allow http/https protocols to prevent potential attacks
|
||||||
|
// via data:, javascript:, file:, or other dangerous URL schemes
|
||||||
|
if (devServerUrl.protocol !== 'http:' && devServerUrl.protocol !== 'https:') {
|
||||||
|
logger.error('Invalid dev server URL protocol:', devServerUrl.protocol);
|
||||||
|
toast.error('Invalid dev server URL', {
|
||||||
|
description: 'The server returned an unsupported URL protocol.',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
devServerUrl.hostname = window.location.hostname;
|
||||||
|
window.open(devServerUrl.toString(), '_blank', 'noopener,noreferrer');
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to parse dev server URL:', error);
|
||||||
|
toast.error('Failed to open dev server', {
|
||||||
|
description: 'The server URL could not be processed. Please try again.',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[runningDevServers, getWorktreeKey]
|
[runningDevServers, getWorktreeKey]
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function AddEditServerDialog({
|
|||||||
Configure an MCP server to extend agent capabilities with custom tools.
|
Configure an MCP server to extend agent capabilities with custom tools.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="space-y-4 py-4">
|
<div className="space-y-4 py-4 overflow-y-auto">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="server-name">Name</Label>
|
<Label htmlFor="server-name">Name</Label>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@@ -159,9 +159,6 @@ export function PhaseModelSelector({
|
|||||||
const expandedCodexTriggerRef = useRef<HTMLDivElement>(null);
|
const expandedCodexTriggerRef = useRef<HTMLDivElement>(null);
|
||||||
const {
|
const {
|
||||||
enabledCursorModels,
|
enabledCursorModels,
|
||||||
enabledCodexModels,
|
|
||||||
enabledOpencodeModels,
|
|
||||||
enabledDynamicModelIds,
|
|
||||||
favoriteModels,
|
favoriteModels,
|
||||||
toggleFavoriteModel,
|
toggleFavoriteModel,
|
||||||
codexModels,
|
codexModels,
|
||||||
@@ -264,14 +261,6 @@ export function PhaseModelSelector({
|
|||||||
}));
|
}));
|
||||||
}, [codexModels]);
|
}, [codexModels]);
|
||||||
|
|
||||||
const availableCodexModels = useMemo(
|
|
||||||
() =>
|
|
||||||
transformedCodexModels.filter((model) =>
|
|
||||||
enabledCodexModels.includes(model.id as CodexModelId)
|
|
||||||
),
|
|
||||||
[transformedCodexModels, enabledCodexModels]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter Cursor models to only show enabled ones
|
// Filter Cursor models to only show enabled ones
|
||||||
const availableCursorModels = CURSOR_MODELS.filter((model) => {
|
const availableCursorModels = CURSOR_MODELS.filter((model) => {
|
||||||
const cursorId = stripProviderPrefix(model.id) as CursorModelId;
|
const cursorId = stripProviderPrefix(model.id) as CursorModelId;
|
||||||
@@ -377,20 +366,16 @@ export function PhaseModelSelector({
|
|||||||
// Combine static and dynamic OpenCode models
|
// Combine static and dynamic OpenCode models
|
||||||
const allOpencodeModels: ModelOption[] = useMemo(() => {
|
const allOpencodeModels: ModelOption[] = useMemo(() => {
|
||||||
// Start with static models
|
// Start with static models
|
||||||
const staticModels = OPENCODE_MODELS.filter((model) =>
|
const staticModels = [...OPENCODE_MODELS];
|
||||||
enabledOpencodeModels.includes(model.id)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add dynamic models (convert ModelDefinition to ModelOption)
|
// Add dynamic models (convert ModelDefinition to ModelOption)
|
||||||
const dynamicModelOptions: ModelOption[] = dynamicOpencodeModels
|
const dynamicModelOptions: ModelOption[] = dynamicOpencodeModels.map((model) => ({
|
||||||
.filter((model) => enabledDynamicModelIds.includes(model.id))
|
id: model.id,
|
||||||
.map((model) => ({
|
label: model.name,
|
||||||
id: model.id,
|
description: model.description,
|
||||||
label: model.name,
|
badge: model.tier === 'premium' ? 'Premium' : model.tier === 'basic' ? 'Free' : undefined,
|
||||||
description: model.description,
|
provider: 'opencode' as const,
|
||||||
badge: model.tier === 'premium' ? 'Premium' : model.tier === 'basic' ? 'Free' : undefined,
|
}));
|
||||||
provider: 'opencode' as const,
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Merge, avoiding duplicates (static models take precedence for same ID)
|
// Merge, avoiding duplicates (static models take precedence for same ID)
|
||||||
// In practice, static and dynamic IDs don't overlap
|
// In practice, static and dynamic IDs don't overlap
|
||||||
@@ -398,14 +383,14 @@ export function PhaseModelSelector({
|
|||||||
const uniqueDynamic = dynamicModelOptions.filter((m) => !staticIds.has(m.id));
|
const uniqueDynamic = dynamicModelOptions.filter((m) => !staticIds.has(m.id));
|
||||||
|
|
||||||
return [...staticModels, ...uniqueDynamic];
|
return [...staticModels, ...uniqueDynamic];
|
||||||
}, [dynamicOpencodeModels, enabledOpencodeModels, enabledDynamicModelIds]);
|
}, [dynamicOpencodeModels]);
|
||||||
|
|
||||||
// Group models
|
// Group models
|
||||||
const { favorites, claude, cursor, codex, opencode } = useMemo(() => {
|
const { favorites, claude, cursor, codex, opencode } = useMemo(() => {
|
||||||
const favs: typeof CLAUDE_MODELS = [];
|
const favs: typeof CLAUDE_MODELS = [];
|
||||||
const cModels: typeof CLAUDE_MODELS = [];
|
const cModels: typeof CLAUDE_MODELS = [];
|
||||||
const curModels: typeof CURSOR_MODELS = [];
|
const curModels: typeof CURSOR_MODELS = [];
|
||||||
const codModels: typeof availableCodexModels = [];
|
const codModels: typeof transformedCodexModels = [];
|
||||||
const ocModels: ModelOption[] = [];
|
const ocModels: ModelOption[] = [];
|
||||||
|
|
||||||
// Process Claude Models
|
// Process Claude Models
|
||||||
@@ -427,7 +412,7 @@ export function PhaseModelSelector({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Process Codex Models
|
// Process Codex Models
|
||||||
availableCodexModels.forEach((model) => {
|
transformedCodexModels.forEach((model) => {
|
||||||
if (favoriteModels.includes(model.id)) {
|
if (favoriteModels.includes(model.id)) {
|
||||||
favs.push(model);
|
favs.push(model);
|
||||||
} else {
|
} else {
|
||||||
@@ -451,7 +436,7 @@ export function PhaseModelSelector({
|
|||||||
codex: codModels,
|
codex: codModels,
|
||||||
opencode: ocModels,
|
opencode: ocModels,
|
||||||
};
|
};
|
||||||
}, [favoriteModels, availableCursorModels, availableCodexModels, allOpencodeModels]);
|
}, [favoriteModels, availableCursorModels, transformedCodexModels, allOpencodeModels]);
|
||||||
|
|
||||||
// Group OpenCode models by model type for better organization
|
// Group OpenCode models by model type for better organization
|
||||||
const opencodeSections = useMemo(() => {
|
const opencodeSections = useMemo(() => {
|
||||||
@@ -468,11 +453,8 @@ export function PhaseModelSelector({
|
|||||||
free: {},
|
free: {},
|
||||||
dynamic: {},
|
dynamic: {},
|
||||||
};
|
};
|
||||||
const enabledDynamicProviders = dynamicOpencodeModels.filter((model) =>
|
|
||||||
enabledDynamicModelIds.includes(model.id)
|
|
||||||
);
|
|
||||||
const dynamicProviderById = new Map(
|
const dynamicProviderById = new Map(
|
||||||
enabledDynamicProviders.map((model) => [model.id, model.provider])
|
dynamicOpencodeModels.map((model) => [model.id, model.provider])
|
||||||
);
|
);
|
||||||
|
|
||||||
const resolveProviderKey = (modelId: string): string => {
|
const resolveProviderKey = (modelId: string): string => {
|
||||||
@@ -542,10 +524,10 @@ export function PhaseModelSelector({
|
|||||||
}).filter(Boolean) as OpencodeSection[];
|
}).filter(Boolean) as OpencodeSection[];
|
||||||
|
|
||||||
return builtSections;
|
return builtSections;
|
||||||
}, [opencode, dynamicOpencodeModels, enabledDynamicModelIds]);
|
}, [opencode, dynamicOpencodeModels]);
|
||||||
|
|
||||||
// Render Codex model item with secondary popover for reasoning effort (only for models that support it)
|
// Render Codex model item with secondary popover for reasoning effort (only for models that support it)
|
||||||
const renderCodexModelItem = (model: (typeof availableCodexModels)[0]) => {
|
const renderCodexModelItem = (model: (typeof transformedCodexModels)[0]) => {
|
||||||
const isSelected = selectedModel === model.id;
|
const isSelected = selectedModel === model.id;
|
||||||
const isFavorite = favoriteModels.includes(model.id);
|
const isFavorite = favoriteModels.includes(model.id);
|
||||||
const hasReasoning = codexModelHasThinking(model.id as CodexModelId);
|
const hasReasoning = codexModelHasThinking(model.id as CodexModelId);
|
||||||
@@ -726,7 +708,7 @@ export function PhaseModelSelector({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Render OpenCode model item (simple selector, no thinking/reasoning options)
|
// Render OpenCode model item (simple selector, no thinking/reasoning options)
|
||||||
const renderOpencodeModelItem = (model: ModelOption) => {
|
const renderOpencodeModelItem = (model: (typeof OPENCODE_MODELS)[0]) => {
|
||||||
const isSelected = selectedModel === model.id;
|
const isSelected = selectedModel === model.id;
|
||||||
const isFavorite = favoriteModels.includes(model.id);
|
const isFavorite = favoriteModels.includes(model.id);
|
||||||
|
|
||||||
@@ -1172,7 +1154,7 @@ export function PhaseModelSelector({
|
|||||||
}
|
}
|
||||||
// Codex model
|
// Codex model
|
||||||
if (model.provider === 'codex') {
|
if (model.provider === 'codex') {
|
||||||
return renderCodexModelItem(model as (typeof availableCodexModels)[0]);
|
return renderCodexModelItem(model as (typeof transformedCodexModels)[0]);
|
||||||
}
|
}
|
||||||
// OpenCode model
|
// OpenCode model
|
||||||
if (model.provider === 'opencode') {
|
if (model.provider === 'opencode') {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export function CreateSpecDialog({
|
|||||||
<DialogDescription className="text-muted-foreground">{description}</DialogDescription>
|
<DialogDescription className="text-muted-foreground">{description}</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="space-y-4 py-4">
|
<div className="space-y-4 py-4 overflow-y-auto">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-sm font-medium">Project Overview</label>
|
<label className="text-sm font-medium">Project Overview</label>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export function RegenerateSpecDialog({
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="space-y-4 py-4">
|
<div className="space-y-4 py-4 overflow-y-auto">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-sm font-medium">Describe your project</label>
|
<label className="text-sm font-medium">Describe your project</label>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
|
|||||||
@@ -136,12 +136,11 @@ volumes:
|
|||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
| Problem | Solution |
|
| Problem | Solution |
|
||||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| Container won't start | Check `.env` has `ANTHROPIC_API_KEY` set. Run `docker-compose logs` for errors. |
|
| Container won't start | Check `.env` has `ANTHROPIC_API_KEY` set. Run `docker-compose logs` for errors. |
|
||||||
| Can't access web UI | Verify container is running with `docker ps \| grep automaker` |
|
| Can't access web UI | Verify container is running with `docker ps \| grep automaker` |
|
||||||
| Need a fresh start | Run `docker-compose down && docker volume rm automaker-data && docker-compose up -d --build` |
|
| Need a fresh start | Run `docker-compose down && docker volume rm automaker-data && docker-compose up -d --build` |
|
||||||
| Cursor auth fails | Re-extract token with `./scripts/get-cursor-token.sh` - tokens expire periodically. Make sure you've run `cursor-agent login` on your host first. |
|
| Cursor auth fails | Re-extract token with `./scripts/get-cursor-token.sh` - tokens expire periodically. Make sure you've run `cursor-agent login` on your host first. |
|
||||||
| OpenCode not detected | Mount `~/.local/share/opencode` to `/home/automaker/.local/share/opencode`. Make sure you've run `opencode auth login` on your host first. |
|
| OpenCode not detected | Mount `~/.local/share/opencode` to `/home/automaker/.local/share/opencode`. Make sure you've run `opencode auth login` on your host first. |
|
||||||
| File permission errors | Rebuild with `UID=$(id -u) GID=$(id -g) docker-compose build` to match container user to your host user. See [Fixing File Permission Issues](#fixing-file-permission-issues). |
|
| File permission errors | Rebuild with `UID=$(id -u) GID=$(id -g) docker-compose build` to match container user to your host user. See [Fixing File Permission Issues](#fixing-file-permission-issues). |
|
||||||
|
|
||||||
|
|||||||
91
package-lock.json
generated
91
package-lock.json
generated
@@ -679,6 +679,7 @@
|
|||||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/generator": "^7.28.5",
|
"@babel/generator": "^7.28.5",
|
||||||
@@ -1271,6 +1272,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.4.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.4.tgz",
|
||||||
"integrity": "sha512-xMF6OfEAUVY5Waega4juo1QGACfNkNF+aJLqpd8oUJz96ms2zbfQ9Gh35/tI3y8akEV31FruKfj7hBnIU/nkqA==",
|
"integrity": "sha512-xMF6OfEAUVY5Waega4juo1QGACfNkNF+aJLqpd8oUJz96ms2zbfQ9Gh35/tI3y8akEV31FruKfj7hBnIU/nkqA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.5.0",
|
"@codemirror/state": "^6.5.0",
|
||||||
"crelt": "^1.0.6",
|
"crelt": "^1.0.6",
|
||||||
@@ -1313,6 +1315,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
|
||||||
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
|
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/accessibility": "^3.1.1",
|
"@dnd-kit/accessibility": "^3.1.1",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
@@ -2133,7 +2136,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-dirname": "^0.1.0",
|
"cross-dirname": "^0.1.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
@@ -2155,7 +2157,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
"jsonfile": "^6.0.1",
|
"jsonfile": "^6.0.1",
|
||||||
@@ -2172,7 +2173,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -2187,7 +2187,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
@@ -2955,7 +2954,6 @@
|
|||||||
"integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
|
"integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
@@ -3080,7 +3078,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -3097,7 +3094,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -3114,7 +3110,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -3223,7 +3218,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -3246,7 +3240,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -3269,7 +3262,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -3355,7 +3347,6 @@
|
|||||||
],
|
],
|
||||||
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emnapi/runtime": "^1.7.0"
|
"@emnapi/runtime": "^1.7.0"
|
||||||
},
|
},
|
||||||
@@ -3378,7 +3369,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -3398,7 +3388,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -3798,8 +3787,7 @@
|
|||||||
"version": "16.0.10",
|
"version": "16.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.10.tgz",
|
||||||
"integrity": "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==",
|
"integrity": "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-darwin-arm64": {
|
"node_modules/@next/swc-darwin-arm64": {
|
||||||
"version": "16.0.10",
|
"version": "16.0.10",
|
||||||
@@ -3813,7 +3801,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
@@ -3830,7 +3817,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
@@ -3847,7 +3833,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
@@ -3864,7 +3849,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
@@ -3881,7 +3865,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
@@ -3898,7 +3881,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
@@ -3915,7 +3897,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
@@ -3932,7 +3913,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
@@ -4032,6 +4012,7 @@
|
|||||||
"integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==",
|
"integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.57.0"
|
"playwright": "1.57.0"
|
||||||
},
|
},
|
||||||
@@ -5472,7 +5453,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
||||||
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
|
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.8.0"
|
"tslib": "^2.8.0"
|
||||||
}
|
}
|
||||||
@@ -5806,6 +5786,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.141.6.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.141.6.tgz",
|
||||||
"integrity": "sha512-qWFxi2D6eGc1L03RzUuhyEOplZ7Q6q62YOl7Of9Y0q4YjwQwxRm4zxwDVtvUIoy4RLVCpqp5UoE+Nxv2PY9trg==",
|
"integrity": "sha512-qWFxi2D6eGc1L03RzUuhyEOplZ7Q6q62YOl7Of9Y0q4YjwQwxRm4zxwDVtvUIoy4RLVCpqp5UoE+Nxv2PY9trg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/history": "1.141.0",
|
"@tanstack/history": "1.141.0",
|
||||||
"@tanstack/react-store": "^0.8.0",
|
"@tanstack/react-store": "^0.8.0",
|
||||||
@@ -6232,6 +6213,7 @@
|
|||||||
"integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
|
"integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/body-parser": "*",
|
"@types/body-parser": "*",
|
||||||
"@types/express-serve-static-core": "^5.0.0",
|
"@types/express-serve-static-core": "^5.0.0",
|
||||||
@@ -6374,6 +6356,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
|
||||||
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
|
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.2.2"
|
"csstype": "^3.2.2"
|
||||||
}
|
}
|
||||||
@@ -6384,6 +6367,7 @@
|
|||||||
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.2.0"
|
"@types/react": "^19.2.0"
|
||||||
}
|
}
|
||||||
@@ -6489,6 +6473,7 @@
|
|||||||
"integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==",
|
"integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.50.0",
|
"@typescript-eslint/scope-manager": "8.50.0",
|
||||||
"@typescript-eslint/types": "8.50.0",
|
"@typescript-eslint/types": "8.50.0",
|
||||||
@@ -6982,7 +6967,8 @@
|
|||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
||||||
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==",
|
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/@xyflow/react": {
|
"node_modules/@xyflow/react": {
|
||||||
"version": "12.10.0",
|
"version": "12.10.0",
|
||||||
@@ -7080,6 +7066,7 @@
|
|||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -7140,6 +7127,7 @@
|
|||||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
@@ -7738,6 +7726,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.9.0",
|
"baseline-browser-mapping": "^2.9.0",
|
||||||
"caniuse-lite": "^1.0.30001759",
|
"caniuse-lite": "^1.0.30001759",
|
||||||
@@ -8269,8 +8258,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/cliui": {
|
"node_modules/cliui": {
|
||||||
"version": "8.0.1",
|
"version": "8.0.1",
|
||||||
@@ -8575,8 +8563,7 @@
|
|||||||
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
|
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/cross-env": {
|
"node_modules/cross-env": {
|
||||||
"version": "10.1.0",
|
"version": "10.1.0",
|
||||||
@@ -8673,6 +8660,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
@@ -8974,6 +8962,7 @@
|
|||||||
"integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==",
|
"integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"app-builder-lib": "26.0.12",
|
"app-builder-lib": "26.0.12",
|
||||||
"builder-util": "26.0.11",
|
"builder-util": "26.0.11",
|
||||||
@@ -9300,7 +9289,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/asar": "^3.2.1",
|
"@electron/asar": "^3.2.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@@ -9321,7 +9309,6 @@
|
|||||||
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
|
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.1.2",
|
"graceful-fs": "^4.1.2",
|
||||||
"jsonfile": "^4.0.0",
|
"jsonfile": "^4.0.0",
|
||||||
@@ -9572,6 +9559,7 @@
|
|||||||
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
@@ -9886,6 +9874,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
||||||
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "^2.0.0",
|
"accepts": "^2.0.0",
|
||||||
"body-parser": "^2.2.1",
|
"body-parser": "^2.2.1",
|
||||||
@@ -11553,7 +11542,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -11619,7 +11607,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"freebsd"
|
"freebsd"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -14061,7 +14048,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.6",
|
"nanoid": "^3.3.6",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
@@ -14078,7 +14064,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "^9.4.0"
|
"commander": "^9.4.0"
|
||||||
},
|
},
|
||||||
@@ -14096,7 +14081,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.20.0 || >=14"
|
"node": "^12.20.0 || >=14"
|
||||||
}
|
}
|
||||||
@@ -14285,6 +14269,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
|
||||||
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
|
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -14294,6 +14279,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
|
||||||
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
|
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.27.0"
|
"scheduler": "^0.27.0"
|
||||||
},
|
},
|
||||||
@@ -14652,7 +14638,6 @@
|
|||||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.1.3"
|
"glob": "^7.1.3"
|
||||||
},
|
},
|
||||||
@@ -14841,6 +14826,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/seroval/-/seroval-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/seroval/-/seroval-1.4.0.tgz",
|
||||||
"integrity": "sha512-BdrNXdzlofomLTiRnwJTSEAaGKyHHZkbMXIywOh7zlzp4uZnXErEwl9XZ+N1hJSNpeTtNxWvVwN0wUzAIQ4Hpg==",
|
"integrity": "sha512-BdrNXdzlofomLTiRnwJTSEAaGKyHHZkbMXIywOh7zlzp4uZnXErEwl9XZ+N1hJSNpeTtNxWvVwN0wUzAIQ4Hpg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
@@ -14889,7 +14875,6 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@img/colour": "^1.0.0",
|
"@img/colour": "^1.0.0",
|
||||||
"detect-libc": "^2.1.2",
|
"detect-libc": "^2.1.2",
|
||||||
@@ -14940,7 +14925,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -14963,7 +14947,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -14986,7 +14969,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -15003,7 +14985,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -15020,7 +15001,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -15037,7 +15017,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -15054,7 +15033,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -15071,7 +15049,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -15088,7 +15065,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
}
|
}
|
||||||
@@ -15105,7 +15081,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -15128,7 +15103,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -15151,7 +15125,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -15174,7 +15147,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -15197,7 +15169,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -15220,7 +15191,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
@@ -15689,7 +15659,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
|
||||||
"integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
|
"integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"client-only": "0.0.1"
|
"client-only": "0.0.1"
|
||||||
},
|
},
|
||||||
@@ -15859,7 +15828,6 @@
|
|||||||
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"rimraf": "~2.6.2"
|
"rimraf": "~2.6.2"
|
||||||
@@ -15923,7 +15891,6 @@
|
|||||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": "^1.2.6"
|
"minimist": "^1.2.6"
|
||||||
},
|
},
|
||||||
@@ -16021,6 +15988,7 @@
|
|||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -16225,6 +16193,7 @@
|
|||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -16596,6 +16565,7 @@
|
|||||||
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
|
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.27.0",
|
"esbuild": "^0.27.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
@@ -16685,7 +16655,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/vite-plugin-electron-renderer/-/vite-plugin-electron-renderer-0.14.6.tgz",
|
"resolved": "https://registry.npmjs.org/vite-plugin-electron-renderer/-/vite-plugin-electron-renderer-0.14.6.tgz",
|
||||||
"integrity": "sha512-oqkWFa7kQIkvHXG7+Mnl1RTroA4sP0yesKatmAy0gjZC4VwUqlvF9IvOpHd1fpLWsqYX/eZlVxlhULNtaQ78Jw==",
|
"integrity": "sha512-oqkWFa7kQIkvHXG7+Mnl1RTroA4sP0yesKatmAy0gjZC4VwUqlvF9IvOpHd1fpLWsqYX/eZlVxlhULNtaQ78Jw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/fdir": {
|
"node_modules/vite/node_modules/fdir": {
|
||||||
"version": "6.5.0",
|
"version": "6.5.0",
|
||||||
@@ -16711,6 +16682,7 @@
|
|||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -16753,6 +16725,7 @@
|
|||||||
"integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==",
|
"integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/expect": "4.0.16",
|
"@vitest/expect": "4.0.16",
|
||||||
"@vitest/mocker": "4.0.16",
|
"@vitest/mocker": "4.0.16",
|
||||||
@@ -17010,6 +16983,7 @@
|
|||||||
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
|
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"yaml": "bin.mjs"
|
"yaml": "bin.mjs"
|
||||||
},
|
},
|
||||||
@@ -17078,6 +17052,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
|
||||||
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
|
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user