feat(coding-agent): add experimental first-time setup flow (#5587)
Behind PI_EXPERIMENTAL=1, show a first-time setup dialog on interactive startup when the default agent directory is used and settings.json does not exist. The dialog preselects the detected terminal appearance with an explicit dark/light choice (live preview) and asks for opt-in analytics data sharing. Submitting writes settings.json, which serves as the completion marker; opting in stores a generated trackingId. Escape at any point skips out of setup.
This commit is contained in:
95
packages/coding-agent/test/first-time-setup.test.ts
Normal file
95
packages/coding-agent/test/first-time-setup.test.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { mkdtempSync, rmSync, writeFileSync } from "fs";
|
||||
import { tmpdir } from "os";
|
||||
import { join } from "path";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { shouldRunFirstTimeSetup } from "../src/cli/startup-ui.ts";
|
||||
import { ENV_AGENT_DIR } from "../src/config.ts";
|
||||
import { SettingsManager } from "../src/core/settings-manager.ts";
|
||||
|
||||
describe("shouldRunFirstTimeSetup", () => {
|
||||
const originalPiExperimental = process.env.PI_EXPERIMENTAL;
|
||||
const originalAgentDir = process.env[ENV_AGENT_DIR];
|
||||
let tempDir: string;
|
||||
let settingsPath: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tempDir = mkdtempSync(join(tmpdir(), "pi-first-time-setup-"));
|
||||
settingsPath = join(tempDir, "settings.json");
|
||||
process.env.PI_EXPERIMENTAL = "1";
|
||||
delete process.env[ENV_AGENT_DIR];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
if (originalPiExperimental === undefined) {
|
||||
delete process.env.PI_EXPERIMENTAL;
|
||||
} else {
|
||||
process.env.PI_EXPERIMENTAL = originalPiExperimental;
|
||||
}
|
||||
if (originalAgentDir === undefined) {
|
||||
delete process.env[ENV_AGENT_DIR];
|
||||
} else {
|
||||
process.env[ENV_AGENT_DIR] = originalAgentDir;
|
||||
}
|
||||
});
|
||||
|
||||
it("returns true when experimental, default agent dir, and no settings.json", () => {
|
||||
expect(shouldRunFirstTimeSetup(settingsPath)).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when experimental features are disabled", () => {
|
||||
delete process.env.PI_EXPERIMENTAL;
|
||||
|
||||
expect(shouldRunFirstTimeSetup(settingsPath)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when a custom agent dir is set", () => {
|
||||
process.env[ENV_AGENT_DIR] = tempDir;
|
||||
|
||||
expect(shouldRunFirstTimeSetup(settingsPath)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when settings.json already exists", () => {
|
||||
writeFileSync(settingsPath, "{}", "utf-8");
|
||||
|
||||
expect(shouldRunFirstTimeSetup(settingsPath)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("analytics settings", () => {
|
||||
it("defaults to disabled with no tracking identifier", () => {
|
||||
const manager = SettingsManager.inMemory();
|
||||
|
||||
expect(manager.getEnableAnalytics()).toBe(false);
|
||||
expect(manager.getTrackingId()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("generates a tracking identifier on opt-in", () => {
|
||||
const manager = SettingsManager.inMemory();
|
||||
|
||||
manager.setEnableAnalytics(true);
|
||||
|
||||
expect(manager.getEnableAnalytics()).toBe(true);
|
||||
expect(manager.getTrackingId()).toMatch(/^[0-9a-f-]{36}$/);
|
||||
});
|
||||
|
||||
it("does not generate a tracking identifier on opt-out", () => {
|
||||
const manager = SettingsManager.inMemory();
|
||||
|
||||
manager.setEnableAnalytics(false);
|
||||
|
||||
expect(manager.getEnableAnalytics()).toBe(false);
|
||||
expect(manager.getTrackingId()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps the tracking identifier when toggling analytics", () => {
|
||||
const manager = SettingsManager.inMemory();
|
||||
|
||||
manager.setEnableAnalytics(true);
|
||||
const trackingId = manager.getTrackingId();
|
||||
manager.setEnableAnalytics(false);
|
||||
manager.setEnableAnalytics(true);
|
||||
|
||||
expect(manager.getTrackingId()).toBe(trackingId);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user