Expose plain-text API documentation with agent_mode
studio CI and deployment / verify-and-deploy (push) Successful in 3m17s
wiki CI and deployment / verify-and-deploy (push) Successful in 16m44s

This commit is contained in:
2026-10-26 14:59:54 +08:00
parent b0a60ea498
commit f81aed8ce8
20 changed files with 228 additions and 5 deletions
+11
View File
@@ -0,0 +1,11 @@
import type {NextApiRequest,NextApiResponse} from 'next';
const docs:Record<string,string>={
'/studio/api/export/{slug}': '# 导出创作方案\n\n方法:GET\n路径参数:slug,创作方案的稳定标识。\n查询参数:format=markdown 返回 Markdown;其他值或省略时返回带 version:1 的方案 JSON,带附件文件名。\n示例:GET /studio/api/export/{slug}\n错误:404 方案不存在;405 方法不支持。',
'/studio/api/health': '# 创作站健康检查\n\n方法:GET, HEAD\n无业务参数。GET 返回 200 JSON:{"status":"ok","service":"prompt-studio"};HEAD 无正文。\n示例:GET /studio/api/health\n错误:405 方法不支持。',
};
export function serveApiDocumentation(req:NextApiRequest,res:NextApiResponse,path:string){
if(!['GET','HEAD'].includes(req.method||'')||typeof req.query.agent_mode!=='string'||req.query.agent_mode.toLowerCase()!=='true')return false;
if(!docs[path])return false;
res.setHeader('Content-Type','text/plain; charset=utf-8');res.setHeader('Cache-Control','no-store');res.status(200);
if(req.method==='HEAD')res.end();else res.send(docs[path]+'\n\n使用 GET 或 HEAD,在原地址加 ?agent_mode=True;已有参数时加 &agent_mode=True。值不区分大小写。动态路径可保留占位符读取说明。业务调用请移除 agent_mode。\nAPI 目录:/api?agent_mode=True\n');return true;
}
+2 -1
View File
@@ -1,3 +1,4 @@
import {serveApiDocumentation} from '../../../lib/api-documentation';
import type {NextApiRequest,NextApiResponse} from 'next';
import {ideas} from '../../../content/ideas';
export default function handler(req:NextApiRequest,res:NextApiResponse){if(req.method!=='GET')return res.status(405).end();const idea=ideas.find(i=>i.slug===req.query.slug);if(!idea)return res.status(404).end();if(req.query.format==='markdown'){res.setHeader('Content-Type','text/markdown; charset=utf-8');return res.send('# '+idea.title+'\n\n'+idea.summary+'\n\n'+idea.slides.map(s=>'## '+s.heading+'\n\n'+s.body).join('\n\n'));}res.setHeader('Content-Disposition',`attachment; filename="${idea.slug}.json"`);return res.json({version:1,...idea});}
export default function handler(req:NextApiRequest,res:NextApiResponse){if(serveApiDocumentation(req,res,'/studio/api/export/{slug}'))return;if(req.method!=='GET')return res.status(405).end();const idea=ideas.find(i=>i.slug===req.query.slug);if(!idea)return res.status(404).end();if(req.query.format==='markdown'){res.setHeader('Content-Type','text/markdown; charset=utf-8');return res.send('# '+idea.title+'\n\n'+idea.summary+'\n\n'+idea.slides.map(s=>'## '+s.heading+'\n\n'+s.body).join('\n\n'));}res.setHeader('Content-Disposition',`attachment; filename="${idea.slug}.json"`);return res.json({version:1,...idea});}
+2 -1
View File
@@ -1,2 +1,3 @@
import {serveApiDocumentation} from '../../lib/api-documentation';
import type {NextApiRequest,NextApiResponse} from "next";
export default function handler(req:NextApiRequest,res:NextApiResponse){res.setHeader("Cache-Control","no-store");if(!["GET","HEAD"].includes(req.method||""))return res.status(405).end();return req.method==="HEAD"?res.status(200).end():res.status(200).json({status:"ok",service:"prompt-studio"});}
export default function handler(req:NextApiRequest,res:NextApiResponse){if(serveApiDocumentation(req,res,'/studio/api/health'))return;res.setHeader("Cache-Control","no-store");if(!["GET","HEAD"].includes(req.method||""))return res.status(405).end();return req.method==="HEAD"?res.status(200).end():res.status(200).json({status:"ok",service:"prompt-studio"});}