Log background agent failure reasons

This commit is contained in:
Ramnique Singh 2026-07-22 10:48:36 +05:30
parent 358e819a15
commit e659f0bdde
2 changed files with 29 additions and 3 deletions

View file

@ -181,7 +181,8 @@ All renderer events live in `apps/renderer/src/lib/analytics.ts` (typed wrappers
- `email_send_failed` — send returned an error or threw (`components/email-view.tsx`)
- `meeting_summarize_failed` — post-recording notes generation threw (`App.tsx`)
- `bg_agent_run_failed` / `bg_agent_run_completed``{ trigger: 'manual' | 'cron' | 'window' | 'event' }` **(core)** — every background-agent run settles as exactly one of these (`packages/core/src/background-tasks/runner.ts`), giving a failure *rate* across all trigger sources, not just manual clicks
- `bg_agent_run_failed``{ trigger: 'manual' | 'cron' | 'window' | 'event', error: string }` **(core)** — emitted when a background-agent run fails; `error` contains the normalized failure message
- `bg_agent_run_completed``{ trigger: 'manual' | 'cron' | 'window' | 'event' }` **(core)** — emitted when a background-agent run succeeds; together these events give a failure *rate* across all trigger sources, not just manual clicks
**Misc**:

View file

@ -93,6 +93,10 @@ Your task folder is \`${wsFolder}\`. The user-visible artifact is \`${wsFolder}i
const runningTasks = new Set<string>();
type RunAnalyticsOutcome =
| { event: 'bg_agent_run_completed'; properties: { trigger: BackgroundTaskTriggerType } }
| { event: 'bg_agent_run_failed'; properties: { trigger: BackgroundTaskTriggerType; error: string } };
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
@ -114,6 +118,8 @@ export async function runBackgroundTask(
}
runningTasks.add(slug);
let analyticsOutcome: RunAnalyticsOutcome | undefined;
try {
const task = await fetchTask(slug);
if (!task) {
@ -211,7 +217,6 @@ export async function runBackgroundTask(
});
log.log(`${slug} — done summary="${truncate(summary)}"`);
capture('bg_agent_run_completed', { trigger });
backgroundTaskBus.publish({
type: 'background_task_agent_complete',
@ -220,10 +225,16 @@ export async function runBackgroundTask(
...(summary ? { summary } : {}),
});
analyticsOutcome = { event: 'bg_agent_run_completed', properties: { trigger } };
return { slug, runId, summary };
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
analyticsOutcome = {
event: 'bg_agent_run_failed',
properties: { trigger, error: msg },
};
// Failure — only record the error. `lastRunAt` and `lastRunSummary`
// are deliberately untouched so the user keeps seeing the last good
// state; the scheduler's backoff (lastAttemptAt + 5min) prevents
@ -235,7 +246,6 @@ export async function runBackgroundTask(
}
log.log(`${slug} — failed: ${truncate(msg)}`);
capture('bg_agent_run_failed', { trigger });
backgroundTaskBus.publish({
type: 'background_task_agent_complete',
@ -246,7 +256,22 @@ export async function runBackgroundTask(
return { slug, runId, summary: null, error: msg };
}
} catch (err) {
// Preserve the original throw behavior for setup/infrastructure errors,
// but still settle analytics for the attempted run. If the agent had
// already failed, keep that original failure reason.
analyticsOutcome ??= {
event: 'bg_agent_run_failed',
properties: {
trigger,
error: err instanceof Error ? err.message : String(err),
},
};
throw err;
} finally {
if (analyticsOutcome) {
capture(analyticsOutcome.event, analyticsOutcome.properties);
}
runningTasks.delete(slug);
}
}