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
2 changes: 2 additions & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ jobs:
# Upload skill-menu.json (used by the wizard to discover available skills)
echo "Uploading skill-menu.json..."
gh release upload "$RELEASE_TAG" dist/skills/skill-menu.json --clobber
# Upload the orchestrator agent prompts + menu (flat asset names)
gh release upload "$RELEASE_TAG" dist/agents/agent-menu.json dist/agents/agents-*.md --clobber
# Upload each bundled group (one JSON of every variant, in place of per-variant ZIPs)
for file in dist/skills/*.json; do
filename=$(basename "$file")
Expand Down
10 changes: 5 additions & 5 deletions scripts/dev-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const agentsDir = path.join(distDir, 'agents');
const exampleAppsDir = path.join(repoRoot, 'example-apps');

const localSkillsUrl = `http://localhost:${PORT}/skills`;
const localAgentsUrl = `http://localhost:${PORT}/agents`;
const localAgentsUrl = `http://localhost:${PORT}`;

// `generateManifest` reads SKILLS_BASE_URL from process.env, and the agent build
// reads AGENTS_BASE_URL. Partial rebuilds run in this process, so set both here —
Expand Down Expand Up @@ -301,9 +301,9 @@ function createServer() {
return;
}

const agentMatch = req.url?.match(/^\/agents\/([\w-]+)\/([\w-]+\.md)$/);
const agentMatch = req.url?.match(/^\/(agents-[\w-]+\.md)$/);
if (agentMatch) {
serveFile(res, path.join(agentsDir, agentMatch[1], agentMatch[2]), 'text/markdown; charset=utf-8');
serveFile(res, path.join(agentsDir, agentMatch[1]), 'text/markdown; charset=utf-8');
return;
}

Expand All @@ -323,7 +323,7 @@ function createServer() {
}

res.writeHead(404, { 'Content-Type': 'text/plain', ...NO_CACHE_HEADERS });
res.end('Not found. Available endpoints:\n /skill-menu.json\n /skills-mcp-resources.zip\n /skills/{id}.zip\n /skills/{group}.json\n /agent-menu.json\n /agents/{flow}/{type}.md');
res.end('Not found. Available endpoints:\n /skill-menu.json\n /skills-mcp-resources.zip\n /skills/{id}.zip\n /skills/{group}.json\n /agent-menu.json\n /agents-{flow}-{type}.md');
});

server.listen(PORT, () => {
Expand All @@ -332,7 +332,7 @@ function createServer() {
console.log(`📍 Individual skill: http://localhost:${PORT}/skills/{id}.zip`);
console.log(`📦 Bundled group: http://localhost:${PORT}/skills/{group}.json`);
console.log(`📋 Skills menu: http://localhost:${PORT}/skill-menu.json`);
console.log(`🤖 Agent prompt: http://localhost:${PORT}/agents/{flow}/{type}.md`);
console.log(`🤖 Agent prompt: http://localhost:${PORT}/agents-{flow}-{type}.md`);
console.log(`📋 Agents menu: http://localhost:${PORT}/agent-menu.json`);
});

Expand Down
19 changes: 12 additions & 7 deletions scripts/lib/agent-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@

import fs from 'fs';
import path from 'path';
import { REPO_URL } from './constants.js';

const DEFAULT_AGENTS_BASE_URL =
'https://github.com/PostHog/context-mill/releases/latest/download/agents';
/** Release assets are a flat namespace: agent prompts live at the release root, like skills. */
function defaultAgentsBaseUrl(version) {
return version && version !== 'dev'
? `${REPO_URL}/releases/download/v${version}`
: `${REPO_URL}/releases/latest/download`;
}

/**
* The agent prompts available in source: one { flow, id } per
Expand Down Expand Up @@ -74,7 +79,7 @@ function assertFlowMatches(sourcePath, flow) {
export function buildAgents({ configDir, distDir, baseUrl, version = 'dev' }) {
const agentsSourceDir = path.join(configDir, 'agents');
const agentsDistDir = path.join(distDir, 'agents');
const resolvedBase = (baseUrl || DEFAULT_AGENTS_BASE_URL).replace(/\/+$/, '');
const resolvedBase = (baseUrl || defaultAgentsBaseUrl(version)).replace(/\/+$/, '');

fs.mkdirSync(agentsDistDir, { recursive: true });

Expand All @@ -83,9 +88,9 @@ export function buildAgents({ configDir, distDir, baseUrl, version = 'dev' }) {
for (const { flow, id } of entries) {
const sourcePath = path.join(agentsSourceDir, flow, `${id}.md`);
assertFlowMatches(sourcePath, flow);
fs.mkdirSync(path.join(agentsDistDir, flow), { recursive: true });
fs.copyFileSync(sourcePath, path.join(agentsDistDir, flow, `${id}.md`));
agents.push({ id, flow, downloadUrl: `${resolvedBase}/${flow}/${id}.md` });
const assetName = `agents-${flow}-${id}.md`;
fs.copyFileSync(sourcePath, path.join(agentsDistDir, assetName));
agents.push({ id, flow, downloadUrl: `${resolvedBase}/${assetName}` });
}

const menu = { version: '1.0', buildVersion: version, agents };
Expand All @@ -95,7 +100,7 @@ export function buildAgents({ configDir, distDir, baseUrl, version = 'dev' }) {
);

// Reconcile: drop dist files and folders whose source markdown was removed.
const keep = new Set(entries.map(e => path.join(e.flow, `${e.id}.md`)));
const keep = new Set(entries.map(e => `agents-${e.flow}-${e.id}.md`));
keep.add('agent-menu.json');
const walk = dir => {
for (const dirent of fs.readdirSync(dir, { withFileTypes: true })) {
Expand Down
2 changes: 1 addition & 1 deletion scripts/lib/tests/agent-generator-flow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('buildAgents flow frontmatter', () => {
expect(count).toBe(1);
const menu = JSON.parse(readFileSync(join(distDir, 'agents', 'agent-menu.json'), 'utf8'));
expect(menu.agents).toEqual([
{ id: 'task', flow: 'my-flow', downloadUrl: 'http://x/my-flow/task.md' },
{ id: 'task', flow: 'my-flow', downloadUrl: 'http://x/agents-my-flow-task.md' },
]);
});

Expand Down
Loading