Skip to content
Merged
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
22 changes: 22 additions & 0 deletions patterns/workflow-generation.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,28 @@
"browser": {
"tool": "playwright",
"requirement": "Enable Playwright CLI for browser automation"
},
"agentic-workflows": {
"tool": "agentic-workflows",
"requirement": "Enable agentic-workflows tools to create meta-workflows that analyze and optimize agentic workflows"
},
"lsp": {
"lsp": {
"typescript": {
"command": "typescript-language-server",
"args": [
"--stdio"
],
"fileExtensions": {
".ts": "typescript",
".tsx": "typescriptreact",
".js": "javascript",
".mjs": "javascript",
".cjs": "javascript"
}
}
},
"requirement": "Detect the programming languages used in the repository and targeted by the workflow, then configure matching Language Server Protocol tools and add steps to install them"
}
},
"pre_steps": {
Expand Down
26 changes: 17 additions & 9 deletions src/js/workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,16 +172,21 @@ function toolsetsFor(patterns, archetype) {
generation.default_github_toolsets || [];
}

function lspFor(patterns, archetype, engine) {
if (normalizeEngine(engine) !== 'copilot') return null;
const lsp = workflowDefinition(patterns, archetype).lsp || {};
const validLsp = {};
Object.entries(lsp).forEach(([language, config]) => {
function validLsp(lsp) {
const valid = {};
Object.entries(lsp || {}).forEach(([language, config]) => {
if (config && config.command && config.fileExtensions && Object.keys(config.fileExtensions).length) {
validLsp[language] = config;
valid[language] = config;
}
});
return Object.keys(validLsp).length ? validLsp : null;
return valid;
}

function lspFor(patterns, archetype, engine, extras) {
if (normalizeEngine(engine) !== 'copilot') return null;
const lsp = validLsp(workflowDefinition(patterns, archetype).lsp);
extras.forEach((extra) => Object.assign(lsp, validLsp(extra.lsp)));
return Object.keys(lsp).length ? lsp : null;
}

export function generateWorkflowFile(answers, patterns) {
Expand All @@ -197,7 +202,7 @@ export function generateWorkflowFile(answers, patterns) {
const safeOutputs = safeOutputsFor(answers, patterns);
const inferred = inferCapabilities(answers.archetype, patterns);
const extras = selectedExtras(answers, patterns);
const lsp = lspFor(patterns, answers.archetype, answers.engine);
const lsp = lspFor(patterns, answers.archetype, answers.engine, extras);

let timeout = archetype.timeout_minutes || 30;
const timeoutByTrigger = patterns.config_defaults && patterns.config_defaults.timeout_by_trigger;
Expand Down Expand Up @@ -239,7 +244,10 @@ export function generateWorkflowFile(answers, patterns) {
if (inferred.githubToolsets) {
frontmatter += ` github:\n toolsets: [${ toolsetsFor(patterns, answers.archetype).join(', ') }]\n`;
}
if (extras.some((extra) => extra.tool === 'cache-memory')) frontmatter += ' cache-memory:\n';
extras.forEach((extra) => {
if (extra.tool === 'cache-memory') frontmatter += ' cache-memory:\n';
if (extra.tool === 'agentic-workflows') frontmatter += ' agentic-workflows: true\n';
});
if (inferred.browser || extras.some((extra) => extra.tool === 'playwright')) {
frontmatter += ' playwright:\n mode: cli\n';
}
Expand Down
14 changes: 14 additions & 0 deletions src/wizard.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,20 @@
"description": "Enable Playwright CLI for browser automation",
"icon": "device-desktop",
"summary": "browser access"
},
{
"id": "agentic-workflows",
"label": "Analyze workflows",
"description": "Create meta-workflows that analyze and optimize agentic workflows",
"icon": "tools",
"summary": "agentic workflow analysis"
},
{
"id": "lsp",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot the LSP prompt should tell the agent to detect the programming languages used in the repo and targeted by the agentic workflow and add the steps to install the LSP tooling.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in c2ad21a. The generated LSP requirement now directs the agent to detect repository/workflow languages, configure matching language servers, and add installation steps.

"label": "Use language services",
"description": "Use language service protocol tools for symbol-aware code analysis",
"icon": "terminal",
"summary": "language service access"
}
]
},
Expand Down
4 changes: 3 additions & 1 deletion test/a11y.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,9 @@ describe('Primer iconography', () => {
expect(wizard.steps.extra.options.map((option) => option.icon)).toEqual([
'cache',
'graph',
'device-desktop'
'device-desktop',
'tools',
'terminal'
]);
});

Expand Down
6 changes: 4 additions & 2 deletions test/summary.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ describe('buildWorkflowSummary', () => {
it('summarizes optional extras separately from the selected engine', () => {
const summary = buildWorkflowSummary(answers({
engine: 'copilot',
extras: ['memory', 'charts', 'browser']
extras: ['memory', 'charts', 'browser', 'agentic-workflows', 'lsp']
}), patterns, wizardConfig);

expect(summary.extras.value).toBe('memory between runs, chart generation, and browser access');
expect(summary.extras.value).toBe(
'memory between runs, chart generation, browser access, agentic workflow analysis, and language service access'
);
expect(summary.extras.complete).toBe(true);
expect(summary.engine.value).toBe('Copilot');
});
Expand Down
24 changes: 24 additions & 0 deletions test/workflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,22 @@ describe('inferCapabilities', () => {
);
expect(md).not.toContain('lsp:\n');
});

it('adds selected agentic-workflows and LSP extras for Copilot workflows', () => {
const md = generateWorkflowFile(
answers({
extras: ['agentic-workflows', 'lsp'],
triggers: ['schedule'],
outputs: ['create-issue']
}),
patterns
);

expect(md).toContain(' agentic-workflows: true\n');
expect(md).toContain('lsp:\n typescript:\n command: typescript-language-server\n');
expect(md).toContain(' ".tsx": typescriptreact\n');
expect(md).toContain('network:\n allowed:\n - defaults\n - github\n - node\n');
});
});

describe('buildTriggerYaml', () => {
Expand Down Expand Up @@ -449,6 +465,14 @@ describe('generateAgentPrompt', () => {
expect(prompt).toContain('- Enable Playwright CLI for browser automation\n');
});

it('directs LSP workflows to detect relevant languages and install matching tooling', () => {
const prompt = generateAgentPrompt(answers({ extras: ['lsp'] }), patterns);

expect(prompt).toContain(
'- Detect the programming languages used in the repository and targeted by the workflow, then configure matching Language Server Protocol tools and add steps to install them\n'
);
});

it('includes the selected engine requirement', () => {
const prompt = generateAgentPrompt(answers({ engine: 'claude' }), patterns);
expect(prompt).toContain('- Engine: claude\n');
Expand Down
Loading