Skip to content

Commit 66a868e

Browse files
vibeguiclaude
andcommitted
feat(agent): add site context injection for Deco sites
AGENT_SPAWN now accepts a siteContext parameter that provides: - isDeco: whether this is a Deco site - serverUrl: dev server URL if running - pages: list of available page paths - decoImports: Deco imports from deno.json - siteType: type of site - guidelines: site-specific guidelines When siteContext.isDeco is true, the agent prompt includes: - Reference to skills/decocms-landing-pages patterns - Deco site conventions (page configs, sections, colors) - Available pages and dev server status This enables site-builder to provide context when spawning agents. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 516f65d commit 66a868e

1 file changed

Lines changed: 101 additions & 3 deletions

File tree

task-runner/server/tools/agent.ts

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,29 @@ interface QualityGate {
6161
required: boolean;
6262
}
6363

64+
interface SiteContext {
65+
/** Whether this is a Deco site */
66+
isDeco?: boolean;
67+
/** Dev server URL if running */
68+
serverUrl?: string;
69+
/** List of page paths available */
70+
pages?: string[];
71+
/** Deco imports found in deno.json */
72+
decoImports?: string[];
73+
/** Site type (e.g., "deco", "next", "unknown") */
74+
siteType?: string;
75+
/** Additional site-specific guidelines */
76+
guidelines?: string;
77+
}
78+
6479
interface TaskContext {
6580
taskId: string;
6681
taskTitle: string;
6782
taskDescription?: string;
6883
acceptanceCriteria?: AcceptanceCriterion[];
6984
qualityGates?: QualityGate[];
7085
workspace: string;
86+
siteContext?: SiteContext;
7187
}
7288

7389
/**
@@ -120,12 +136,67 @@ async function loadMemorySummary(workspace: string): Promise<string> {
120136
: "No project memory yet. Start writing discoveries to MEMORY.md";
121137
}
122138

139+
/**
140+
* Build site context section for the prompt
141+
*/
142+
function buildSiteContextSection(siteContext?: SiteContext): string {
143+
if (!siteContext) return "";
144+
145+
const sections: string[] = [];
146+
147+
if (siteContext.isDeco) {
148+
sections.push(`## Site Context (Deco Site)
149+
150+
This workspace contains a **Deco site**. Use the skills and patterns from the \`skills/\` folder.`);
151+
152+
if (siteContext.serverUrl) {
153+
sections.push(`- **Dev Server:** Running at ${siteContext.serverUrl}`);
154+
}
155+
156+
if (siteContext.pages && siteContext.pages.length > 0) {
157+
sections.push(`- **Available Pages:**
158+
${siteContext.pages.map((p) => ` - ${p}`).join("\n")}`);
159+
}
160+
161+
if (siteContext.decoImports && siteContext.decoImports.length > 0) {
162+
sections.push(
163+
`- **Deco Imports:** ${siteContext.decoImports.slice(0, 5).join(", ")}${siteContext.decoImports.length > 5 ? "..." : ""}`,
164+
);
165+
}
166+
167+
sections.push(`
168+
### Deco Site Patterns
169+
- Page configs are in \`.deco/blocks/pages-{slug}.json\`
170+
- Sections go in \`sections/{ComponentName}.tsx\`
171+
- Use the color system: dc-950 (darkest) to dc-100 (lightest), primary-light (#D0EC1A)
172+
- Always provide default props in sections
173+
- Check \`skills/decocms-landing-pages/SKILL.md\` for detailed patterns`);
174+
} else if (siteContext.siteType) {
175+
sections.push(`## Site Context
176+
177+
Site type: ${siteContext.siteType}`);
178+
}
179+
180+
if (siteContext.guidelines) {
181+
sections.push(`### Site Guidelines
182+
${siteContext.guidelines}`);
183+
}
184+
185+
return sections.join("\n\n");
186+
}
187+
123188
/**
124189
* Build the context-rich prompt for an agent
125190
*/
126191
async function buildAgentPrompt(ctx: TaskContext): Promise<string> {
127-
const { taskId, taskTitle, taskDescription, acceptanceCriteria, workspace } =
128-
ctx;
192+
const {
193+
taskId,
194+
taskTitle,
195+
taskDescription,
196+
acceptanceCriteria,
197+
workspace,
198+
siteContext,
199+
} = ctx;
129200

130201
// Load project-specific data
131202
const qualityGates = ctx.qualityGates ?? (await loadQualityGates(workspace));
@@ -238,6 +309,8 @@ This captures:
238309
239310
${memorySummary}
240311
312+
${buildSiteContextSection(siteContext)}
313+
241314
## Completion Protocol
242315
243316
When you believe the task is complete:
@@ -312,6 +385,29 @@ export const createAgentSpawnTool = (_env: Env) =>
312385
.number()
313386
.optional()
314387
.describe("Timeout in milliseconds (default: 30 minutes)"),
388+
siteContext: z
389+
.object({
390+
isDeco: z
391+
.boolean()
392+
.optional()
393+
.describe("Whether this is a Deco site"),
394+
serverUrl: z
395+
.string()
396+
.optional()
397+
.describe("Dev server URL if running"),
398+
pages: z.array(z.string()).optional().describe("List of page paths"),
399+
decoImports: z
400+
.array(z.string())
401+
.optional()
402+
.describe("Deco imports found"),
403+
siteType: z.string().optional().describe("Site type"),
404+
guidelines: z
405+
.string()
406+
.optional()
407+
.describe("Site-specific guidelines"),
408+
})
409+
.optional()
410+
.describe("Site context for Deco/web projects"),
315411
}),
316412
outputSchema: z.object({
317413
sessionId: z.string().describe("Unique session ID for this agent run"),
@@ -329,7 +425,8 @@ export const createAgentSpawnTool = (_env: Env) =>
329425
} else {
330426
workspace = getWorkspace();
331427
}
332-
const { taskId, taskTitle, taskDescription, timeout } = context;
428+
const { taskId, taskTitle, taskDescription, timeout, siteContext } =
429+
context;
333430

334431
// Clean up any stale sessions from previous runs
335432
await cleanupStaleSessions(workspace);
@@ -347,6 +444,7 @@ export const createAgentSpawnTool = (_env: Env) =>
347444
taskTitle,
348445
taskDescription,
349446
workspace,
447+
siteContext,
350448
});
351449

352450
// Create abort controller for timeout

0 commit comments

Comments
 (0)