feat: Add agent preview integration with auto-teardown and simplified commands
- Add agentId label to preview containers (cw.agent-id) for tracking - Add startForAgent/stopByAgentId methods to PreviewManager - Auto-teardown: previews torn down on agent:stopped event - Conditional preview prompt injection for execute/refine/discuss agents - Agent-simplified CLI: cw preview start/stop --agent <id> - cw preview setup command with --auto mode for guided config generation - hasPreviewConfig hint on cw project register output - New tRPC procedures: startPreviewForAgent, stopPreviewByAgent
This commit is contained in:
@@ -37,9 +37,10 @@ import type {
|
||||
ProcessCrashedEvent,
|
||||
} from '../events/index.js';
|
||||
import { writeInputFiles } from './file-io.js';
|
||||
import { buildWorkspaceLayout, buildInterAgentCommunication } from './prompts/index.js';
|
||||
import { buildWorkspaceLayout, buildInterAgentCommunication, buildPreviewInstructions } from './prompts/index.js';
|
||||
import { getProvider } from './providers/registry.js';
|
||||
import { createModuleLogger } from '../logger/index.js';
|
||||
import { getProjectCloneDir } from '../git/project-clones.js';
|
||||
import { join } from 'node:path';
|
||||
import { unlink, readFile, writeFile as writeFileAsync } from 'node:fs/promises';
|
||||
import { existsSync } from 'node:fs';
|
||||
@@ -282,7 +283,15 @@ export class MultiProviderAgentManager implements AgentManager {
|
||||
// 3a. Append inter-agent communication instructions with actual agent ID
|
||||
prompt = prompt + buildInterAgentCommunication(agentId, mode);
|
||||
|
||||
// 3b. Write input files (after agent creation so we can include agentId/agentName)
|
||||
// 3b. Append preview deployment instructions if applicable
|
||||
if (['execute', 'refine', 'discuss'].includes(mode) && initiativeId) {
|
||||
const shouldInject = await this.shouldInjectPreviewInstructions(initiativeId);
|
||||
if (shouldInject) {
|
||||
prompt = prompt + buildPreviewInstructions(agentId);
|
||||
}
|
||||
}
|
||||
|
||||
// 3c. Write input files (after agent creation so we can include agentId/agentName)
|
||||
if (options.inputContext) {
|
||||
await writeInputFiles({ agentWorkdir: agentCwd, ...options.inputContext, agentId, agentName: alias });
|
||||
log.debug({ alias }, 'input files written');
|
||||
@@ -1038,6 +1047,23 @@ export class MultiProviderAgentManager implements AgentManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether preview instructions should be injected for this initiative.
|
||||
* Returns true if exactly one project linked and it has .cw-preview.yml.
|
||||
*/
|
||||
private async shouldInjectPreviewInstructions(initiativeId: string): Promise<boolean> {
|
||||
try {
|
||||
const projects = await this.projectRepository.findProjectsByInitiativeId(initiativeId);
|
||||
if (projects.length !== 1) return false;
|
||||
|
||||
const project = projects[0];
|
||||
const cloneDir = join(this.workspaceRoot, getProjectCloneDir(project.name, project.id));
|
||||
return existsSync(join(cloneDir, '.cw-preview.yml'));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert database agent record to AgentInfo.
|
||||
*/
|
||||
|
||||
@@ -14,3 +14,4 @@ export { buildRefinePrompt } from './refine.js';
|
||||
export { buildChatPrompt } from './chat.js';
|
||||
export type { ChatHistoryEntry } from './chat.js';
|
||||
export { buildWorkspaceLayout } from './workspace.js';
|
||||
export { buildPreviewInstructions } from './preview.js';
|
||||
|
||||
37
apps/server/agent/prompts/preview.ts
Normal file
37
apps/server/agent/prompts/preview.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Preview Deployment Prompt Instructions
|
||||
*
|
||||
* Conditional prompt section injected when the agent's initiative has
|
||||
* a project with `.cw-preview.yml`. Provides prefilled commands using
|
||||
* the agent's own ID so the server can resolve everything else.
|
||||
*/
|
||||
|
||||
export function buildPreviewInstructions(agentId: string): string {
|
||||
return `
|
||||
|
||||
<preview_deployments>
|
||||
This project supports preview deployments via Docker. You can spin up a running
|
||||
instance to verify your changes visually or explore the app.
|
||||
|
||||
## Start a Preview
|
||||
cw preview start --agent ${agentId}
|
||||
|
||||
Automatically uses your worktree (dev mode with hot reload). The URL is printed
|
||||
to stdout (e.g. http://abc123.localhost:9100).
|
||||
|
||||
## Check Preview Status
|
||||
cw preview list
|
||||
|
||||
## Stop a Preview
|
||||
cw preview stop --agent ${agentId}
|
||||
|
||||
## When to Use
|
||||
- After implementing a UI change, spin up a preview to verify rendering.
|
||||
- After API changes, verify the frontend still works end-to-end.
|
||||
- To explore the existing app state via Chrome DevTools or browser.
|
||||
|
||||
## When NOT to Use
|
||||
- Backend-only changes with no visual component — run tests instead.
|
||||
- If Docker is not available (the command will fail gracefully).
|
||||
</preview_deployments>`;
|
||||
}
|
||||
Reference in New Issue
Block a user