Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ import { drainQueue, type RunTask } from './executor';
import { RunMetrics } from './run-metrics';
import { dependencyClosure, uncoveredBySink } from './queue-tools';
import { deferSeededTasks } from './seeded-deps';
import { createWizardAskBridge } from '@lib/wizard-ask-bridge';
import {
createWizardAskBridge,
CREDENTIAL_ASK_TIMEOUT_MS,
} from '@lib/wizard-ask-bridge';
import { shouldDisableAsk } from '../../shared/bootstrap';
import {
agentRunTools,
Expand Down Expand Up @@ -196,7 +199,7 @@ function resolveReferenceSkillId(
* open a database console or mint a restricted API key. The drain waits it out
* — the executor holds the task's promise — so the only real limit is this one.
*/
const TASK_ASK_TIMEOUT_MS = 20 * 60 * 1000;
const TASK_ASK_TIMEOUT_MS = CREDENTIAL_ASK_TIMEOUT_MS;

/**
* How long an optional step's notice waits for an answer.
Expand Down
39 changes: 39 additions & 0 deletions src/lib/programs/__tests__/warehouse-ask-timeout.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* How long the standalone `wizard warehouse` command waits for a credential.
*
* The same source credentials are collected two ways: as the orchestrator's
* seeded warehouse task, and as this command — the one the outro points at
* when the user declines the offer or a source falls back to browser setup.
* The command was on the 5-minute default, so the fallback route gave the
* user a quarter of the time the in-run prompt does for identical questions.
*/
import type { WizardSession } from '@lib/wizard-session';

vi.mock('@utils/analytics', () => ({
analytics: {
wizardCapture: vi.fn(),
setTag: vi.fn(),
capture: vi.fn(),
captureException: vi.fn(),
},
}));

import { warehouseSourceConfig } from '@lib/programs/warehouse-source/index';
import {
CREDENTIAL_ASK_TIMEOUT_MS,
DEFAULT_ASK_TIMEOUT_MS,
} from '@lib/wizard-ask-bridge';

function session(): WizardSession {
return { installDir: '/tmp/app', frameworkContext: {} } as WizardSession;
}

describe('warehouse command ask timeout', () => {
it('gives credential questions the shared allowance, not the default', async () => {
const { run } = warehouseSourceConfig;
const resolved = typeof run === 'function' ? await run(session()) : run;

expect(resolved?.askTimeoutMs).toBe(CREDENTIAL_ASK_TIMEOUT_MS);
expect(resolved?.askTimeoutMs).toBeGreaterThan(DEFAULT_ASK_TIMEOUT_MS);
});
});
6 changes: 6 additions & 0 deletions src/lib/programs/warehouse-source/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ProgramConfig } from '@lib/programs/program-step';
import type { ProgramRun } from '@lib/agent/agent-runner';
import type { WizardSession } from '@lib/wizard-session';
import { CREDENTIAL_ASK_TIMEOUT_MS } from '@lib/wizard-ask-bridge';
import { WAREHOUSE_SOURCE_PROGRAM } from './steps.js';
import {
WAREHOUSE_ABORT_CASES,
Expand Down Expand Up @@ -60,6 +61,11 @@ export const warehouseSourceConfig: ProgramConfig = {
docsUrl: 'https://posthog.com/docs/data-warehouse',
spinnerMessage: 'Connecting your data source...',
estimatedDurationMinutes: 5,
// Same questions the orchestrator's seeded warehouse task asks, so the
// same allowance. On the 5-minute default a user who went to fetch a
// database password came back to a cancelled prompt and the browser
// fallback — in the command the outro sends declines to.
askTimeoutMs: CREDENTIAL_ASK_TIMEOUT_MS,
abortCases: WAREHOUSE_ABORT_CASES,
}),
requires: ['posthog-integration'],
Expand Down
16 changes: 16 additions & 0 deletions src/lib/wizard-ask-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,22 @@ export const CANCELLED_SENTINEL = '__cancelled__';
/** Default per-question timeout (5 minutes). */
export const DEFAULT_ASK_TIMEOUT_MS = 5 * 60 * 1000;

/**
* Per-question timeout for a flow that collects source credentials.
*
* These questions wait on a person, not on a model: opening a database
* console, finding a host and port, minting a restricted API key. The default
* above is sized for a question the user can answer from memory and expires
* long before that errand is done.
*
* Shared rather than inlined because the same credential prompts are reached
* two ways — as the orchestrator's seeded warehouse task and as the standalone
* `wizard warehouse` command the outro points declines at — and the two giving
* the user different allowances for identical questions is the bug, not a
* setting.
*/
export const CREDENTIAL_ASK_TIMEOUT_MS = 20 * 60 * 1000;

function buildCancelledAnswers(questions: AskQuestion[]): AskAnswers {
const out: AskAnswers = {};
for (const q of questions) {
Expand Down
Loading