mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-01 20:23:36 +00:00
Merge branch 'v0.14.0rc' into feature/bug-complete-fix-for-the-plan-mode-system-inside-sbyt
Resolved conflict in apps/ui/src/hooks/use-query-invalidation.ts by: - Keeping the refactored structure from v0.14.0rc (using constants and hasFeatureId() type guard) - Adding the additional event types from the feature branch (auto_mode_task_status, auto_mode_summary) to SINGLE_FEATURE_INVALIDATION_EVENTS constant 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,59 @@ import { useEventRecencyStore } from './use-event-recency';
|
||||
const PROGRESS_DEBOUNCE_WAIT = 150;
|
||||
const PROGRESS_DEBOUNCE_MAX_WAIT = 2000;
|
||||
|
||||
/**
|
||||
* Events that should invalidate the feature list (features.all query)
|
||||
* Note: pipeline_step_started is included to ensure Kanban board immediately reflects
|
||||
* feature moving to custom pipeline columns (fixes GitHub issue #668)
|
||||
*/
|
||||
const FEATURE_LIST_INVALIDATION_EVENTS: AutoModeEvent['type'][] = [
|
||||
'auto_mode_feature_complete',
|
||||
'auto_mode_error',
|
||||
'plan_approval_required',
|
||||
'plan_approved',
|
||||
'plan_rejected',
|
||||
'pipeline_step_started',
|
||||
'pipeline_step_complete',
|
||||
];
|
||||
|
||||
/**
|
||||
* Events that should invalidate a specific feature (features.single query)
|
||||
* Note: pipeline_step_started is NOT included here because it already invalidates
|
||||
* features.all() above, which also invalidates child queries (features.single)
|
||||
*/
|
||||
const SINGLE_FEATURE_INVALIDATION_EVENTS: AutoModeEvent['type'][] = [
|
||||
'auto_mode_feature_start',
|
||||
'auto_mode_phase',
|
||||
'auto_mode_phase_complete',
|
||||
'auto_mode_task_status',
|
||||
'auto_mode_summary',
|
||||
];
|
||||
|
||||
/**
|
||||
* Events that should invalidate running agents status
|
||||
*/
|
||||
const RUNNING_AGENTS_INVALIDATION_EVENTS: AutoModeEvent['type'][] = [
|
||||
'auto_mode_feature_start',
|
||||
'auto_mode_feature_complete',
|
||||
'auto_mode_error',
|
||||
'auto_mode_resuming_features',
|
||||
];
|
||||
|
||||
/**
|
||||
* Events that signal a feature is done and debounce cleanup should occur
|
||||
*/
|
||||
const FEATURE_CLEANUP_EVENTS: AutoModeEvent['type'][] = [
|
||||
'auto_mode_feature_complete',
|
||||
'auto_mode_error',
|
||||
];
|
||||
|
||||
/**
|
||||
* Type guard to check if an event has a featureId property
|
||||
*/
|
||||
function hasFeatureId(event: AutoModeEvent): event is AutoModeEvent & { featureId: string } {
|
||||
return 'featureId' in event && typeof event.featureId === 'string';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unique key for per-feature debounce tracking
|
||||
*/
|
||||
@@ -115,42 +168,22 @@ export function useAutoModeQueryInvalidation(projectPath: string | undefined) {
|
||||
// This allows polling to be disabled when WebSocket events are flowing
|
||||
recordGlobalEvent();
|
||||
|
||||
// Invalidate features when agent completes, errors, or receives plan approval
|
||||
if (
|
||||
event.type === 'auto_mode_feature_complete' ||
|
||||
event.type === 'auto_mode_error' ||
|
||||
event.type === 'plan_approval_required' ||
|
||||
event.type === 'plan_approved' ||
|
||||
event.type === 'plan_rejected' ||
|
||||
event.type === 'pipeline_step_complete'
|
||||
) {
|
||||
// Invalidate feature list for lifecycle events
|
||||
if (FEATURE_LIST_INVALIDATION_EVENTS.includes(event.type)) {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.features.all(currentProjectPath),
|
||||
});
|
||||
}
|
||||
|
||||
// Invalidate running agents on any status change
|
||||
if (
|
||||
event.type === 'auto_mode_feature_start' ||
|
||||
event.type === 'auto_mode_feature_complete' ||
|
||||
event.type === 'auto_mode_error' ||
|
||||
event.type === 'auto_mode_resuming_features'
|
||||
) {
|
||||
// Invalidate running agents on status changes
|
||||
if (RUNNING_AGENTS_INVALIDATION_EVENTS.includes(event.type)) {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.runningAgents.all(),
|
||||
});
|
||||
}
|
||||
|
||||
// Invalidate specific feature when it starts, has phase changes, or task status updates
|
||||
if (
|
||||
(event.type === 'auto_mode_feature_start' ||
|
||||
event.type === 'auto_mode_phase' ||
|
||||
event.type === 'auto_mode_phase_complete' ||
|
||||
event.type === 'auto_mode_task_status' ||
|
||||
event.type === 'auto_mode_summary' ||
|
||||
event.type === 'pipeline_step_started') &&
|
||||
'featureId' in event
|
||||
) {
|
||||
// Invalidate specific feature for phase changes and task status updates
|
||||
if (SINGLE_FEATURE_INVALIDATION_EVENTS.includes(event.type) && hasFeatureId(event)) {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.features.single(currentProjectPath, event.featureId),
|
||||
});
|
||||
@@ -158,23 +191,19 @@ export function useAutoModeQueryInvalidation(projectPath: string | undefined) {
|
||||
|
||||
// Invalidate agent output during progress updates (DEBOUNCED)
|
||||
// Uses per-feature debouncing to batch rapid progress events during streaming
|
||||
if (event.type === 'auto_mode_progress' && 'featureId' in event) {
|
||||
if (event.type === 'auto_mode_progress' && hasFeatureId(event)) {
|
||||
const debouncedInvalidation = getDebouncedInvalidation(event.featureId);
|
||||
debouncedInvalidation();
|
||||
}
|
||||
|
||||
// Clean up debounced functions when feature completes or errors
|
||||
// This ensures we flush any pending invalidations and free memory
|
||||
if (
|
||||
(event.type === 'auto_mode_feature_complete' || event.type === 'auto_mode_error') &&
|
||||
'featureId' in event &&
|
||||
event.featureId
|
||||
) {
|
||||
if (FEATURE_CLEANUP_EVENTS.includes(event.type) && hasFeatureId(event)) {
|
||||
cleanupFeatureDebounce(event.featureId);
|
||||
}
|
||||
|
||||
// Invalidate worktree queries when feature completes (may have created worktree)
|
||||
if (event.type === 'auto_mode_feature_complete' && 'featureId' in event) {
|
||||
if (event.type === 'auto_mode_feature_complete' && hasFeatureId(event)) {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.worktrees.all(currentProjectPath),
|
||||
});
|
||||
|
||||
@@ -181,6 +181,7 @@ export function parseLocalStorageSettings(): Partial<GlobalSettings> | null {
|
||||
defaultPlanningMode: state.defaultPlanningMode as GlobalSettings['defaultPlanningMode'],
|
||||
defaultRequirePlanApproval: state.defaultRequirePlanApproval as boolean,
|
||||
muteDoneSound: state.muteDoneSound as boolean,
|
||||
disableSplashScreen: state.disableSplashScreen as boolean,
|
||||
enhancementModel: state.enhancementModel as GlobalSettings['enhancementModel'],
|
||||
validationModel: state.validationModel as GlobalSettings['validationModel'],
|
||||
phaseModels: state.phaseModels as GlobalSettings['phaseModels'],
|
||||
@@ -713,6 +714,7 @@ export function hydrateStoreFromSettings(settings: GlobalSettings): void {
|
||||
model: 'claude-opus',
|
||||
},
|
||||
muteDoneSound: settings.muteDoneSound ?? false,
|
||||
disableSplashScreen: settings.disableSplashScreen ?? false,
|
||||
serverLogLevel: settings.serverLogLevel ?? 'info',
|
||||
enableRequestLogging: settings.enableRequestLogging ?? true,
|
||||
showQueryDevtools: settings.showQueryDevtools ?? true,
|
||||
@@ -800,6 +802,7 @@ function buildSettingsUpdateFromStore(): Record<string, unknown> {
|
||||
defaultPlanningMode: state.defaultPlanningMode,
|
||||
defaultRequirePlanApproval: state.defaultRequirePlanApproval,
|
||||
muteDoneSound: state.muteDoneSound,
|
||||
disableSplashScreen: state.disableSplashScreen,
|
||||
serverLogLevel: state.serverLogLevel,
|
||||
enableRequestLogging: state.enableRequestLogging,
|
||||
enhancementModel: state.enhancementModel,
|
||||
|
||||
@@ -66,6 +66,7 @@ const SETTINGS_FIELDS_TO_SYNC = [
|
||||
'defaultRequirePlanApproval',
|
||||
'defaultFeatureModel',
|
||||
'muteDoneSound',
|
||||
'disableSplashScreen',
|
||||
'serverLogLevel',
|
||||
'enableRequestLogging',
|
||||
'showQueryDevtools',
|
||||
@@ -714,6 +715,7 @@ export async function refreshSettingsFromServer(): Promise<boolean> {
|
||||
? migratePhaseModelEntry(serverSettings.defaultFeatureModel)
|
||||
: { model: 'claude-opus' },
|
||||
muteDoneSound: serverSettings.muteDoneSound,
|
||||
disableSplashScreen: serverSettings.disableSplashScreen ?? false,
|
||||
serverLogLevel: serverSettings.serverLogLevel ?? 'info',
|
||||
enableRequestLogging: serverSettings.enableRequestLogging ?? true,
|
||||
enhancementModel: serverSettings.enhancementModel,
|
||||
|
||||
Reference in New Issue
Block a user