Show prompt titles immediately for new workspaces (#1567)
* Set workspace prompt titles at creation * Cover existing workspace prompt titles * Fix rewind E2E prompt selector
This commit is contained in:
@@ -132,7 +132,7 @@ interface SessionTestAccess {
|
||||
emitWorkspaceUpdatesForWorkspaceIds(...args: unknown[]): Promise<unknown>;
|
||||
applyGeneratedWorkspaceTitle(
|
||||
workspaceId: string,
|
||||
input: { title: string; branch?: string | null },
|
||||
input: { title: string; branch?: string | null; promptTitle?: string | null },
|
||||
): Promise<void>;
|
||||
emit(message: unknown): void;
|
||||
onMessage(message: unknown): void;
|
||||
@@ -791,6 +791,122 @@ test("create_agent_request keeps requested child cwd when grouped under an exist
|
||||
}
|
||||
});
|
||||
|
||||
test("create_agent_request writes the first prompt title onto an untitled existing workspace", async () => {
|
||||
const workdir = mkdtempSync(path.join(tmpdir(), "paseo-create-agent-existing-title-"));
|
||||
try {
|
||||
const cwd = path.join(workdir, "repo");
|
||||
mkdirSync(cwd, { recursive: true });
|
||||
|
||||
const logger = {
|
||||
child: () => logger,
|
||||
trace: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
const agentStorage = new AgentStorage(path.join(workdir, "agents"), asSessionLogger(logger));
|
||||
const agentManager = new AgentManager({
|
||||
clients: { codex: new CreateAgentTestClient() },
|
||||
registry: agentStorage,
|
||||
logger: asSessionLogger(logger),
|
||||
idFactory: () => "00000000-0000-4000-8000-000000000552",
|
||||
});
|
||||
const projectRegistry = new FileBackedProjectRegistry(
|
||||
path.join(workdir, "projects.json"),
|
||||
asSessionLogger(logger),
|
||||
);
|
||||
const workspaceRegistry = new FileBackedWorkspaceRegistry(
|
||||
path.join(workdir, "workspaces.json"),
|
||||
asSessionLogger(logger),
|
||||
);
|
||||
|
||||
await projectRegistry.upsert(
|
||||
createPersistedProjectRecord({
|
||||
projectId: "proj-existing",
|
||||
rootPath: cwd,
|
||||
kind: "git",
|
||||
displayName: "repo",
|
||||
createdAt: "2026-05-07T00:00:00.000Z",
|
||||
updatedAt: "2026-05-07T00:00:00.000Z",
|
||||
}),
|
||||
);
|
||||
await workspaceRegistry.upsert(
|
||||
createPersistedWorkspaceRecord({
|
||||
workspaceId: "ws-existing",
|
||||
projectId: "proj-existing",
|
||||
cwd,
|
||||
kind: "local_checkout",
|
||||
displayName: "repo",
|
||||
title: null,
|
||||
createdAt: "2026-05-07T00:00:00.000Z",
|
||||
updatedAt: "2026-05-07T00:00:00.000Z",
|
||||
}),
|
||||
);
|
||||
|
||||
const session = asTestSession(
|
||||
new Session({
|
||||
clientId: "test-client",
|
||||
appVersion: null,
|
||||
onMessage: vi.fn(),
|
||||
logger: asSessionLogger(logger),
|
||||
downloadTokenStore: asDownloadTokenStore(),
|
||||
pushTokenStore: asPushTokenStore(),
|
||||
paseoHome: path.join(workdir, "paseo-home"),
|
||||
agentManager,
|
||||
agentStorage,
|
||||
projectRegistry,
|
||||
workspaceRegistry,
|
||||
chatService: asChatService(),
|
||||
scheduleService: asScheduleService(),
|
||||
loopService: asLoopService(),
|
||||
checkoutDiffManager: asCheckoutDiffManager({
|
||||
subscribe: async () => ({
|
||||
initial: { cwd, files: [], error: null },
|
||||
unsubscribe: () => {},
|
||||
}),
|
||||
scheduleRefreshForCwd: () => {},
|
||||
onWorkspaceStateMayHaveChanged: () => {},
|
||||
getMetrics: () => ({
|
||||
checkoutDiffTargetCount: 0,
|
||||
checkoutDiffSubscriptionCount: 0,
|
||||
checkoutDiffWatcherCount: 0,
|
||||
checkoutDiffFallbackRefreshTargetCount: 0,
|
||||
}),
|
||||
dispose: () => {},
|
||||
}),
|
||||
workspaceGitService: createNoopWorkspaceGitService(),
|
||||
daemonConfigStore: asDaemonConfigStore({
|
||||
get: () => ({ mcp: { injectIntoAgents: false }, providers: {} }),
|
||||
onChange: () => () => {},
|
||||
}),
|
||||
mcpBaseUrl: null,
|
||||
stt: null,
|
||||
tts: null,
|
||||
providerSnapshotManager: createProviderSnapshotManagerStub().manager,
|
||||
terminalManager: null,
|
||||
}),
|
||||
);
|
||||
|
||||
await session.handleMessage({
|
||||
type: "create_agent_request",
|
||||
requestId: "req-create-existing-title",
|
||||
workspaceId: "ws-existing",
|
||||
config: { provider: "codex", cwd },
|
||||
initialPrompt: "Fix login bug\nwith better validation",
|
||||
attachments: [],
|
||||
});
|
||||
|
||||
const [createdAgent] = agentManager.listAgents();
|
||||
expect(createdAgent?.workspaceId).toBe("ws-existing");
|
||||
await expect(workspaceRegistry.get("ws-existing")).resolves.toMatchObject({
|
||||
title: "Fix login bug",
|
||||
});
|
||||
} finally {
|
||||
rmSync(workdir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("unsupported persisted agents are excluded from active lists but preserved in history payloads", async () => {
|
||||
const session = createSessionForWorkspaceTests({ appVersion: "0.1.45" });
|
||||
const storedRecord = {
|
||||
@@ -6266,6 +6382,46 @@ test("applyGeneratedWorkspaceTitle writes branch metadata and does not clobber c
|
||||
expect(saved?.title).toBe("User-set title");
|
||||
});
|
||||
|
||||
test("applyGeneratedWorkspaceTitle replaces the unchanged prompt title", async () => {
|
||||
const session = createSessionForWorkspaceTests();
|
||||
const workspace = createPersistedWorkspaceRecord({
|
||||
workspaceId: "ws-prompt-title",
|
||||
projectId: "proj-prompt-title",
|
||||
cwd: REPO_CWD,
|
||||
kind: "directory",
|
||||
displayName: "repo",
|
||||
title: "Fix login bug",
|
||||
createdAt: "2026-03-01T12:00:00.000Z",
|
||||
updatedAt: "2026-03-01T12:00:00.000Z",
|
||||
});
|
||||
const stored = new Map([[workspace.workspaceId, workspace]]);
|
||||
session.workspaceRegistry.get = async (id: string) => stored.get(id) ?? null;
|
||||
session.workspaceRegistry.upsert = async (record: unknown) => {
|
||||
const parsed = record as typeof workspace;
|
||||
stored.set(parsed.workspaceId, parsed);
|
||||
};
|
||||
|
||||
await session.applyGeneratedWorkspaceTitle(workspace.workspaceId, {
|
||||
title: "Generated login fix",
|
||||
promptTitle: "Fix login bug",
|
||||
});
|
||||
|
||||
expect(stored.get(workspace.workspaceId)?.title).toBe("Generated login fix");
|
||||
|
||||
stored.set(workspace.workspaceId, {
|
||||
...workspace,
|
||||
title: "User rename",
|
||||
updatedAt: "2026-03-01T12:01:00.000Z",
|
||||
});
|
||||
|
||||
await session.applyGeneratedWorkspaceTitle(workspace.workspaceId, {
|
||||
title: "Generated login fix",
|
||||
promptTitle: "Fix login bug",
|
||||
});
|
||||
|
||||
expect(stored.get(workspace.workspaceId)?.title).toBe("User rename");
|
||||
});
|
||||
|
||||
// Phase 7: branch is a git fact derived per-descriptor from each workspace's own
|
||||
// live git snapshot, and reconciliation re-persists `branch` per workspace from
|
||||
// its own cwd. handleCheckoutRenameBranchRequest renames the git branch and
|
||||
@@ -6327,3 +6483,42 @@ test("checkout.rename_branch.request renames the branch without a denormalized b
|
||||
expect(persisted?.displayName).toBe("Refactor auth flow");
|
||||
expect(persisted?.title).toBe("Refactor auth flow");
|
||||
});
|
||||
|
||||
test("workspace.create.response persists the first prompt as the initial title", async () => {
|
||||
const emitted: SessionOutboundMessage[] = [];
|
||||
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
|
||||
const session = createSessionForWorkspaceTests({
|
||||
onMessage: (message) => emitted.push(message),
|
||||
workspaceRegistry: {
|
||||
initialize: async () => {},
|
||||
existsOnDisk: async () => true,
|
||||
list: async () => Array.from(workspaces.values()),
|
||||
get: async (workspaceId: string) => workspaces.get(workspaceId) ?? null,
|
||||
upsert: async (workspace) => {
|
||||
workspaces.set(workspace.workspaceId, workspace);
|
||||
},
|
||||
archive: async () => {},
|
||||
remove: async () => {},
|
||||
},
|
||||
});
|
||||
session.listAgentPayloads = async () => [];
|
||||
|
||||
await session.handleMessage({
|
||||
type: "workspace.create.request",
|
||||
requestId: "req-create-first-prompt",
|
||||
source: { kind: "directory", path: REPO_CWD },
|
||||
firstAgentContext: {
|
||||
prompt: "Add retries to the payments flow\nwith exponential backoff",
|
||||
},
|
||||
});
|
||||
|
||||
const response = findByType(emitted, "workspace.create.response");
|
||||
expect(response?.payload.error).toBeNull();
|
||||
expect(response?.payload.workspace?.title).toBe("Add retries to the payments flow");
|
||||
expect(response?.payload.workspace?.name).toBe("Add retries to the payments flow");
|
||||
|
||||
const workspaceId = response?.payload.workspace?.id;
|
||||
expect(workspaceId).toBeDefined();
|
||||
const persisted = await session.workspaceRegistry.get(workspaceId as string);
|
||||
expect(persisted?.title).toBe("Add retries to the payments flow");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user