mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-16 21:53:07 +00:00
Fix Codex CLI timeout handling and improve CI workflows (#797)
* Changes from fix/codex-cli-timeout * test: Clarify timeout values and multipliers in codex-provider tests * refactor: Rename useWorktreesEnabled to worktreesEnabled for clarity
This commit is contained in:
@@ -33,7 +33,6 @@ import {
|
||||
supportsReasoningEffort,
|
||||
validateBareModelId,
|
||||
calculateReasoningTimeout,
|
||||
DEFAULT_TIMEOUT_MS,
|
||||
type CodexApprovalPolicy,
|
||||
type CodexSandboxMode,
|
||||
type CodexAuthStatus,
|
||||
@@ -98,7 +97,7 @@ const TEXT_ENCODING = 'utf-8';
|
||||
*
|
||||
* @see calculateReasoningTimeout from @automaker/types
|
||||
*/
|
||||
const CODEX_CLI_TIMEOUT_MS = DEFAULT_TIMEOUT_MS;
|
||||
const CODEX_CLI_TIMEOUT_MS = 120000; // 2 minutes — matches CLI provider base timeout
|
||||
const CODEX_FEATURE_GENERATION_BASE_TIMEOUT_MS = 300000; // 5 minutes for feature generation
|
||||
const SYSTEM_PROMPT_SEPARATOR = '\n\n';
|
||||
const CODEX_INSTRUCTIONS_DIR = '.codex';
|
||||
|
||||
@@ -320,8 +320,10 @@ describe('codex-provider.ts', () => {
|
||||
);
|
||||
|
||||
const call = vi.mocked(spawnJSONLProcess).mock.calls[0][0];
|
||||
// High reasoning effort should have 3x the default timeout (90000ms)
|
||||
expect(call.timeout).toBe(DEFAULT_TIMEOUT_MS * REASONING_TIMEOUT_MULTIPLIERS.high);
|
||||
// High reasoning effort should have 3x the CLI base timeout (120000ms)
|
||||
// CODEX_CLI_TIMEOUT_MS = 120000, multiplier for 'high' = 3.0 → 360000ms
|
||||
const CODEX_CLI_TIMEOUT_MS = 120000;
|
||||
expect(call.timeout).toBe(CODEX_CLI_TIMEOUT_MS * REASONING_TIMEOUT_MULTIPLIERS.high);
|
||||
});
|
||||
|
||||
it('passes extended timeout for xhigh reasoning effort', async () => {
|
||||
@@ -357,8 +359,10 @@ describe('codex-provider.ts', () => {
|
||||
);
|
||||
|
||||
const call = vi.mocked(spawnJSONLProcess).mock.calls[0][0];
|
||||
// No reasoning effort should use the default timeout
|
||||
expect(call.timeout).toBe(DEFAULT_TIMEOUT_MS);
|
||||
// No reasoning effort should use the CLI base timeout (2 minutes)
|
||||
// CODEX_CLI_TIMEOUT_MS = 120000ms, no multiplier applied
|
||||
const CODEX_CLI_TIMEOUT_MS = 120000;
|
||||
expect(call.timeout).toBe(CODEX_CLI_TIMEOUT_MS);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -84,17 +84,19 @@ export function useBoardActions({
|
||||
onWorktreeAutoSelect,
|
||||
currentWorktreeBranch,
|
||||
}: UseBoardActionsProps) {
|
||||
const {
|
||||
addFeature,
|
||||
updateFeature,
|
||||
removeFeature,
|
||||
moveFeature,
|
||||
useWorktrees,
|
||||
enableDependencyBlocking,
|
||||
skipVerificationInAutoMode,
|
||||
isPrimaryWorktreeBranch,
|
||||
getPrimaryWorktreeBranch,
|
||||
} = useAppStore();
|
||||
// IMPORTANT: Use individual selectors instead of bare useAppStore() to prevent
|
||||
// subscribing to the entire store. Bare useAppStore() causes the host component
|
||||
// (BoardView) to re-render on EVERY store change, which cascades through effects
|
||||
// and triggers React error #185 (maximum update depth exceeded).
|
||||
const addFeature = useAppStore((s) => s.addFeature);
|
||||
const updateFeature = useAppStore((s) => s.updateFeature);
|
||||
const removeFeature = useAppStore((s) => s.removeFeature);
|
||||
const moveFeature = useAppStore((s) => s.moveFeature);
|
||||
const worktreesEnabled = useAppStore((s) => s.useWorktrees);
|
||||
const enableDependencyBlocking = useAppStore((s) => s.enableDependencyBlocking);
|
||||
const skipVerificationInAutoMode = useAppStore((s) => s.skipVerificationInAutoMode);
|
||||
const isPrimaryWorktreeBranch = useAppStore((s) => s.isPrimaryWorktreeBranch);
|
||||
const getPrimaryWorktreeBranch = useAppStore((s) => s.getPrimaryWorktreeBranch);
|
||||
const autoMode = useAutoMode();
|
||||
|
||||
// React Query mutations for feature operations
|
||||
@@ -549,7 +551,7 @@ export function useBoardActions({
|
||||
const result = await api.autoMode.runFeature(
|
||||
currentProject.path,
|
||||
feature.id,
|
||||
useWorktrees
|
||||
worktreesEnabled
|
||||
// No worktreePath - server derives from feature.branchName
|
||||
);
|
||||
|
||||
@@ -560,7 +562,7 @@ export function useBoardActions({
|
||||
throw new Error(result.error || 'Failed to start feature');
|
||||
}
|
||||
},
|
||||
[currentProject, useWorktrees]
|
||||
[currentProject, worktreesEnabled]
|
||||
);
|
||||
|
||||
const handleStartImplementation = useCallback(
|
||||
@@ -693,9 +695,9 @@ export function useBoardActions({
|
||||
logger.error('No current project');
|
||||
return;
|
||||
}
|
||||
resumeFeatureMutation.mutate({ featureId: feature.id, useWorktrees });
|
||||
resumeFeatureMutation.mutate({ featureId: feature.id, useWorktrees: worktreesEnabled });
|
||||
},
|
||||
[currentProject, resumeFeatureMutation, useWorktrees]
|
||||
[currentProject, resumeFeatureMutation, worktreesEnabled]
|
||||
);
|
||||
|
||||
const handleManualVerify = useCallback(
|
||||
@@ -780,7 +782,7 @@ export function useBoardActions({
|
||||
followUpFeature.id,
|
||||
followUpPrompt,
|
||||
imagePaths,
|
||||
useWorktrees
|
||||
worktreesEnabled
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
@@ -818,7 +820,7 @@ export function useBoardActions({
|
||||
setFollowUpPrompt,
|
||||
setFollowUpImagePaths,
|
||||
setFollowUpPreviewMap,
|
||||
useWorktrees,
|
||||
worktreesEnabled,
|
||||
]);
|
||||
|
||||
const handleCommitFeature = useCallback(
|
||||
|
||||
@@ -33,7 +33,12 @@ export function useBoardDragDrop({
|
||||
const [pendingDependencyLink, setPendingDependencyLink] = useState<PendingDependencyLink | null>(
|
||||
null
|
||||
);
|
||||
const { moveFeature, updateFeature } = useAppStore();
|
||||
// IMPORTANT: Use individual selectors instead of bare useAppStore() to prevent
|
||||
// subscribing to the entire store. Bare useAppStore() causes the host component
|
||||
// (BoardView) to re-render on EVERY store change, which cascades through effects
|
||||
// and triggers React error #185 (maximum update depth exceeded).
|
||||
const moveFeature = useAppStore((s) => s.moveFeature);
|
||||
const updateFeature = useAppStore((s) => s.updateFeature);
|
||||
const autoMode = useAutoMode();
|
||||
|
||||
// Note: getOrCreateWorktreeForFeature removed - worktrees are now created server-side
|
||||
|
||||
@@ -14,7 +14,11 @@ interface UseBoardPersistenceProps {
|
||||
}
|
||||
|
||||
export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps) {
|
||||
const { updateFeature } = useAppStore();
|
||||
// IMPORTANT: Use individual selector instead of bare useAppStore() to prevent
|
||||
// subscribing to the entire store. Bare useAppStore() causes the host component
|
||||
// (BoardView) to re-render on EVERY store change, which cascades through effects
|
||||
// and triggers React error #185 (maximum update depth exceeded).
|
||||
const updateFeature = useAppStore((s) => s.updateFeature);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// Persist feature update to API (replaces saveFeatures)
|
||||
|
||||
Reference in New Issue
Block a user